@openzeppelin/wizard-stellar 0.4.3 → 0.4.5

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 (71) hide show
  1. package/README.md +2 -2
  2. package/dist/add-pausable.d.ts +1 -1
  3. package/dist/add-pausable.d.ts.map +1 -1
  4. package/dist/add-pausable.js +10 -8
  5. package/dist/add-pausable.js.map +1 -1
  6. package/dist/add-upgradeable.d.ts +1 -1
  7. package/dist/add-upgradeable.d.ts.map +1 -1
  8. package/dist/add-upgradeable.js +2 -2
  9. package/dist/add-upgradeable.js.map +1 -1
  10. package/dist/common-options.d.ts +1 -0
  11. package/dist/common-options.d.ts.map +1 -1
  12. package/dist/common-options.js +4 -4
  13. package/dist/common-options.js.map +1 -1
  14. package/dist/contract.d.ts +2 -0
  15. package/dist/contract.d.ts.map +1 -1
  16. package/dist/contract.js +11 -7
  17. package/dist/contract.js.map +1 -1
  18. package/dist/fungible.d.ts +1 -1
  19. package/dist/fungible.d.ts.map +1 -1
  20. package/dist/fungible.js +43 -24
  21. package/dist/fungible.js.map +1 -1
  22. package/dist/generate/alternatives.js +1 -1
  23. package/dist/generate/alternatives.js.map +1 -1
  24. package/dist/generate/fungible.d.ts.map +1 -1
  25. package/dist/generate/fungible.js +1 -0
  26. package/dist/generate/fungible.js.map +1 -1
  27. package/dist/generate/non-fungible.d.ts.map +1 -1
  28. package/dist/generate/non-fungible.js +2 -0
  29. package/dist/generate/non-fungible.js.map +1 -1
  30. package/dist/generate/stablecoin.d.ts.map +1 -1
  31. package/dist/generate/stablecoin.js +1 -0
  32. package/dist/generate/stablecoin.js.map +1 -1
  33. package/dist/non-fungible.d.ts +2 -1
  34. package/dist/non-fungible.d.ts.map +1 -1
  35. package/dist/non-fungible.js +96 -45
  36. package/dist/non-fungible.js.map +1 -1
  37. package/dist/print.js +3 -6
  38. package/dist/print.js.map +1 -1
  39. package/dist/set-access-control.d.ts +2 -2
  40. package/dist/set-access-control.d.ts.map +1 -1
  41. package/dist/set-access-control.js +105 -8
  42. package/dist/set-access-control.js.map +1 -1
  43. package/dist/stablecoin.d.ts +2 -1
  44. package/dist/stablecoin.d.ts.map +1 -1
  45. package/dist/stablecoin.js +30 -10
  46. package/dist/stablecoin.js.map +1 -1
  47. package/dist/utils/compile-test.d.ts +1 -0
  48. package/dist/utils/compile-test.d.ts.map +1 -1
  49. package/dist/utils/compile-test.js +20 -6
  50. package/dist/utils/compile-test.js.map +1 -1
  51. package/dist/utils/define-functions.js +4 -7
  52. package/dist/utils/define-functions.js.map +1 -1
  53. package/dist/zip-rust.d.ts.map +1 -1
  54. package/dist/zip-rust.js +5 -1
  55. package/dist/zip-rust.js.map +1 -1
  56. package/dist/zip-shared.js +1 -1
  57. package/dist/zip-shared.js.map +1 -1
  58. package/package.json +3 -3
  59. package/src/add-pausable.ts +30 -15
  60. package/src/add-upgradeable.ts +13 -6
  61. package/src/common-options.ts +3 -0
  62. package/src/contract.ts +9 -0
  63. package/src/fungible.ts +54 -20
  64. package/src/generate/fungible.ts +1 -0
  65. package/src/generate/non-fungible.ts +2 -0
  66. package/src/generate/stablecoin.ts +1 -0
  67. package/src/non-fungible.ts +127 -41
  68. package/src/set-access-control.ts +105 -7
  69. package/src/stablecoin.ts +39 -9
  70. package/src/utils/compile-test.ts +52 -25
  71. package/src/zip-rust.ts +5 -0
package/src/contract.ts CHANGED
@@ -185,6 +185,10 @@ export class ContractBuilder implements Contract {
185
185
  }
186
186
  }
187
187
 
188
+ addTraitForEachFunctions(baseTrait: BaseTraitImplBlock, functions: Record<string, BaseFunction>) {
189
+ Object.values(functions).forEach(fn => this.addTraitFunction(baseTrait, fn));
190
+ }
191
+
188
192
  // used for adding a function to a trait implementation block
189
193
  addTraitFunction(baseTrait: BaseTraitImplBlock, fn: BaseFunction): ContractFunction {
190
194
  const t = this.addTraitImplBlock(baseTrait);
@@ -241,6 +245,11 @@ export class ContractBuilder implements Contract {
241
245
  existingFn.tags = [...(existingFn.tags ?? []), tag];
242
246
  }
243
247
 
248
+ setFunctionCode(fn: BaseFunction, code: string[], baseTrait?: BaseTraitImplBlock): void {
249
+ const existingFn = this.getOrCreateFunction(fn, baseTrait);
250
+ existingFn.code = [...code];
251
+ }
252
+
244
253
  addConstructorArgument(arg: Argument): void {
245
254
  for (const existingArg of this.constructorArgs) {
246
255
  if (existingArg.name == arg.name) {
package/src/fungible.ts CHANGED
@@ -11,6 +11,7 @@ import { OptionsError } from './error';
11
11
  import { contractDefaults as commonDefaults } from './common-options';
12
12
  import { printContract } from './print';
13
13
  import { toByteArray, toUint } from './utils/convert-strings';
14
+ import { pickKeys } from '@openzeppelin/wizard-common';
14
15
 
15
16
  export const defaults: Required<FungibleOptions> = {
16
17
  name: 'MyToken',
@@ -22,6 +23,7 @@ export const defaults: Required<FungibleOptions> = {
22
23
  mintable: false,
23
24
  access: commonDefaults.access,
24
25
  info: commonDefaults.info,
26
+ explicitImplementations: commonDefaults.explicitImplementations,
25
27
  } as const;
26
28
 
27
29
  export function printFungible(opts: FungibleOptions = defaults): string {
@@ -59,58 +61,68 @@ export function buildFungible(opts: FungibleOptions): ContractBuilder {
59
61
 
60
62
  const allOpts = withDefaults(opts);
61
63
 
62
- addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), allOpts.pausable);
64
+ addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), allOpts.pausable, allOpts.explicitImplementations);
63
65
 
64
66
  if (allOpts.premint) {
65
67
  addPremint(c, allOpts.premint);
66
68
  }
67
69
 
68
70
  if (allOpts.pausable) {
69
- addPausable(c, allOpts.access);
71
+ addPausable(c, allOpts.access, allOpts.explicitImplementations);
70
72
  }
71
73
 
72
74
  if (allOpts.upgradeable) {
73
- addUpgradeable(c, allOpts.access);
75
+ addUpgradeable(c, allOpts.access, allOpts.explicitImplementations);
74
76
  }
75
77
 
76
78
  if (allOpts.burnable) {
77
- addBurnable(c, allOpts.pausable);
79
+ addBurnable(c, allOpts.pausable, allOpts.explicitImplementations);
78
80
  }
79
81
 
80
82
  if (allOpts.mintable) {
81
- addMintable(c, allOpts.access, allOpts.pausable);
83
+ addMintable(c, allOpts.access, allOpts.pausable, allOpts.explicitImplementations);
82
84
  }
83
85
 
84
- setAccessControl(c, allOpts.access);
86
+ setAccessControl(c, allOpts.access, allOpts.explicitImplementations);
85
87
  setInfo(c, allOpts.info);
86
88
 
87
89
  return c;
88
90
  }
89
91
 
90
- function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boolean) {
92
+ function addBase(
93
+ c: ContractBuilder,
94
+ name: string,
95
+ symbol: string,
96
+ pausable: boolean,
97
+ explicitImplementations: boolean,
98
+ ) {
91
99
  // Set metadata
92
100
  c.addConstructorCode(`Base::set_metadata(e, 18, String::from_str(e, "${name}"), String::from_str(e, "${symbol}"));`);
93
101
 
94
102
  // Set token functions
95
103
  c.addUseClause('stellar_tokens::fungible', 'Base');
96
104
  c.addUseClause('stellar_tokens::fungible', 'FungibleToken');
97
- c.addUseClause('stellar_macros', 'default_impl');
105
+ if (!explicitImplementations) c.addUseClause('stellar_macros', 'default_impl');
98
106
  c.addUseClause('soroban_sdk', 'contract');
99
107
  c.addUseClause('soroban_sdk', 'contractimpl');
100
108
  c.addUseClause('soroban_sdk', 'String');
101
109
  c.addUseClause('soroban_sdk', 'Env');
110
+ if (explicitImplementations || pausable) {
111
+ c.addUseClause('soroban_sdk', 'Address');
112
+ }
102
113
 
103
114
  const fungibleTokenTrait = {
104
115
  traitName: 'FungibleToken',
105
116
  structName: c.name,
106
- tags: ['default_impl', 'contractimpl'],
117
+ tags: explicitImplementations ? ['contractimpl'] : ['default_impl', 'contractimpl'],
107
118
  assocType: 'type ContractType = Base;',
108
119
  };
109
120
 
110
121
  c.addTraitImplBlock(fungibleTokenTrait);
111
122
 
123
+ if (explicitImplementations) c.addTraitForEachFunctions(fungibleTokenTrait, fungibleTokenTraitFunctions);
124
+
112
125
  if (pausable) {
113
- c.addUseClause('soroban_sdk', 'Address');
114
126
  c.addUseClause('stellar_macros', 'when_not_paused');
115
127
 
116
128
  c.addTraitFunction(fungibleTokenTrait, functions.transfer);
@@ -121,7 +133,7 @@ function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boo
121
133
  }
122
134
  }
123
135
 
124
- function addMintable(c: ContractBuilder, access: Access, pausable: boolean) {
136
+ function addMintable(c: ContractBuilder, access: Access, pausable: boolean, explicitImplementations: boolean) {
125
137
  c.addUseClause('soroban_sdk', 'Address');
126
138
  switch (access) {
127
139
  case false:
@@ -129,7 +141,7 @@ function addMintable(c: ContractBuilder, access: Access, pausable: boolean) {
129
141
  case 'ownable': {
130
142
  c.addFreeFunction(functions.mint);
131
143
 
132
- requireAccessControl(c, undefined, functions.mint, access);
144
+ requireAccessControl(c, undefined, functions.mint, access, undefined, explicitImplementations);
133
145
 
134
146
  if (pausable) {
135
147
  c.addFunctionTag(functions.mint, 'when_not_paused');
@@ -139,11 +151,18 @@ function addMintable(c: ContractBuilder, access: Access, pausable: boolean) {
139
151
  case 'roles': {
140
152
  c.addFreeFunction(functions.mint_with_caller);
141
153
 
142
- requireAccessControl(c, undefined, functions.mint_with_caller, access, {
143
- useMacro: true,
144
- caller: 'caller',
145
- role: 'minter',
146
- });
154
+ requireAccessControl(
155
+ c,
156
+ undefined,
157
+ functions.mint_with_caller,
158
+ access,
159
+ {
160
+ useMacro: true,
161
+ caller: 'caller',
162
+ role: 'minter',
163
+ },
164
+ explicitImplementations,
165
+ );
147
166
 
148
167
  if (pausable) {
149
168
  c.addFunctionTag(functions.mint_with_caller, 'when_not_paused');
@@ -157,7 +176,7 @@ function addMintable(c: ContractBuilder, access: Access, pausable: boolean) {
157
176
  }
158
177
  }
159
178
 
160
- function addBurnable(c: ContractBuilder, pausable: boolean) {
179
+ function addBurnable(c: ContractBuilder, pausable: boolean, explicitImplementations: boolean) {
161
180
  c.addUseClause('stellar_tokens::fungible', 'burnable::FungibleBurnable');
162
181
  c.addUseClause('soroban_sdk', 'Address');
163
182
 
@@ -176,7 +195,8 @@ function addBurnable(c: ContractBuilder, pausable: boolean) {
176
195
 
177
196
  c.addTraitFunction(fungibleBurnableTrait, functions.burn_from);
178
197
  c.addFunctionTag(functions.burn_from, 'when_not_paused', fungibleBurnableTrait);
179
- } else {
198
+ } else if (explicitImplementations) c.addTraitForEachFunctions(fungibleBurnableTrait, fungibleBurnableFunctions);
199
+ else {
180
200
  // prepend '#[default_impl]'
181
201
  fungibleBurnableTrait.tags.unshift('default_impl');
182
202
  c.addTraitImplBlock(fungibleBurnableTrait);
@@ -204,7 +224,7 @@ function addPremint(c: ContractBuilder, amount: string) {
204
224
  }
205
225
 
206
226
  /**
207
- * Calculates the initial supply that would be used in an Fungible contract based on a given premint amount and number of decimals.
227
+ * Calculates the initial supply that would be used in a Fungible contract based on a given premint amount and number of decimals.
208
228
  *
209
229
  * @param premint Premint amount in token units, may be fractional
210
230
  * @param decimals The number of decimals in the token
@@ -335,3 +355,17 @@ export const functions = defineFunctions({
335
355
  code: ['Base::mint(e, &account, amount);'],
336
356
  },
337
357
  });
358
+
359
+ const fungibleTokenTraitFunctions = pickKeys(functions, [
360
+ 'total_supply',
361
+ 'balance',
362
+ 'allowance',
363
+ 'transfer',
364
+ 'transfer_from',
365
+ 'approve',
366
+ 'decimals',
367
+ 'name',
368
+ 'symbol',
369
+ ]);
370
+
371
+ const fungibleBurnableFunctions = pickKeys(functions, ['burn', 'burn_from']);
@@ -15,6 +15,7 @@ const blueprint = {
15
15
  premint: ['1'],
16
16
  access: accessOptions,
17
17
  info: infoOptions,
18
+ explicitImplementations: booleans,
18
19
  };
19
20
 
20
21
  export function* generateFungibleOptions(): Generator<Required<FungibleOptions>> {
@@ -8,6 +8,7 @@ const booleans = [true, false];
8
8
  const blueprint = {
9
9
  name: ['MyToken'],
10
10
  symbol: ['MTK'],
11
+ tokenUri: ['https://www.mytoken.com'],
11
12
  burnable: booleans,
12
13
  pausable: booleans,
13
14
  upgradeable: booleans,
@@ -17,6 +18,7 @@ const blueprint = {
17
18
  mintable: booleans,
18
19
  access: accessOptions,
19
20
  info: infoOptions,
21
+ explicitImplementations: booleans,
20
22
  };
21
23
 
22
24
  export function* generateNonFungibleOptions(): Generator<Required<NonFungibleOptions>> {
@@ -16,6 +16,7 @@ const blueprint = {
16
16
  access: accessOptions,
17
17
  limitations: limitationsOptions,
18
18
  info: infoOptions,
19
+ explicitImplementations: booleans,
19
20
  };
20
21
 
21
22
  export function* generateStablecoinOptions(): Generator<Required<StablecoinOptions>> {
@@ -1,21 +1,22 @@
1
- import type { Contract } from './contract';
2
- import { ContractBuilder } from './contract';
3
- import { type Access, requireAccessControl, setAccessControl } from './set-access-control';
1
+ import { pickKeys } from '@openzeppelin/wizard-common';
4
2
  import { addPausable } from './add-pausable';
5
3
  import { addUpgradeable } from './add-upgradeable';
6
- import { defineFunctions } from './utils/define-functions';
7
4
  import type { CommonContractOptions } from './common-options';
8
- import { withCommonContractDefaults, getSelfArg } from './common-options';
9
- import { setInfo } from './set-info';
5
+ import { contractDefaults as commonDefaults, getSelfArg, withCommonContractDefaults } from './common-options';
6
+ import type { Contract } from './contract';
7
+ import { ContractBuilder } from './contract';
10
8
  import type { OptionsErrorMessages } from './error';
11
9
  import { OptionsError } from './error';
12
- import { contractDefaults as commonDefaults } from './common-options';
13
10
  import { printContract } from './print';
11
+ import { type Access, DEFAULT_ACCESS_CONTROL, requireAccessControl, setAccessControl } from './set-access-control';
12
+ import { setInfo } from './set-info';
14
13
  import { toByteArray } from './utils/convert-strings';
14
+ import { defineFunctions } from './utils/define-functions';
15
15
 
16
16
  export const defaults: Required<NonFungibleOptions> = {
17
17
  name: 'MyToken',
18
18
  symbol: 'MTK',
19
+ tokenUri: 'https://www.mytoken.com',
19
20
  burnable: false,
20
21
  enumerable: false,
21
22
  consecutive: false,
@@ -25,6 +26,7 @@ export const defaults: Required<NonFungibleOptions> = {
25
26
  sequential: false,
26
27
  access: commonDefaults.access, // TODO: Determine whether Access Control options should be visible in the UI before they are implemented as modules
27
28
  info: commonDefaults.info,
29
+ explicitImplementations: commonDefaults.explicitImplementations,
28
30
  } as const;
29
31
 
30
32
  export function printNonFungible(opts: NonFungibleOptions = defaults): string {
@@ -34,6 +36,7 @@ export function printNonFungible(opts: NonFungibleOptions = defaults): string {
34
36
  export interface NonFungibleOptions extends CommonContractOptions {
35
37
  name: string;
36
38
  symbol: string;
39
+ tokenUri?: string;
37
40
  burnable?: boolean;
38
41
  enumerable?: boolean;
39
42
  consecutive?: boolean;
@@ -47,6 +50,7 @@ function withDefaults(opts: NonFungibleOptions): Required<NonFungibleOptions> {
47
50
  return {
48
51
  ...opts,
49
52
  ...withCommonContractDefaults(opts),
53
+ tokenUri: opts.tokenUri ?? defaults.tokenUri,
50
54
  burnable: opts.burnable ?? defaults.burnable,
51
55
  consecutive: opts.consecutive ?? defaults.consecutive,
52
56
  enumerable: opts.enumerable ?? defaults.enumerable,
@@ -87,41 +91,62 @@ export function buildNonFungible(opts: NonFungibleOptions): Contract {
87
91
  throw new OptionsError(errors);
88
92
  }
89
93
 
90
- addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), allOpts.pausable);
94
+ addBase(
95
+ c,
96
+ toByteArray(allOpts.name),
97
+ toByteArray(allOpts.symbol),
98
+ toByteArray(allOpts.tokenUri),
99
+ allOpts.pausable,
100
+ allOpts.explicitImplementations,
101
+ );
91
102
 
92
103
  if (allOpts.pausable) {
93
- addPausable(c, allOpts.access);
104
+ addPausable(c, allOpts.access, allOpts.explicitImplementations);
94
105
  }
95
106
 
96
107
  if (allOpts.upgradeable) {
97
- addUpgradeable(c, allOpts.access);
108
+ addUpgradeable(c, allOpts.access, allOpts.explicitImplementations);
98
109
  }
99
110
 
100
111
  if (allOpts.burnable) {
101
- addBurnable(c, allOpts.pausable);
112
+ addBurnable(c, allOpts.pausable, allOpts.explicitImplementations);
102
113
  }
103
114
 
104
115
  if (allOpts.enumerable) {
105
- addEnumerable(c);
116
+ addEnumerable(c, allOpts.explicitImplementations);
106
117
  }
107
118
 
108
119
  if (allOpts.consecutive) {
109
- addConsecutive(c, allOpts.pausable, allOpts.access);
120
+ addConsecutive(c, allOpts.pausable, allOpts.access, allOpts.explicitImplementations);
110
121
  }
111
122
 
112
123
  if (allOpts.mintable) {
113
- addMintable(c, allOpts.enumerable, allOpts.pausable, allOpts.sequential, allOpts.access);
124
+ addMintable(
125
+ c,
126
+ allOpts.enumerable,
127
+ allOpts.pausable,
128
+ allOpts.sequential,
129
+ allOpts.access,
130
+ allOpts.explicitImplementations,
131
+ );
114
132
  }
115
133
 
116
- setAccessControl(c, allOpts.access);
134
+ setAccessControl(c, allOpts.access, allOpts.explicitImplementations);
117
135
  setInfo(c, allOpts.info);
118
136
 
119
137
  return c;
120
138
  }
121
139
 
122
- function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boolean) {
140
+ function addBase(
141
+ c: ContractBuilder,
142
+ name: string,
143
+ symbol: string,
144
+ tokenUri: string,
145
+ pausable: boolean,
146
+ explicitImplementations: boolean,
147
+ ) {
123
148
  // Set metadata
124
- c.addConstructorCode('let uri = String::from_str(e, "www.mytoken.com");');
149
+ c.addConstructorCode(`let uri = String::from_str(e, "${tokenUri}");`);
125
150
  c.addConstructorCode(`let name = String::from_str(e, "${name}");`);
126
151
  c.addConstructorCode(`let symbol = String::from_str(e, "${symbol}");`);
127
152
  c.addConstructorCode(`Base::set_metadata(e, uri, name, symbol);`);
@@ -129,21 +154,25 @@ function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boo
129
154
  // Set token functions
130
155
  c.addUseClause('stellar_tokens::non_fungible', 'Base');
131
156
  c.addUseClause('stellar_tokens::non_fungible', 'NonFungibleToken');
132
- c.addUseClause('stellar_macros', 'default_impl');
157
+ if (explicitImplementations) c.addUseClause('stellar_tokens::non_fungible', 'ContractOverrides');
158
+ else c.addUseClause('stellar_macros', 'default_impl');
133
159
  c.addUseClause('soroban_sdk', 'contract');
134
160
  c.addUseClause('soroban_sdk', 'contractimpl');
135
161
  c.addUseClause('soroban_sdk', 'String');
136
162
  c.addUseClause('soroban_sdk', 'Env');
163
+ if (explicitImplementations || pausable) c.addUseClause('soroban_sdk', 'Address');
137
164
 
138
165
  const nonFungibleTokenTrait = {
139
166
  traitName: 'NonFungibleToken',
140
167
  structName: c.name,
141
- tags: ['default_impl', 'contractimpl'],
168
+ tags: explicitImplementations ? ['contractimpl'] : ['default_impl', 'contractimpl'],
142
169
  assocType: 'type ContractType = Base;',
143
170
  };
144
171
 
145
172
  c.addTraitImplBlock(nonFungibleTokenTrait);
146
173
 
174
+ if (explicitImplementations) c.addTraitForEachFunctions(nonFungibleTokenTrait, nonFungibleTokenTraitFunctions);
175
+
147
176
  if (pausable) {
148
177
  c.addUseClause('stellar_macros', 'when_not_paused');
149
178
 
@@ -155,7 +184,7 @@ function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boo
155
184
  }
156
185
  }
157
186
 
158
- function addBurnable(c: ContractBuilder, pausable: boolean) {
187
+ function addBurnable(c: ContractBuilder, pausable: boolean, explicitImplementations: boolean) {
159
188
  c.addUseClause('stellar_tokens::non_fungible', 'burnable::NonFungibleBurnable');
160
189
 
161
190
  const nonFungibleBurnableTrait = {
@@ -173,32 +202,38 @@ function addBurnable(c: ContractBuilder, pausable: boolean) {
173
202
 
174
203
  c.addTraitFunction(nonFungibleBurnableTrait, burnableFunctions.burn_from);
175
204
  c.addFunctionTag(burnableFunctions.burn_from, 'when_not_paused', nonFungibleBurnableTrait);
176
- } else {
205
+ } else if (explicitImplementations)
206
+ c.addTraitForEachFunctions(nonFungibleBurnableTrait, nonFungibleBurnableFunctions);
207
+ else {
177
208
  // prepend '#[default_impl]'
178
209
  nonFungibleBurnableTrait.tags.unshift('default_impl');
179
210
  c.addTraitImplBlock(nonFungibleBurnableTrait);
180
211
  }
181
212
  }
182
213
 
183
- function addEnumerable(c: ContractBuilder) {
214
+ function addEnumerable(c: ContractBuilder, explicitImplementations: boolean) {
184
215
  c.addUseClause('stellar_tokens::non_fungible', 'enumerable::{NonFungibleEnumerable, Enumerable}');
185
- c.addUseClause('stellar_macros', 'default_impl');
216
+ if (explicitImplementations) c.addUseClause('soroban_sdk', 'Address');
217
+ else c.addUseClause('stellar_macros', 'default_impl');
186
218
 
187
219
  const nonFungibleEnumerableTrait = {
188
220
  traitName: 'NonFungibleEnumerable',
189
221
  structName: c.name,
190
- tags: ['default_impl', 'contractimpl'],
222
+ tags: explicitImplementations ? ['contractimpl'] : ['default_impl', 'contractimpl'],
191
223
  section: 'Extensions',
192
224
  };
193
- c.addTraitImplBlock(nonFungibleEnumerableTrait);
225
+ if (explicitImplementations)
226
+ c.addTraitForEachFunctions(nonFungibleEnumerableTrait, nonFungibleEnumerableTraitFunctions);
227
+ else c.addTraitImplBlock(nonFungibleEnumerableTrait);
194
228
 
195
229
  c.overrideAssocType('NonFungibleToken', 'type ContractType = Enumerable;');
196
230
  }
197
231
 
198
- function addConsecutive(c: ContractBuilder, pausable: boolean, access: Access) {
232
+ function addConsecutive(c: ContractBuilder, pausable: boolean, access: Access, explicitImplementations: boolean) {
199
233
  c.addUseClause('stellar_tokens::non_fungible', 'consecutive::{NonFungibleConsecutive, Consecutive}');
200
234
  c.addUseClause('soroban_sdk', 'Address');
201
235
 
236
+ const effectiveAccess = access === false ? DEFAULT_ACCESS_CONTROL : access;
202
237
  const nonFungibleConsecutiveTrait = {
203
238
  traitName: 'NonFungibleConsecutive',
204
239
  structName: c.name,
@@ -210,45 +245,64 @@ function addConsecutive(c: ContractBuilder, pausable: boolean, access: Access) {
210
245
 
211
246
  c.overrideAssocType('NonFungibleToken', 'type ContractType = Consecutive;');
212
247
 
213
- const mintFn = access === 'ownable' ? consecutiveFunctions.batch_mint : consecutiveFunctions.batch_mint_with_caller;
248
+ const mintFn =
249
+ effectiveAccess === 'ownable' ? consecutiveFunctions.batch_mint : consecutiveFunctions.batch_mint_with_caller;
214
250
  c.addFreeFunction(mintFn);
215
251
  if (pausable) {
216
252
  c.addFunctionTag(mintFn, 'when_not_paused');
217
253
  }
218
254
 
219
- requireAccessControl(c, undefined, mintFn, access, {
220
- useMacro: true,
221
- role: 'minter',
222
- caller: 'caller',
223
- });
255
+ requireAccessControl(
256
+ c,
257
+ undefined,
258
+ mintFn,
259
+ effectiveAccess,
260
+ {
261
+ useMacro: true,
262
+ role: 'minter',
263
+ caller: 'caller',
264
+ },
265
+ explicitImplementations,
266
+ );
224
267
  }
225
268
 
226
- function addMintable(c: ContractBuilder, enumerable: boolean, pausable: boolean, sequential: boolean, access: Access) {
269
+ function addMintable(
270
+ c: ContractBuilder,
271
+ enumerable: boolean,
272
+ pausable: boolean,
273
+ sequential: boolean,
274
+ access: Access,
275
+ explicitImplementations: boolean,
276
+ ) {
227
277
  c.addUseClause('soroban_sdk', 'Address');
228
278
  const accessProps = { useMacro: true, role: 'minter', caller: 'caller' };
279
+ const effectiveAccess = access === false ? DEFAULT_ACCESS_CONTROL : access;
229
280
 
230
281
  let mintFn;
231
282
 
232
283
  if (enumerable) {
233
284
  if (sequential) {
234
285
  mintFn =
235
- access === 'ownable' ? enumerableFunctions.sequential_mint : enumerableFunctions.sequential_mint_with_caller;
286
+ effectiveAccess === 'ownable'
287
+ ? enumerableFunctions.sequential_mint
288
+ : enumerableFunctions.sequential_mint_with_caller;
236
289
  } else {
237
290
  mintFn =
238
- access === 'ownable'
291
+ effectiveAccess === 'ownable'
239
292
  ? enumerableFunctions.non_sequential_mint
240
293
  : enumerableFunctions.non_sequential_mint_with_caller;
241
294
  }
242
295
  } else {
243
296
  if (sequential) {
244
- mintFn = access === 'ownable' ? baseFunctions.sequential_mint : baseFunctions.sequential_mint_with_caller;
297
+ mintFn =
298
+ effectiveAccess === 'ownable' ? baseFunctions.sequential_mint : baseFunctions.sequential_mint_with_caller;
245
299
  } else {
246
- mintFn = access === 'ownable' ? baseFunctions.mint : baseFunctions.mint_with_caller;
300
+ mintFn = effectiveAccess === 'ownable' ? baseFunctions.mint : baseFunctions.mint_with_caller;
247
301
  }
248
302
  }
249
303
 
250
304
  c.addFreeFunction(mintFn);
251
- requireAccessControl(c, undefined, mintFn, access, accessProps);
305
+ requireAccessControl(c, undefined, mintFn, effectiveAccess, accessProps, explicitImplementations);
252
306
 
253
307
  if (pausable) {
254
308
  c.addFunctionTag(mintFn, 'when_not_paused');
@@ -358,6 +412,20 @@ const baseFunctions = defineFunctions({
358
412
  },
359
413
  });
360
414
 
415
+ const nonFungibleTokenTraitFunctions = pickKeys(baseFunctions, [
416
+ 'balance',
417
+ 'owner_of',
418
+ 'transfer',
419
+ 'transfer_from',
420
+ 'approve',
421
+ 'approve_for_all',
422
+ 'get_approved',
423
+ 'is_approved_for_all',
424
+ 'name',
425
+ 'symbol',
426
+ 'token_uri',
427
+ ]);
428
+
361
429
  const burnableFunctions = defineFunctions({
362
430
  burn: {
363
431
  args: [getSelfArg(), { name: 'from', type: 'Address' }, { name: 'token_id', type: 'u32' }],
@@ -374,11 +442,23 @@ const burnableFunctions = defineFunctions({
374
442
  },
375
443
  });
376
444
 
445
+ const nonFungibleBurnableFunctions = pickKeys(burnableFunctions, ['burn', 'burn_from']);
446
+
377
447
  const enumerableFunctions = defineFunctions({
378
448
  total_supply: {
379
449
  args: [getSelfArg()],
380
450
  returns: 'u32',
381
- code: ['non_fungible::enumerable::Enumerable::total_supply(e)'],
451
+ code: ['Enumerable::total_supply(e)'],
452
+ },
453
+ get_owner_token_id: {
454
+ args: [getSelfArg(), { name: 'owner', type: 'Address' }, { name: 'index', type: 'u32' }],
455
+ returns: 'u32',
456
+ code: ['Enumerable::get_owner_token_id(e, &owner, index)'],
457
+ },
458
+ get_token_id: {
459
+ args: [getSelfArg(), { name: 'index', type: 'u32' }],
460
+ returns: 'u32',
461
+ code: ['Enumerable::get_token_id(e, index)'],
382
462
  },
383
463
  non_sequential_mint: {
384
464
  name: 'mint',
@@ -407,12 +487,18 @@ const enumerableFunctions = defineFunctions({
407
487
  },
408
488
  });
409
489
 
490
+ const nonFungibleEnumerableTraitFunctions = pickKeys(enumerableFunctions, [
491
+ 'total_supply',
492
+ 'get_owner_token_id',
493
+ 'get_token_id',
494
+ ]);
495
+
410
496
  const consecutiveFunctions = defineFunctions({
411
497
  batch_mint: {
412
498
  name: 'batch_mint',
413
499
  args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'amount', type: 'u32' }],
414
500
  returns: 'u32',
415
- code: ['Consecutive::batch_mint(e, &to, amount);'],
501
+ code: ['Consecutive::batch_mint(e, &to, amount)'],
416
502
  },
417
503
  batch_mint_with_caller: {
418
504
  name: 'batch_mint',
@@ -423,6 +509,6 @@ const consecutiveFunctions = defineFunctions({
423
509
  { name: 'caller', type: 'Address' },
424
510
  ],
425
511
  returns: 'u32',
426
- code: ['Consecutive::batch_mint(e, &to, amount);'],
512
+ code: ['Consecutive::batch_mint(e, &to, amount)'],
427
513
  },
428
514
  });