@openzeppelin/wizard-stellar 0.2.3 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/add-pausable.d.ts.map +1 -1
  2. package/dist/add-pausable.js +29 -8
  3. package/dist/add-pausable.js.map +1 -1
  4. package/dist/add-upgradeable.d.ts.map +1 -1
  5. package/dist/add-upgradeable.js +14 -4
  6. package/dist/add-upgradeable.js.map +1 -1
  7. package/dist/api.d.ts +5 -2
  8. package/dist/api.d.ts.map +1 -1
  9. package/dist/api.js +9 -1
  10. package/dist/api.js.map +1 -1
  11. package/dist/build-generic.d.ts +5 -1
  12. package/dist/build-generic.d.ts.map +1 -1
  13. package/dist/build-generic.js +3 -0
  14. package/dist/build-generic.js.map +1 -1
  15. package/dist/contract.d.ts +1 -1
  16. package/dist/contract.d.ts.map +1 -1
  17. package/dist/contract.js +9 -1
  18. package/dist/contract.js.map +1 -1
  19. package/dist/fungible.d.ts +5 -2
  20. package/dist/fungible.d.ts.map +1 -1
  21. package/dist/fungible.js +86 -55
  22. package/dist/fungible.js.map +1 -1
  23. package/dist/generate/sources.d.ts.map +1 -1
  24. package/dist/generate/sources.js +6 -0
  25. package/dist/generate/sources.js.map +1 -1
  26. package/dist/generate/stablecoin.d.ts +3 -0
  27. package/dist/generate/stablecoin.d.ts.map +1 -0
  28. package/dist/generate/stablecoin.js +24 -0
  29. package/dist/generate/stablecoin.js.map +1 -0
  30. package/dist/index.d.ts +2 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +3 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/kind.js +1 -0
  35. package/dist/kind.js.map +1 -1
  36. package/dist/non-fungible.d.ts +1 -0
  37. package/dist/non-fungible.d.ts.map +1 -1
  38. package/dist/non-fungible.js +101 -81
  39. package/dist/non-fungible.js.map +1 -1
  40. package/dist/print.js +5 -5
  41. package/dist/print.js.map +1 -1
  42. package/dist/set-access-control.d.ts +7 -4
  43. package/dist/set-access-control.d.ts.map +1 -1
  44. package/dist/set-access-control.js +57 -15
  45. package/dist/set-access-control.js.map +1 -1
  46. package/dist/stablecoin.d.ts +11 -0
  47. package/dist/stablecoin.d.ts.map +1 -0
  48. package/dist/stablecoin.js +103 -0
  49. package/dist/stablecoin.js.map +1 -0
  50. package/dist/utils/define-functions.d.ts +4 -2
  51. package/dist/utils/define-functions.d.ts.map +1 -1
  52. package/dist/utils/define-functions.js +7 -1
  53. package/dist/utils/define-functions.js.map +1 -1
  54. package/dist/utils/version.d.ts +3 -3
  55. package/dist/utils/version.js +2 -2
  56. package/dist/zip-rust.d.ts +2 -1
  57. package/dist/zip-rust.d.ts.map +1 -1
  58. package/dist/zip-rust.js +8 -5
  59. package/dist/zip-rust.js.map +1 -1
  60. package/dist/zip-scaffold.d.ts +2 -2
  61. package/dist/zip-scaffold.d.ts.map +1 -1
  62. package/dist/zip-scaffold.js +14 -158
  63. package/dist/zip-scaffold.js.map +1 -1
  64. package/dist/zip-shared.d.ts +4 -17
  65. package/dist/zip-shared.d.ts.map +1 -1
  66. package/dist/zip-shared.js +25 -19
  67. package/dist/zip-shared.js.map +1 -1
  68. package/package.json +1 -1
  69. package/src/add-pausable.ts +31 -9
  70. package/src/add-upgradeable.ts +17 -5
  71. package/src/api.ts +27 -4
  72. package/src/build-generic.ts +6 -0
  73. package/src/contract.ts +9 -2
  74. package/src/fungible.ts +90 -61
  75. package/src/generate/sources.ts +7 -0
  76. package/src/generate/stablecoin.ts +23 -0
  77. package/src/index.ts +2 -0
  78. package/src/kind.ts +1 -0
  79. package/src/non-fungible.ts +108 -87
  80. package/src/print.ts +5 -5
  81. package/src/set-access-control.ts +72 -19
  82. package/src/stablecoin.ts +124 -0
  83. package/src/utils/define-functions.ts +11 -4
  84. package/src/utils/version.ts +2 -2
  85. package/src/zip-rust.ts +10 -6
  86. package/src/zip-scaffold.ts +15 -169
  87. package/src/zip-shared.ts +26 -22
package/src/print.ts CHANGED
@@ -248,7 +248,7 @@ function printFunction(fn: ContractFunction): Lines[] {
248
248
  }
249
249
  }
250
250
 
251
- return printFunction2(fn.pub, head, args, fn.tag, fn.returns, undefined, codeLines);
251
+ return printFunction2(fn.pub, head, args, fn.tags, fn.returns, undefined, codeLines);
252
252
  }
253
253
 
254
254
  function printContractFunctions(contract: Contract): Lines[] {
@@ -289,7 +289,7 @@ function printConstructor(contract: Contract): Lines[] {
289
289
  true,
290
290
  head,
291
291
  args.map(a => printArgument(a)),
292
- undefined,
292
+ [],
293
293
  undefined,
294
294
  undefined,
295
295
  body,
@@ -306,15 +306,15 @@ function printFunction2(
306
306
  pub: boolean | undefined,
307
307
  kindedName: string,
308
308
  args: string[],
309
- tag: string | undefined,
309
+ tags: string[],
310
310
  returns: string | undefined,
311
311
  returnLine: string | undefined,
312
312
  code: Lines[],
313
313
  ): Lines[] {
314
314
  const fn = [];
315
315
 
316
- if (tag !== undefined) {
317
- fn.push(`#[${tag}]`);
316
+ for (let i = 0; i < tags.length; i++) {
317
+ fn.push(`#[${tags[i]}]`);
318
318
  }
319
319
 
320
320
  let accum = '';
@@ -1,9 +1,14 @@
1
1
  import type { BaseFunction, BaseTraitImplBlock, ContractBuilder } from './contract';
2
2
 
3
- export const accessOptions = [false, 'ownable'] as const;
3
+ export const accessOptions = [false, 'ownable', 'roles'] as const;
4
4
  export const DEFAULT_ACCESS_CONTROL = 'ownable';
5
5
 
6
6
  export type Access = (typeof accessOptions)[number];
7
+ export type AccessProps = {
8
+ useMacro: boolean;
9
+ caller?: string;
10
+ role?: string;
11
+ };
7
12
 
8
13
  /**
9
14
  * Sets access control for the contract via constructor args.
@@ -15,14 +20,40 @@ export function setAccessControl(c: ContractBuilder, access: Access): void {
15
20
  case 'ownable': {
16
21
  if (!c.ownable) {
17
22
  c.ownable = true;
18
- c.addUseClause('soroban_sdk', 'symbol_short');
19
- c.addUseClause('soroban_sdk', 'Symbol');
20
- c.addVariable({ name: 'OWNER', type: 'Symbol', value: `symbol_short!("OWNER")` });
23
+ c.addUseClause('soroban_sdk', 'Address');
24
+ c.addUseClause('stellar_contract_utils::ownable', 'self', { alias: 'ownable' });
25
+ c.addUseClause('stellar_contract_utils::ownable', 'Ownable');
26
+
27
+ const ownableTrait = {
28
+ traitName: 'Ownable',
29
+ structName: c.name,
30
+ tags: ['default_impl', 'contractimpl'],
31
+ section: 'Utils',
32
+ };
33
+ c.addTraitImplBlock(ownableTrait);
34
+
21
35
  c.addConstructorArgument({ name: 'owner', type: 'Address' });
22
- c.addConstructorCode('e.storage().instance().set(&OWNER, &owner);');
36
+ c.addConstructorCode('ownable::set_owner(e, &owner);');
23
37
  }
24
38
  break;
25
39
  }
40
+ case 'roles': {
41
+ c.addUseClause('soroban_sdk', 'Address');
42
+ c.addUseClause('stellar_contract_utils::access_control', 'self', { alias: 'access_control' });
43
+ c.addUseClause('stellar_contract_utils::access_control', 'AccessControl');
44
+
45
+ const accessControltrait = {
46
+ traitName: 'AccessControl',
47
+ structName: c.name,
48
+ tags: ['default_impl', 'contractimpl'],
49
+ section: 'Utils',
50
+ };
51
+ c.addTraitImplBlock(accessControltrait);
52
+
53
+ c.addConstructorArgument({ name: 'admin', type: 'Address' });
54
+ c.addConstructorCode('access_control::set_admin(e, &admin);');
55
+ break;
56
+ }
26
57
  default: {
27
58
  const _: never = access;
28
59
  throw new Error('Unknown value for `access`');
@@ -32,15 +63,13 @@ export function setAccessControl(c: ContractBuilder, access: Access): void {
32
63
 
33
64
  /**
34
65
  * Enables access control for the contract and restricts the given function with access control.
35
- *
36
- * If `caller` is provided, requires that the caller is the owner. Otherwise, requires that the owner is authorized.
37
66
  */
38
67
  export function requireAccessControl(
39
68
  c: ContractBuilder,
40
69
  trait: BaseTraitImplBlock | undefined,
41
70
  fn: BaseFunction,
42
71
  access: Access,
43
- caller?: string,
72
+ accessProps: AccessProps = { useMacro: true },
44
73
  ): void {
45
74
  if (access === false) {
46
75
  access = DEFAULT_ACCESS_CONTROL;
@@ -49,19 +78,43 @@ export function requireAccessControl(
49
78
 
50
79
  switch (access) {
51
80
  case 'ownable': {
52
- c.addUseClause('soroban_sdk', 'Address');
53
- const getOwner = 'let owner: Address = e.storage().instance().get(&OWNER).expect("owner should be set");';
54
- if (caller) {
55
- c.addUseClause('soroban_sdk', 'panic_with_error');
56
- c.addError('Unauthorized', 1); // TODO: Ensure there are no conflicts in error codes
57
- c.addFunctionCodeBefore(
58
- fn,
59
- [getOwner, `if owner != ${caller} {`, ` panic_with_error!(e, ${c.name}Error::Unauthorized)`, '}'],
60
- trait,
61
- );
81
+ c.addUseClause('stellar_macros', 'only_owner');
82
+
83
+ if (accessProps.useMacro) {
84
+ c.addFunctionTag(fn, 'only_owner', trait);
62
85
  } else {
63
- c.addFunctionCodeBefore(fn, [getOwner, 'owner.require_auth();'], trait);
86
+ c.addFunctionCodeBefore(fn, [`ownable::enforce_owner_auth(e);`], trait);
64
87
  }
88
+
89
+ break;
90
+ }
91
+ case 'roles': {
92
+ const { useMacro, caller, role } = accessProps;
93
+
94
+ if (caller && role) {
95
+ c.addUseClause('soroban_sdk', 'Symbol');
96
+ c.addConstructorArgument({ name: role, type: 'Address' });
97
+ c.addConstructorCode(`access_control::grant_role_no_auth(e, &admin, &${role}, &Symbol::new(e, "${role}"));`);
98
+
99
+ if (useMacro) {
100
+ c.addUseClause('stellar_macros', 'only_role');
101
+ c.addFunctionTag(fn, `only_role(${caller}, "${role}")`, trait);
102
+ } else {
103
+ c.addFunctionCodeBefore(
104
+ fn,
105
+ [`access_control::ensure_role(e, ${caller}, &Symbol::new(e, "${role}"));`],
106
+ trait,
107
+ );
108
+ }
109
+ } else {
110
+ if (useMacro) {
111
+ c.addUseClause('stellar_macros', 'only_admin');
112
+ c.addFunctionTag(fn, 'only_admin', trait);
113
+ } else {
114
+ c.addFunctionCodeBefore(fn, ['access_control::enforce_admin_auth(e);'], trait);
115
+ }
116
+ }
117
+
65
118
  break;
66
119
  }
67
120
  default: {
@@ -0,0 +1,124 @@
1
+ import type { Contract, ContractBuilder } from './contract';
2
+ import { defineFunctions } from './utils/define-functions';
3
+ import { getSelfArg } from './common-options';
4
+ import { printContract } from './print';
5
+ import type { FungibleOptions } from './fungible';
6
+ import {
7
+ buildFungible,
8
+ defaults as fungibleDefaults,
9
+ withDefaults as withFungibleDefaults,
10
+ functions as fungibleFunctions,
11
+ isAccessControlRequired as fungibleIsAccessControlRequired,
12
+ } from './fungible';
13
+ import { requireAccessControl, type Access } from './set-access-control';
14
+
15
+ export const defaults: Required<StablecoinOptions> = {
16
+ ...fungibleDefaults,
17
+ name: 'MyStablecoin',
18
+ symbol: 'MST',
19
+ limitations: false,
20
+ } as const;
21
+
22
+ export const limitationsOptions = [false, 'allowlist', 'blocklist'] as const;
23
+
24
+ export function printStablecoin(opts: StablecoinOptions = defaults): string {
25
+ return printContract(buildStablecoin(opts));
26
+ }
27
+
28
+ export interface StablecoinOptions extends FungibleOptions {
29
+ limitations?: false | 'allowlist' | 'blocklist';
30
+ }
31
+
32
+ function withDefaults(opts: StablecoinOptions): Required<StablecoinOptions> {
33
+ return {
34
+ ...withFungibleDefaults(opts),
35
+ name: opts.name ?? defaults.name,
36
+ symbol: opts.symbol ?? defaults.symbol,
37
+ limitations: opts.limitations ?? defaults.limitations,
38
+ };
39
+ }
40
+
41
+ export function isAccessControlRequired(opts: Partial<StablecoinOptions>): boolean {
42
+ return fungibleIsAccessControlRequired(opts) || opts.limitations !== false;
43
+ }
44
+
45
+ export function buildStablecoin(opts: StablecoinOptions): Contract {
46
+ const allOpts = withDefaults(opts);
47
+
48
+ const c = buildFungible(allOpts);
49
+
50
+ if (allOpts.limitations) {
51
+ addLimitations(c, allOpts.access, allOpts.limitations);
52
+ }
53
+
54
+ return c;
55
+ }
56
+
57
+ function addLimitations(c: ContractBuilder, access: Access, mode: 'allowlist' | 'blocklist') {
58
+ const type = mode === 'allowlist';
59
+
60
+ const limitationsTrait = {
61
+ traitName: type ? 'FungibleAllowList' : 'FungibleBlockList',
62
+ structName: c.name,
63
+ tags: ['contractimpl'],
64
+ section: 'Extensions',
65
+ };
66
+
67
+ if (type) {
68
+ c.addUseClause('stellar_tokens::fungible', 'allowlist::{AllowList, FungibleAllowList}');
69
+ c.overrideAssocType('FungibleToken', 'type ContractType = AllowList;');
70
+ } else {
71
+ c.addUseClause('stellar_tokens::fungible', 'blocklist::{BlockList, FungibleBlockList}');
72
+ c.overrideAssocType('FungibleToken', 'type ContractType = BlockList;');
73
+ }
74
+
75
+ const [getterFn, addFn, removeFn] = type
76
+ ? [functions.allowed, functions.allow_user, functions.disallow_user]
77
+ : [functions.blocked, functions.block_user, functions.unblock_user];
78
+
79
+ c.addTraitFunction(limitationsTrait, getterFn);
80
+
81
+ const accessProps = {
82
+ useMacro: true,
83
+ role: 'manager',
84
+ caller: 'operator',
85
+ };
86
+
87
+ c.addTraitFunction(limitationsTrait, addFn);
88
+ requireAccessControl(c, limitationsTrait, addFn, access, accessProps);
89
+
90
+ c.addTraitFunction(limitationsTrait, removeFn);
91
+ requireAccessControl(c, limitationsTrait, removeFn, access, accessProps);
92
+ }
93
+
94
+ const functions = {
95
+ ...fungibleFunctions,
96
+ ...defineFunctions({
97
+ allowed: {
98
+ args: [getSelfArg(), { name: 'account', type: 'Address' }],
99
+ returns: 'bool',
100
+ code: ['AllowList::allowed(e, &account)'],
101
+ },
102
+ allow_user: {
103
+ args: [getSelfArg(), { name: 'user', type: 'Address' }, { name: 'operator', type: 'Address' }],
104
+ code: ['AllowList::allow_user(e, &user)'],
105
+ },
106
+ disallow_user: {
107
+ args: [getSelfArg(), { name: 'user', type: 'Address' }, { name: 'operator', type: 'Address' }],
108
+ code: ['AllowList::disallow_user(e, &user)'],
109
+ },
110
+ blocked: {
111
+ args: [getSelfArg(), { name: 'account', type: 'Address' }],
112
+ returns: 'bool',
113
+ code: ['BlockList::blocked(e, &account)'],
114
+ },
115
+ block_user: {
116
+ args: [getSelfArg(), { name: 'user', type: 'Address' }, { name: 'operator', type: 'Address' }],
117
+ code: ['BlockList::block_user(e, &user)'],
118
+ },
119
+ unblock_user: {
120
+ args: [getSelfArg(), { name: 'user', type: 'Address' }, { name: 'operator', type: 'Address' }],
121
+ code: ['BlockList::unblock_user(e, &user)'],
122
+ },
123
+ }),
124
+ };
@@ -1,9 +1,16 @@
1
1
  import type { BaseFunction } from '../contract';
2
2
 
3
- type ImplicitNameFunction = Omit<BaseFunction, 'name'>;
3
+ type OverridableImplicitNameFunction = Omit<BaseFunction, 'name'> & { name?: string };
4
4
 
5
- export function defineFunctions<F extends string>(fns: Record<F, ImplicitNameFunction>): Record<F, BaseFunction>;
5
+ export function defineFunctions<F extends string>(
6
+ fns: Record<F, OverridableImplicitNameFunction>,
7
+ ): Record<F, BaseFunction>;
6
8
 
7
- export function defineFunctions(fns: Record<string, ImplicitNameFunction>): Record<string, BaseFunction> {
8
- return Object.fromEntries(Object.entries(fns).map(([name, fn]) => [name, Object.assign({ name }, fn)]));
9
+ export function defineFunctions(fns: Record<string, OverridableImplicitNameFunction>): Record<string, BaseFunction> {
10
+ return Object.fromEntries(
11
+ Object.entries(fns).map(([implicitName, fn]) => [
12
+ implicitName,
13
+ Object.assign({ name: fn.name ?? implicitName }, fn),
14
+ ]),
15
+ );
9
16
  }
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * The actual latest version to use in links.
3
3
  */
4
- export const contractsVersion = '0.2.0';
4
+ export const contractsVersion = '0.4.1';
5
5
  export const contractsVersionTag = `v${contractsVersion}`;
6
6
 
7
7
  /**
8
8
  * Semantic version string representing of the minimum compatible version of Contracts to display in output.
9
9
  */
10
- export const compatibleContractsSemver = '^0.2.0';
10
+ export const compatibleContractsSemver = '^0.4.1';
11
11
 
12
12
  /**
13
13
  * The Soroban version for which compilation and testing have passing tests
package/src/zip-rust.ts CHANGED
@@ -4,13 +4,13 @@ import type { Contract } from './contract';
4
4
  import { printContract, removeCreateLevelAttributes } from './print';
5
5
  import {
6
6
  addDependenciesWith,
7
- allStellarDependencies,
7
+ libDependencies,
8
8
  contractOptionsToContractName,
9
9
  createRustLibFile,
10
10
  printContractCargo,
11
11
  printRustNameTest,
12
12
  } from './zip-shared';
13
- import { contractsVersionTag, compatibleSorobanVersion } from './utils/version';
13
+ import { contractsVersion, compatibleSorobanVersion } from './utils/version';
14
14
 
15
15
  const workspaceCargo = `[workspace]
16
16
  resolver = "2"
@@ -23,7 +23,7 @@ license = "Apache-2.0"
23
23
  version = "0.0.1"
24
24
 
25
25
  [workspace.dependencies]
26
- ${addDependenciesWith(`{ git = "https://github.com/OpenZeppelin/stellar-contracts", tag = "${contractsVersionTag}" }`, allStellarDependencies)}${addDependenciesWith(`{ version = "${compatibleSorobanVersion}" }`, ['soroban'])}
26
+ ${addDependenciesWith(`"${compatibleSorobanVersion}"`, ['soroban-sdk'])}${addDependenciesWith(`"=${contractsVersion}"`, [...libDependencies])}
27
27
  `;
28
28
 
29
29
  const readme = `\
@@ -41,7 +41,7 @@ Continue your development journey with [Stellar CLI](https://github.com/stellar/
41
41
  - See [Git installation guide](https://github.com/git-guides/install-git).
42
42
  `;
43
43
 
44
- export async function zipRust(c: Contract, opts: GenericOptions) {
44
+ export const createRustZipEnvironment = (c: Contract, opts: GenericOptions) => {
45
45
  const zip = new JSZip();
46
46
 
47
47
  const contractName = contractOptionsToContractName(opts?.kind || 'contract');
@@ -51,7 +51,11 @@ export async function zipRust(c: Contract, opts: GenericOptions) {
51
51
  zip.file(`contracts/${contractName}/src/lib.rs`, createRustLibFile);
52
52
  zip.file(`contracts/${contractName}/Cargo.toml`, printContractCargo(contractName));
53
53
  zip.file('Cargo.toml', workspaceCargo);
54
- zip.file('README.md', readme);
55
54
 
56
55
  return zip;
57
- }
56
+ };
57
+
58
+ const addRustProjectReadme = (zip: JSZip) => zip.file('README.md', readme);
59
+
60
+ export const zipRustProject = async (c: Contract, opts: GenericOptions) =>
61
+ addRustProjectReadme(createRustZipEnvironment(c, opts));
@@ -1,138 +1,14 @@
1
- import JSZip from 'jszip';
1
+ import type JSZip from 'jszip';
2
2
  import type { GenericOptions } from './build-generic';
3
3
  import type { Contract } from './contract';
4
- import { printContract, removeCreateLevelAttributes } from './print';
5
- import { compatibleSorobanVersion, contractsVersionTag } from './utils/version';
6
- import {
7
- addDependenciesWith,
8
- allStellarDependencies,
9
- contractOptionsToContractName,
10
- createRustLibFile,
11
- printContractCargo,
12
- printRustNameTest,
13
- } from './zip-shared';
4
+ import { createRustZipEnvironment } from './zip-rust';
14
5
 
15
- function getAddressArgs(c: Contract): string[] {
16
- return c.constructorArgs
17
- .filter(constructorArg => constructorArg.type?.toLowerCase() === 'address')
18
- .map(constructorArg => constructorArg.name);
19
- }
20
-
21
- const setupSh = (c: Contract, opts: GenericOptions, scaffoldContractName: string) => {
22
- const environmentsFileUpdate = (setUpContract: Contract, setUpScaffoldContractName: string) => `
23
- # Update environments.toml: remove original contracts and insert wizard's contract
24
- setup_environment() {
25
- local file="environments.toml"
26
- local temp
27
- temp="$(mktemp)"
28
-
29
- local in_dev_contracts=0
30
- local skip_entry=0
31
- local contract_entry_inserted=0
32
- insert_contract_entry() {
33
- {
34
- printf '%s\\n' "[development.contracts.${setUpScaffoldContractName}_contract]" \\
35
- "client = true" "" \\
36
- "# If your contract has a \\\`__constructor\\\`, specify your arguments to it here." \\
37
- "# These are the same arguments you could pass after the \\\`--\\\` in a call to" \\
38
- "# \\\`stellar contract deploy\\\`" \\
39
- "# Only available in \\\`development\\\` and \\\`test\\\` environments" \\
40
- ${
41
- setUpContract.constructorArgs.length
42
- ? // Mind the spacing
43
- `"# TODO add appropriate values for for the constructors arguments" \\
44
- "constructor_args = \\"\\"\\"" \\
45
- "${setUpContract.constructorArgs.map(constructorArg => `--${constructorArg.name} \\"ADD_${constructorArg.name.toLocaleUpperCase()}_${constructorArg.type?.toLocaleUpperCase() || 'ARGUMENT'}_HERE\\"`).join(' ')}" \\
46
- "\\"\\"\\"" \\
47
- ""`
48
- : '""'
49
- }
50
- } >> "$temp"
51
- }
52
-
53
- while IFS= read -r line; do
54
- if [[ $contract_entry_inserted -eq 0 && $line == '[staging.network]' ]]; then
55
- insert_contract_entry
56
- contract_entry_inserted=1
57
- fi
58
-
59
- if [[ $line =~ ^\\[development\\.contracts\\]$ ]]; then
60
- printf '%s\\n' "$line" >> "$temp"
61
- in_dev_contracts=1
62
- skip_entry=0
63
- continue
64
- fi
65
-
66
- if [[ $line =~ ^\\[[^]]+\\]$ ]]; then
67
- if (( in_dev_contracts )) && [[ $line =~ ^\\[development\\.contracts\\..+\\]$ ]]; then
68
- skip_entry=1
69
- in_dev_contracts=0
70
- continue
71
- fi
72
- in_dev_contracts=0
73
- skip_entry=0
74
- printf '%s\\n' "$line" >> "$temp"
75
- continue
76
- fi
77
-
78
- if (( skip_entry )); then
79
- continue
80
- fi
81
-
82
- if (( in_dev_contracts )); then
83
- if [[ $line =~ ^[[:space:]]*# ]]; then
84
- printf '%s\\n' "$line" >> "$temp"
85
- fi
86
- continue
87
- fi
88
-
89
- printf '%s\\n' "$line" >> "$temp"
90
- done < "$file"
91
-
92
- mv "$temp" "$file"
93
- }
94
- `;
95
-
96
- const updateWorkspaceCargo = `update_cargo() {
97
- cp Cargo.toml Cargo.toml.bak
98
-
99
- cat <<EOF > deps.tmp
100
- ${addDependenciesWith(`{ git = "https://github.com/OpenZeppelin/stellar-contracts", tag = "${contractsVersionTag}" }`, allStellarDependencies)}${addDependenciesWith(`{ version = "${compatibleSorobanVersion}" }`, ['soroban'])}
101
- EOF
102
-
103
- awk '
104
- BEGIN {
105
- inserted = 0
106
- deps = ""
107
- while ((getline line < "deps.tmp") > 0) {
108
- deps = deps line "\\n"
109
- }
110
- close("deps.tmp")
111
- }
112
- /^\\[workspace.dependencies\\]/ {
113
- in_deps = 1
114
- print
115
- if (!inserted) {
116
- printf "%s", deps
117
- inserted = 1
118
- }
119
- next
120
- }
121
- /^\\[/ { in_deps = 0 }
122
- in_deps { next }
123
- { print }
124
- ' Cargo.toml.bak > Cargo.toml
125
-
126
- rm deps.tmp
127
- rm Cargo.toml.bak
128
- }`;
129
-
130
- return `\
6
+ const setupSh = `\
131
7
  #!/usr/bin/env bash
132
8
  #
133
9
  # setup.sh
134
- #
135
- # This script is meant to set up a Scaffold project and insert the Wizard's contracts in the project
10
+ #
11
+ # This script is meant to set up a Scaffold project with the Wizard's contracts
136
12
 
137
13
  check_is_installed() {
138
14
  if ! which "$1" &> /dev/null; then
@@ -143,18 +19,7 @@ check_is_installed() {
143
19
  }
144
20
 
145
21
  scaffold() {
146
- tmp_folder="tmp"
147
- stellar scaffold init "$tmp_folder"
148
-
149
- rm -rf "$tmp_folder/contracts"
150
-
151
- local current_directory
152
- current_directory="$(cd "$(dirname "\${BASH_SOURCE[0]}")" && pwd)"
153
-
154
- shopt -s dotglob
155
-
156
- cp -a "$current_directory/$tmp_folder"/. "$current_directory"/
157
- rm -rf "$current_directory/$tmp_folder"
22
+ stellar-scaffold upgrade
158
23
  }
159
24
 
160
25
  init_git(){
@@ -163,10 +28,6 @@ init_git(){
163
28
  git commit -m "openzeppelin: add wizard output" --quiet
164
29
  }
165
30
 
166
- ${environmentsFileUpdate(c, scaffoldContractName)}
167
-
168
- ${updateWorkspaceCargo}
169
-
170
31
  build_contracts() {
171
32
  cargo build
172
33
  }
@@ -196,10 +57,6 @@ then
196
57
  echo "🏗️ Building Scaffold project"
197
58
 
198
59
  scaffold
199
-
200
- setup_environment
201
-
202
- update_cargo
203
60
 
204
61
  build_contracts
205
62
 
@@ -212,15 +69,11 @@ else
212
69
  echo "✅ Scaffold project already initialized."
213
70
  fi
214
71
  `;
215
- };
216
-
217
- const readme = (c: Contract) => {
218
- const hasTodosToResolve = (c: Contract) => getAddressArgs(c).length > 0;
219
72
 
220
- return `\
73
+ const wizardReadme = `\
221
74
  # Sample Scaffold Project
222
75
 
223
- This project demonstrates a basic Scaffold use case. It comes with a contract generated by [OpenZeppelin Wizard](https://wizard.openzeppelin.com/), a test for that contract, and a script that initiate a Stellar Scaffold project with this contract. [Scaffold Stellar](https://github.com/AhaLabs/scaffold-stellar?tab=readme-ov-file#scaffold-stellar) is a convention-over-configuration toolkit for blockchain and distributed application development on the Stellar network. It provides a seamless development experience through CLI tools, smart contract management, and deployment utilities.
76
+ This project demonstrates a basic Scaffold use case. It comes with a contract generated by [OpenZeppelin Wizard](https://wizard.openzeppelin.com/), a test for that contract, and a script that initiates a Stellar Scaffold project with this contract. [Scaffold Stellar](https://github.com/AhaLabs/scaffold-stellar?tab=readme-ov-file#scaffold-stellar) is a convention-over-configuration toolkit for blockchain and distributed application development on the Stellar network. It provides a seamless development experience through CLI tools, smart contract management, and deployment utilities.
224
77
 
225
78
  ## Installing dependencies
226
79
 
@@ -235,7 +88,6 @@ This project demonstrates a basic Scaffold use case. It comes with a contract ge
235
88
  \`\`\`
236
89
  bash setup.sh
237
90
  \`\`\`
238
- ${hasTodosToResolve(c) ? '\n## Resolve any TODOs \n\nSearch for any TODO comments in the project and resolve them (search for TODO with your code editor).\n' : ''}
239
91
 
240
92
  ## Testing the contract
241
93
 
@@ -255,19 +107,13 @@ stellar scaffold watch --build-clients
255
107
  npm run dev
256
108
  \`\`\`
257
109
  `;
258
- };
259
-
260
- export async function zipScaffold(c: Contract, opts: GenericOptions) {
261
- const zip = new JSZip();
262
110
 
263
- const scaffoldContractName = contractOptionsToContractName(opts?.kind || 'contract');
264
-
265
- zip.file(`contracts/${scaffoldContractName}/src/contract.rs`, removeCreateLevelAttributes(printContract(c)));
266
- zip.file(`contracts/${scaffoldContractName}/src/test.rs`, printRustNameTest(c));
267
- zip.file(`contracts/${scaffoldContractName}/src/lib.rs`, createRustLibFile);
268
- zip.file(`contracts/${scaffoldContractName}/Cargo.toml`, printContractCargo(scaffoldContractName));
269
- zip.file('setup.sh', setupSh(c, opts, scaffoldContractName));
270
- zip.file('README-WIZARD.md', readme(c));
111
+ const addScaffoldProjectFiles = (zip: JSZip) => {
112
+ zip.file('README-WIZARD.md', wizardReadme);
113
+ zip.file('setup.sh', setupSh);
271
114
 
272
115
  return zip;
273
- }
116
+ };
117
+
118
+ export const zipScaffoldProject = async (c: Contract, opts: GenericOptions) =>
119
+ addScaffoldProjectFiles(createRustZipEnvironment(c, opts));