@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/fungible.ts CHANGED
@@ -1,4 +1,3 @@
1
- import type { Contract } from './contract';
2
1
  import { ContractBuilder } from './contract';
3
2
  import type { Access } from './set-access-control';
4
3
  import { requireAccessControl, setAccessControl } from './set-access-control';
@@ -21,7 +20,7 @@ export const defaults: Required<FungibleOptions> = {
21
20
  upgradeable: false,
22
21
  premint: '0',
23
22
  mintable: false,
24
- access: commonDefaults.access, // TODO: Determine whether Access Control options should be visible in the UI before they are implemented as modules
23
+ access: commonDefaults.access,
25
24
  info: commonDefaults.info,
26
25
  } as const;
27
26
 
@@ -39,7 +38,7 @@ export interface FungibleOptions extends CommonContractOptions {
39
38
  mintable?: boolean;
40
39
  }
41
40
 
42
- function withDefaults(opts: FungibleOptions): Required<FungibleOptions> {
41
+ export function withDefaults(opts: FungibleOptions): Required<FungibleOptions> {
43
42
  return {
44
43
  ...opts,
45
44
  ...withCommonContractDefaults(opts),
@@ -51,7 +50,11 @@ function withDefaults(opts: FungibleOptions): Required<FungibleOptions> {
51
50
  };
52
51
  }
53
52
 
54
- export function buildFungible(opts: FungibleOptions): Contract {
53
+ export function isAccessControlRequired(opts: Partial<FungibleOptions>): boolean {
54
+ return opts.mintable === true || opts.pausable === true || opts.upgradeable === true;
55
+ }
56
+
57
+ export function buildFungible(opts: FungibleOptions): ContractBuilder {
55
58
  const c = new ContractBuilder(opts.name);
56
59
 
57
60
  const allOpts = withDefaults(opts);
@@ -86,45 +89,76 @@ export function buildFungible(opts: FungibleOptions): Contract {
86
89
 
87
90
  function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boolean) {
88
91
  // Set metadata
89
- c.addConstructorCode(
90
- `fungible::metadata::set_metadata(e, 18, String::from_str(e, "${name}"), String::from_str(e, "${symbol}"));`,
91
- );
92
+ c.addConstructorCode(`Base::set_metadata(e, 18, String::from_str(e, "${name}"), String::from_str(e, "${symbol}"));`);
92
93
 
93
94
  // Set token functions
94
- c.addUseClause('stellar_fungible', 'self', { alias: 'fungible' });
95
- c.addUseClause('stellar_fungible', 'FungibleToken');
95
+ c.addUseClause('stellar_tokens::fungible', 'Base');
96
+ c.addUseClause('stellar_tokens::fungible', 'FungibleToken');
97
+ c.addUseClause('stellar_macros', 'default_impl');
96
98
  c.addUseClause('soroban_sdk', 'contract');
97
99
  c.addUseClause('soroban_sdk', 'contractimpl');
98
- c.addUseClause('soroban_sdk', 'Address');
99
100
  c.addUseClause('soroban_sdk', 'String');
100
101
  c.addUseClause('soroban_sdk', 'Env');
101
- c.addUseClause('soroban_sdk', 'Symbol');
102
102
 
103
103
  const fungibleTokenTrait = {
104
104
  traitName: 'FungibleToken',
105
105
  structName: c.name,
106
- tags: ['contractimpl'],
106
+ tags: ['default_impl', 'contractimpl'],
107
+ assocType: 'type ContractType = Base;',
107
108
  };
108
109
 
109
- c.addTraitFunction(fungibleTokenTrait, functions.total_supply);
110
- c.addTraitFunction(fungibleTokenTrait, functions.balance);
111
- c.addTraitFunction(fungibleTokenTrait, functions.allowance);
112
- c.addTraitFunction(fungibleTokenTrait, functions.transfer);
113
- c.addTraitFunction(fungibleTokenTrait, functions.transfer_from);
114
- c.addTraitFunction(fungibleTokenTrait, functions.approve);
115
- c.addTraitFunction(fungibleTokenTrait, functions.decimals);
116
- c.addTraitFunction(fungibleTokenTrait, functions.name);
117
- c.addTraitFunction(fungibleTokenTrait, functions.symbol);
110
+ c.addTraitImplBlock(fungibleTokenTrait);
118
111
 
119
112
  if (pausable) {
120
- c.addUseClause('stellar_pausable_macros', 'when_not_paused');
113
+ c.addUseClause('soroban_sdk', 'Address');
114
+ c.addUseClause('stellar_macros', 'when_not_paused');
115
+
116
+ c.addTraitFunction(fungibleTokenTrait, functions.transfer);
121
117
  c.addFunctionTag(functions.transfer, 'when_not_paused', fungibleTokenTrait);
118
+
119
+ c.addTraitFunction(fungibleTokenTrait, functions.transfer_from);
122
120
  c.addFunctionTag(functions.transfer_from, 'when_not_paused', fungibleTokenTrait);
123
121
  }
124
122
  }
125
123
 
124
+ function addMintable(c: ContractBuilder, access: Access, pausable: boolean) {
125
+ c.addUseClause('soroban_sdk', 'Address');
126
+ switch (access) {
127
+ case false:
128
+ break;
129
+ case 'ownable': {
130
+ c.addFreeFunction(functions.mint);
131
+
132
+ requireAccessControl(c, undefined, functions.mint, access);
133
+
134
+ if (pausable) {
135
+ c.addFunctionTag(functions.mint, 'when_not_paused');
136
+ }
137
+ break;
138
+ }
139
+ case 'roles': {
140
+ c.addFreeFunction(functions.mint_with_caller);
141
+
142
+ requireAccessControl(c, undefined, functions.mint_with_caller, access, {
143
+ useMacro: true,
144
+ caller: 'caller',
145
+ role: 'minter',
146
+ });
147
+
148
+ if (pausable) {
149
+ c.addFunctionTag(functions.mint_with_caller, 'when_not_paused');
150
+ }
151
+ break;
152
+ }
153
+ default: {
154
+ const _: never = access;
155
+ throw new Error('Unknown value for `access`');
156
+ }
157
+ }
158
+ }
159
+
126
160
  function addBurnable(c: ContractBuilder, pausable: boolean) {
127
- c.addUseClause('stellar_fungible', 'burnable::FungibleBurnable');
161
+ c.addUseClause('stellar_tokens::fungible', 'burnable::FungibleBurnable');
128
162
  c.addUseClause('soroban_sdk', 'Address');
129
163
 
130
164
  const fungibleBurnableTrait = {
@@ -134,13 +168,18 @@ function addBurnable(c: ContractBuilder, pausable: boolean) {
134
168
  section: 'Extensions',
135
169
  };
136
170
 
137
- c.addTraitFunction(fungibleBurnableTrait, functions.burn);
138
- c.addTraitFunction(fungibleBurnableTrait, functions.burn_from);
139
-
140
171
  if (pausable) {
141
- c.addUseClause('stellar_pausable_macros', 'when_not_paused');
172
+ c.addUseClause('stellar_macros', 'when_not_paused');
173
+
174
+ c.addTraitFunction(fungibleBurnableTrait, functions.burn);
142
175
  c.addFunctionTag(functions.burn, 'when_not_paused', fungibleBurnableTrait);
176
+
177
+ c.addTraitFunction(fungibleBurnableTrait, functions.burn_from);
143
178
  c.addFunctionTag(functions.burn_from, 'when_not_paused', fungibleBurnableTrait);
179
+ } else {
180
+ // prepend '#[default_impl]'
181
+ fungibleBurnableTrait.tags.unshift('default_impl');
182
+ c.addTraitImplBlock(fungibleBurnableTrait);
144
183
  }
145
184
  }
146
185
 
@@ -157,11 +196,10 @@ function addPremint(c: ContractBuilder, amount: string) {
157
196
  // TODO: handle signed int?
158
197
  const premintAbsolute = toUint(getInitialSupply(amount, 18), 'premint', 'u128');
159
198
 
160
- c.addUseClause('stellar_fungible', 'mintable::FungibleMintable');
161
199
  c.addUseClause('soroban_sdk', 'Address');
162
200
 
163
201
  c.addConstructorArgument({ name: 'recipient', type: 'Address' });
164
- c.addConstructorCode(`fungible::mintable::mint(e, &recipient, ${premintAbsolute});`);
202
+ c.addConstructorCode(`Base::mint(e, &recipient, ${premintAbsolute});`);
165
203
  }
166
204
  }
167
205
 
@@ -206,41 +244,22 @@ export function getInitialSupply(premint: string, decimals: number): string {
206
244
  return result;
207
245
  }
208
246
 
209
- function addMintable(c: ContractBuilder, access: Access, pausable: boolean) {
210
- c.addUseClause('stellar_fungible', 'mintable::FungibleMintable');
211
-
212
- const fungibleMintableTrait = {
213
- traitName: 'FungibleMintable',
214
- structName: c.name,
215
- tags: ['contractimpl'],
216
- section: 'Extensions',
217
- };
218
-
219
- c.addTraitFunction(fungibleMintableTrait, functions.mint);
220
-
221
- requireAccessControl(c, fungibleMintableTrait, functions.mint, access);
222
-
223
- if (pausable) {
224
- c.addFunctionTag(functions.mint, 'when_not_paused', fungibleMintableTrait);
225
- }
226
- }
227
-
228
- const functions = defineFunctions({
247
+ export const functions = defineFunctions({
229
248
  // Token Functions
230
249
  total_supply: {
231
250
  args: [getSelfArg()],
232
251
  returns: 'i128',
233
- code: ['fungible::total_supply(e)'],
252
+ code: ['Self::ContractType::total_supply(e)'],
234
253
  },
235
254
  balance: {
236
255
  args: [getSelfArg(), { name: 'account', type: 'Address' }],
237
256
  returns: 'i128',
238
- code: ['fungible::balance(e, &account)'],
257
+ code: ['Self::ContractType::balance(e, &account)'],
239
258
  },
240
259
  allowance: {
241
260
  args: [getSelfArg(), { name: 'owner', type: 'Address' }, { name: 'spender', type: 'Address' }],
242
261
  returns: 'i128',
243
- code: ['fungible::allowance(e, &owner, &spender)'],
262
+ code: ['Self::ContractType::allowance(e, &owner, &spender)'],
244
263
  },
245
264
  transfer: {
246
265
  args: [
@@ -249,7 +268,7 @@ const functions = defineFunctions({
249
268
  { name: 'to', type: 'Address' },
250
269
  { name: 'amount', type: 'i128' },
251
270
  ],
252
- code: ['fungible::transfer(e, &from, &to, amount)'],
271
+ code: ['Self::ContractType::transfer(e, &from, &to, amount)'],
253
272
  },
254
273
  transfer_from: {
255
274
  args: [
@@ -259,7 +278,7 @@ const functions = defineFunctions({
259
278
  { name: 'to', type: 'Address' },
260
279
  { name: 'amount', type: 'i128' },
261
280
  ],
262
- code: ['fungible::transfer_from(e, &spender, &from, &to, amount)'],
281
+ code: ['Self::ContractType::transfer_from(e, &spender, &from, &to, amount)'],
263
282
  },
264
283
  approve: {
265
284
  args: [
@@ -269,28 +288,28 @@ const functions = defineFunctions({
269
288
  { name: 'amount', type: 'i128' },
270
289
  { name: 'live_until_ledger', type: 'u32' },
271
290
  ],
272
- code: ['fungible::approve(e, &owner, &spender, amount, live_until_ledger)'],
291
+ code: ['Self::ContractType::approve(e, &owner, &spender, amount, live_until_ledger)'],
273
292
  },
274
293
  decimals: {
275
294
  args: [getSelfArg()],
276
295
  returns: 'u32',
277
- code: ['fungible::metadata::decimals(e)'],
296
+ code: ['Self::ContractType::decimals(e)'],
278
297
  },
279
298
  name: {
280
299
  args: [getSelfArg()],
281
300
  returns: 'String',
282
- code: ['fungible::metadata::name(e)'],
301
+ code: ['Self::ContractType::name(e)'],
283
302
  },
284
303
  symbol: {
285
304
  args: [getSelfArg()],
286
305
  returns: 'String',
287
- code: ['fungible::metadata::symbol(e)'],
306
+ code: ['Self::ContractType::symbol(e)'],
288
307
  },
289
308
 
290
309
  // Extensions
291
310
  burn: {
292
311
  args: [getSelfArg(), { name: 'from', type: 'Address' }, { name: 'amount', type: 'i128' }],
293
- code: ['fungible::burnable::burn(e, &from, amount)'],
312
+ code: ['Base::burn(e, &from, amount)'],
294
313
  },
295
314
  burn_from: {
296
315
  args: [
@@ -299,10 +318,20 @@ const functions = defineFunctions({
299
318
  { name: 'from', type: 'Address' },
300
319
  { name: 'amount', type: 'i128' },
301
320
  ],
302
- code: ['fungible::burnable::burn_from(e, &spender, &from, amount)'],
321
+ code: ['Base::burn_from(e, &spender, &from, amount)'],
303
322
  },
304
323
  mint: {
305
324
  args: [getSelfArg(), { name: 'account', type: 'Address' }, { name: 'amount', type: 'i128' }],
306
- code: ['fungible::mintable::mint(e, &account, amount);'],
325
+ code: ['Base::mint(e, &account, amount);'],
326
+ },
327
+ mint_with_caller: {
328
+ name: 'mint',
329
+ args: [
330
+ getSelfArg(),
331
+ { name: 'account', type: 'Address' },
332
+ { name: 'amount', type: 'i128' },
333
+ { name: 'caller', type: 'Address' },
334
+ ],
335
+ code: ['Base::mint(e, &account, amount);'],
307
336
  },
308
337
  });
@@ -4,6 +4,7 @@ import crypto from 'crypto';
4
4
 
5
5
  import { generateFungibleOptions } from './fungible';
6
6
  import { generateNonFungibleOptions } from './non-fungible';
7
+ import { generateStablecoinOptions } from './stablecoin';
7
8
  import type { GenericOptions, KindedOptions } from '../build-generic';
8
9
  import { buildGeneric } from '../build-generic';
9
10
  import { printContract } from '../print';
@@ -24,6 +25,12 @@ export function* generateOptions(kind?: Kind): Generator<GenericOptions> {
24
25
  yield { kind: 'NonFungible', ...kindOpts };
25
26
  }
26
27
  }
28
+
29
+ if (!kind || kind === 'Stablecoin') {
30
+ for (const kindOpts of generateStablecoinOptions()) {
31
+ yield { kind: 'Stablecoin', ...kindOpts };
32
+ }
33
+ }
27
34
  }
28
35
 
29
36
  interface GeneratedContract {
@@ -0,0 +1,23 @@
1
+ import { limitationsOptions, type StablecoinOptions } from '../stablecoin';
2
+ import { accessOptions } from '../set-access-control';
3
+ import { infoOptions } from '../set-info';
4
+ import { generateAlternatives } from './alternatives';
5
+
6
+ const booleans = [true, false];
7
+
8
+ const blueprint = {
9
+ name: ['MyStablecoin'],
10
+ symbol: ['MST'],
11
+ burnable: booleans,
12
+ pausable: booleans,
13
+ upgradeable: booleans,
14
+ mintable: booleans,
15
+ premint: ['1'],
16
+ access: accessOptions,
17
+ limitations: limitationsOptions,
18
+ info: infoOptions,
19
+ };
20
+
21
+ export function* generateStablecoinOptions(): Generator<Required<StablecoinOptions>> {
22
+ yield* generateAlternatives(blueprint);
23
+ }
package/src/index.ts CHANGED
@@ -23,6 +23,8 @@ export { contractsVersion, contractsVersionTag, compatibleContractsSemver } from
23
23
 
24
24
  export { fungible } from './api';
25
25
  export { nonFungible } from './api';
26
+ export { stablecoin } from './api';
26
27
 
27
28
  export type { FungibleOptions } from './fungible';
28
29
  export type { NonFungibleOptions } from './non-fungible';
30
+ export type { StablecoinOptions } from './stablecoin';
package/src/kind.ts CHANGED
@@ -16,6 +16,7 @@ function isKind<T>(value: Kind | T): value is Kind {
16
16
  switch (value) {
17
17
  case 'Fungible':
18
18
  case 'NonFungible':
19
+ case 'Stablecoin':
19
20
  return true;
20
21
 
21
22
  default: {
@@ -57,6 +57,10 @@ function withDefaults(opts: NonFungibleOptions): Required<NonFungibleOptions> {
57
57
  };
58
58
  }
59
59
 
60
+ export function isAccessControlRequired(opts: Partial<NonFungibleOptions>): boolean {
61
+ return opts.mintable === true || opts.pausable === true || opts.upgradeable === true || opts.consecutive === true;
62
+ }
63
+
60
64
  export function buildNonFungible(opts: NonFungibleOptions): Contract {
61
65
  const c = new ContractBuilder(opts.name);
62
66
 
@@ -117,50 +121,42 @@ export function buildNonFungible(opts: NonFungibleOptions): Contract {
117
121
 
118
122
  function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boolean) {
119
123
  // Set metadata
120
- c.addConstructorCode(
121
- `Base::set_metadata(e, String::from_str(e, "www.mytoken.com"), String::from_str(e, "${name}"), String::from_str(e, "${symbol}"));`,
122
- );
124
+ c.addConstructorCode('let uri = String::from_str(e, "www.mytoken.com");');
125
+ c.addConstructorCode(`let name = String::from_str(e, "${name}");`);
126
+ c.addConstructorCode(`let symbol = String::from_str(e, "${symbol}");`);
127
+ c.addConstructorCode(`Base::set_metadata(e, uri, name, symbol);`);
123
128
 
124
129
  // Set token functions
125
- c.addUseClause('stellar_non_fungible', 'Base');
126
- c.addUseClause('stellar_non_fungible', 'NonFungibleToken');
130
+ c.addUseClause('stellar_tokens::non_fungible', 'Base');
131
+ c.addUseClause('stellar_tokens::non_fungible', 'NonFungibleToken');
132
+ c.addUseClause('stellar_macros', 'default_impl');
127
133
  c.addUseClause('soroban_sdk', 'contract');
128
134
  c.addUseClause('soroban_sdk', 'contractimpl');
129
- c.addUseClause('soroban_sdk', 'Address');
130
135
  c.addUseClause('soroban_sdk', 'String');
131
136
  c.addUseClause('soroban_sdk', 'Env');
132
137
 
133
138
  const nonFungibleTokenTrait = {
134
139
  traitName: 'NonFungibleToken',
135
140
  structName: c.name,
136
- tags: ['contractimpl'],
141
+ tags: ['default_impl', 'contractimpl'],
137
142
  assocType: 'type ContractType = Base;',
138
143
  };
139
144
 
140
- // all the below may be eliminated by introducing `defaultimpl` macro at `tags` above,
141
- // but we lose the customization for `pausable`, and so on...
142
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.owner_of);
143
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.transfer);
144
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.transfer_from);
145
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.balance);
146
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.approve);
147
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.approve_for_all);
148
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.get_approved);
149
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.is_approved_for_all);
150
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.name);
151
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.symbol);
152
- c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.token_uri);
145
+ c.addTraitImplBlock(nonFungibleTokenTrait);
153
146
 
154
147
  if (pausable) {
155
- c.addUseClause('stellar_pausable_macros', 'when_not_paused');
148
+ c.addUseClause('stellar_macros', 'when_not_paused');
149
+
150
+ c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.transfer);
156
151
  c.addFunctionTag(baseFunctions.transfer, 'when_not_paused', nonFungibleTokenTrait);
152
+
157
153
  c.addFunctionTag(baseFunctions.transfer_from, 'when_not_paused', nonFungibleTokenTrait);
154
+ c.addTraitFunction(nonFungibleTokenTrait, baseFunctions.transfer_from);
158
155
  }
159
156
  }
160
157
 
161
158
  function addBurnable(c: ContractBuilder, pausable: boolean) {
162
- c.addUseClause('stellar_non_fungible', 'burnable::NonFungibleBurnable');
163
- c.addUseClause('soroban_sdk', 'Address');
159
+ c.addUseClause('stellar_tokens::non_fungible', 'burnable::NonFungibleBurnable');
164
160
 
165
161
  const nonFungibleBurnableTrait = {
166
162
  traitName: 'NonFungibleBurnable',
@@ -169,20 +165,24 @@ function addBurnable(c: ContractBuilder, pausable: boolean) {
169
165
  section: 'Extensions',
170
166
  };
171
167
 
172
- c.addTraitFunction(nonFungibleBurnableTrait, burnableFunctions.burn);
173
- c.addTraitFunction(nonFungibleBurnableTrait, burnableFunctions.burn_from);
174
-
175
168
  if (pausable) {
176
- c.addUseClause('stellar_pausable_macros', 'when_not_paused');
169
+ c.addUseClause('stellar_macros', 'when_not_paused');
170
+
171
+ c.addTraitFunction(nonFungibleBurnableTrait, burnableFunctions.burn);
177
172
  c.addFunctionTag(burnableFunctions.burn, 'when_not_paused', nonFungibleBurnableTrait);
173
+
174
+ c.addTraitFunction(nonFungibleBurnableTrait, burnableFunctions.burn_from);
178
175
  c.addFunctionTag(burnableFunctions.burn_from, 'when_not_paused', nonFungibleBurnableTrait);
176
+ } else {
177
+ // prepend '#[default_impl]'
178
+ nonFungibleBurnableTrait.tags.unshift('default_impl');
179
+ c.addTraitImplBlock(nonFungibleBurnableTrait);
179
180
  }
180
181
  }
181
182
 
182
183
  function addEnumerable(c: ContractBuilder) {
183
- c.addUseClause('stellar_non_fungible', 'enumerable::{NonFungibleEnumerable, Enumerable}');
184
- c.addUseClause('stellar_default_impl_macro', 'default_impl');
185
- c.addUseClause('stellar_non_fungible', 'ContractOverrides');
184
+ c.addUseClause('stellar_tokens::non_fungible', 'enumerable::{NonFungibleEnumerable, Enumerable}');
185
+ c.addUseClause('stellar_macros', 'default_impl');
186
186
 
187
187
  const nonFungibleEnumerableTrait = {
188
188
  traitName: 'NonFungibleEnumerable',
@@ -193,23 +193,11 @@ function addEnumerable(c: ContractBuilder) {
193
193
  c.addTraitImplBlock(nonFungibleEnumerableTrait);
194
194
 
195
195
  c.overrideAssocType('NonFungibleToken', 'type ContractType = Enumerable;');
196
-
197
- // Below is not required due to `defaultimpl` macro. If we require to customize the functions,
198
- // then we should:
199
- // 1. get rid of the `defaultimpl` macro form `tags` above,
200
- // 2. get rid of `c.addImplementedTrait(nonFungibleEnumerableTrait);` line,
201
- // 3. uncomment the section below:
202
- // 4. uncomment `get_owner_token_id` and `get_token_id` from `enumerableFunctions` definition
203
- /*
204
- c.addFunction(nonFungibleEnumerableTrait, enumerableFunctions.total_supply);
205
- c.addFunction(nonFungibleEnumerableTrait, enumerableFunctions.get_owner_token_id);
206
- c.addFunction(nonFungibleEnumerableTrait, enumerableFunctions.get_token_id);
207
- */
208
196
  }
209
197
 
210
198
  function addConsecutive(c: ContractBuilder, pausable: boolean, access: Access) {
211
- c.addUseClause('stellar_non_fungible', 'consecutive::{NonFungibleConsecutive, Consecutive}');
212
- c.addUseClause('stellar_non_fungible', 'ContractOverrides');
199
+ c.addUseClause('stellar_tokens::non_fungible', 'consecutive::{NonFungibleConsecutive, Consecutive}');
200
+ c.addUseClause('soroban_sdk', 'Address');
213
201
 
214
202
  const nonFungibleConsecutiveTrait = {
215
203
  traitName: 'NonFungibleConsecutive',
@@ -222,48 +210,49 @@ function addConsecutive(c: ContractBuilder, pausable: boolean, access: Access) {
222
210
 
223
211
  c.overrideAssocType('NonFungibleToken', 'type ContractType = Consecutive;');
224
212
 
225
- c.addFreeFunction(consecutiveFunctions.batch_mint);
213
+ const mintFn = access === 'ownable' ? consecutiveFunctions.batch_mint : consecutiveFunctions.batch_mint_with_caller;
214
+ c.addFreeFunction(mintFn);
226
215
  if (pausable) {
227
- c.addFunctionTag(consecutiveFunctions.batch_mint, 'when_not_paused');
216
+ c.addFunctionTag(mintFn, 'when_not_paused');
228
217
  }
229
218
 
230
- requireAccessControl(c, undefined, consecutiveFunctions.batch_mint, access);
219
+ requireAccessControl(c, undefined, mintFn, access, {
220
+ useMacro: true,
221
+ role: 'minter',
222
+ caller: 'caller',
223
+ });
231
224
  }
232
225
 
233
226
  function addMintable(c: ContractBuilder, enumerable: boolean, pausable: boolean, sequential: boolean, access: Access) {
234
- if (!enumerable) {
227
+ c.addUseClause('soroban_sdk', 'Address');
228
+ const accessProps = { useMacro: true, role: 'minter', caller: 'caller' };
229
+
230
+ let mintFn;
231
+
232
+ if (enumerable) {
235
233
  if (sequential) {
236
- c.addUseClause('stellar_non_fungible', 'Base::sequential_mint');
237
- c.addFreeFunction(baseFunctions.sequential_mint);
238
- requireAccessControl(c, undefined, baseFunctions.sequential_mint, access);
239
- if (pausable) {
240
- c.addFunctionTag(baseFunctions.sequential_mint, 'when_not_paused');
241
- }
234
+ mintFn =
235
+ access === 'ownable' ? enumerableFunctions.sequential_mint : enumerableFunctions.sequential_mint_with_caller;
242
236
  } else {
243
- c.addUseClause('stellar_non_fungible', 'Base::mint');
244
- c.addFreeFunction(baseFunctions.mint);
245
- requireAccessControl(c, undefined, baseFunctions.mint, access);
246
- if (pausable) {
247
- c.addFunctionTag(baseFunctions.mint, 'when_not_paused');
248
- }
237
+ mintFn =
238
+ access === 'ownable'
239
+ ? enumerableFunctions.non_sequential_mint
240
+ : enumerableFunctions.non_sequential_mint_with_caller;
249
241
  }
250
- }
251
-
252
- if (enumerable) {
242
+ } else {
253
243
  if (sequential) {
254
- c.addFreeFunction(enumerableFunctions.sequential_mint);
255
- requireAccessControl(c, undefined, enumerableFunctions.sequential_mint, access);
256
- if (pausable) {
257
- c.addFunctionTag(enumerableFunctions.sequential_mint, 'when_not_paused');
258
- }
244
+ mintFn = access === 'ownable' ? baseFunctions.sequential_mint : baseFunctions.sequential_mint_with_caller;
259
245
  } else {
260
- c.addFreeFunction(enumerableFunctions.non_sequential_mint);
261
- requireAccessControl(c, undefined, enumerableFunctions.non_sequential_mint, access);
262
- if (pausable) {
263
- c.addFunctionTag(enumerableFunctions.non_sequential_mint, 'when_not_paused');
264
- }
246
+ mintFn = access === 'ownable' ? baseFunctions.mint : baseFunctions.mint_with_caller;
265
247
  }
266
248
  }
249
+
250
+ c.addFreeFunction(mintFn);
251
+ requireAccessControl(c, undefined, mintFn, access, accessProps);
252
+
253
+ if (pausable) {
254
+ c.addFunctionTag(mintFn, 'when_not_paused');
255
+ }
267
256
  }
268
257
 
269
258
  const baseFunctions = defineFunctions({
@@ -347,10 +336,26 @@ const baseFunctions = defineFunctions({
347
336
  args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'token_id', type: 'u32' }],
348
337
  code: ['Base::mint(e, &to, token_id);'],
349
338
  },
339
+ mint_with_caller: {
340
+ name: 'mint',
341
+ args: [
342
+ getSelfArg(),
343
+ { name: 'to', type: 'Address' },
344
+ { name: 'token_id', type: 'u32' },
345
+ { name: 'caller', type: 'Address' },
346
+ ],
347
+ code: ['Base::mint(e, &to, token_id);'],
348
+ },
350
349
  sequential_mint: {
350
+ name: 'mint',
351
351
  args: [getSelfArg(), { name: 'to', type: 'Address' }],
352
352
  code: ['Base::sequential_mint(e, &to);'],
353
353
  },
354
+ sequential_mint_with_caller: {
355
+ name: 'mint',
356
+ args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'caller', type: 'Address' }],
357
+ code: ['Base::sequential_mint(e, &to);'],
358
+ },
354
359
  });
355
360
 
356
361
  const burnableFunctions = defineFunctions({
@@ -375,33 +380,49 @@ const enumerableFunctions = defineFunctions({
375
380
  returns: 'u32',
376
381
  code: ['non_fungible::enumerable::Enumerable::total_supply(e)'],
377
382
  },
378
- // These are not currently used, see addEnumerable() above
379
- /*
380
- get_owner_token_id: {
381
- args: [getSelfArg(), { name: 'owner', type: 'Address' }, { name: 'index', type: 'u32' }],
382
- returns: 'u32',
383
- code: ['Enumerable::get_owner_token_id(e, &owner, index)'],
384
- },
385
- get_token_id: {
386
- args: [getSelfArg(), { name: 'index', type: 'u32' }],
387
- returns: 'u32',
388
- code: ['Enumerable::get_token_id(e, index)'],
389
- },
390
- */
391
383
  non_sequential_mint: {
384
+ name: 'mint',
392
385
  args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'token_id', type: 'u32' }],
393
- code: ['Enumerable::non_sequential_mint(e, &to, token_id);'], // TODO: unify `mint` name in Stellar-Contracts across extensions
386
+ code: ['Enumerable::non_sequential_mint(e, &to, token_id);'],
387
+ },
388
+ non_sequential_mint_with_caller: {
389
+ name: 'mint',
390
+ args: [
391
+ getSelfArg(),
392
+ { name: 'to', type: 'Address' },
393
+ { name: 'token_id', type: 'u32' },
394
+ { name: 'caller', type: 'Address' },
395
+ ],
396
+ code: ['Enumerable::non_sequential_mint(e, &to, token_id);'],
394
397
  },
395
398
  sequential_mint: {
399
+ name: 'mint',
396
400
  args: [getSelfArg(), { name: 'to', type: 'Address' }],
397
401
  code: ['Enumerable::sequential_mint(e, &to);'],
398
402
  },
403
+ sequential_mint_with_caller: {
404
+ name: 'mint',
405
+ args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'caller', type: 'Address' }],
406
+ code: ['Enumerable::sequential_mint(e, &to);'],
407
+ },
399
408
  });
400
409
 
401
410
  const consecutiveFunctions = defineFunctions({
402
411
  batch_mint: {
412
+ name: 'batch_mint',
403
413
  args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'amount', type: 'u32' }],
404
414
  returns: 'u32',
405
415
  code: ['Consecutive::batch_mint(e, &to, amount);'],
406
416
  },
417
+ batch_mint_with_caller: {
418
+ name: 'batch_mint',
419
+ args: [
420
+ getSelfArg(),
421
+ { name: 'to', type: 'Address' },
422
+ { name: 'amount', type: 'u32' },
423
+ { name: 'caller', type: 'Address' },
424
+ ],
425
+ returns: 'u32',
426
+ code: ['Consecutive::batch_mint(e, &to, amount);'],
427
+ },
407
428
  });