@openzeppelin/wizard-stellar 0.1.1 → 0.2.0

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 +1 -0
  2. package/dist/add-pausable.js +7 -7
  3. package/dist/add-pausable.js.map +1 -1
  4. package/dist/add-upgradeable.d.ts +4 -0
  5. package/dist/add-upgradeable.d.ts.map +1 -0
  6. package/dist/add-upgradeable.js +26 -0
  7. package/dist/add-upgradeable.js.map +1 -0
  8. package/dist/api.d.ts +3 -0
  9. package/dist/api.d.ts.map +1 -1
  10. package/dist/api.js +6 -1
  11. package/dist/api.js.map +1 -1
  12. package/dist/build-generic.d.ts +4 -0
  13. package/dist/build-generic.d.ts.map +1 -1
  14. package/dist/build-generic.js +5 -2
  15. package/dist/build-generic.js.map +1 -1
  16. package/dist/contract.d.ts +22 -11
  17. package/dist/contract.d.ts.map +1 -1
  18. package/dist/contract.js +58 -12
  19. package/dist/contract.js.map +1 -1
  20. package/dist/fungible.d.ts +1 -0
  21. package/dist/fungible.d.ts.map +1 -1
  22. package/dist/fungible.js +38 -32
  23. package/dist/fungible.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 +3 -0
  28. package/dist/generate/non-fungible.d.ts.map +1 -0
  29. package/dist/generate/non-fungible.js +24 -0
  30. package/dist/generate/non-fungible.js.map +1 -0
  31. package/dist/generate/sources.d.ts.map +1 -1
  32. package/dist/generate/sources.js +6 -0
  33. package/dist/generate/sources.js.map +1 -1
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/kind.js +2 -1
  39. package/dist/kind.js.map +1 -1
  40. package/dist/non-fungible.d.ts +17 -0
  41. package/dist/non-fungible.d.ts.map +1 -0
  42. package/dist/non-fungible.js +356 -0
  43. package/dist/non-fungible.js.map +1 -0
  44. package/dist/print.d.ts.map +1 -1
  45. package/dist/print.js +53 -17
  46. package/dist/print.js.map +1 -1
  47. package/dist/set-access-control.d.ts +2 -2
  48. package/dist/set-access-control.d.ts.map +1 -1
  49. package/dist/set-access-control.js +2 -7
  50. package/dist/set-access-control.js.map +1 -1
  51. package/dist/test.js +3 -0
  52. package/dist/test.js.map +1 -1
  53. package/dist/utils/version.d.ts +3 -3
  54. package/dist/utils/version.js +2 -2
  55. package/package.json +3 -4
  56. package/src/add-pausable.ts +7 -7
  57. package/src/add-upgradeable.ts +30 -0
  58. package/src/api.ts +8 -0
  59. package/src/build-generic.ts +9 -2
  60. package/src/contract.ts +73 -21
  61. package/src/fungible.ts +38 -30
  62. package/src/generate/fungible.ts +1 -0
  63. package/src/generate/non-fungible.ts +24 -0
  64. package/src/generate/sources.ts +7 -0
  65. package/src/index.ts +1 -0
  66. package/src/kind.ts +2 -1
  67. package/src/non-fungible.ts +410 -0
  68. package/src/print.ts +77 -28
  69. package/src/set-access-control.ts +8 -9
  70. package/src/test.ts +4 -0
  71. package/src/utils/version.ts +2 -2
package/src/fungible.ts CHANGED
@@ -3,6 +3,7 @@ import { ContractBuilder } from './contract';
3
3
  import type { Access } from './set-access-control';
4
4
  import { requireAccessControl, setAccessControl } from './set-access-control';
5
5
  import { addPausable } from './add-pausable';
6
+ import { addUpgradeable } from './add-upgradeable';
6
7
  import { defineFunctions } from './utils/define-functions';
7
8
  import type { CommonContractOptions } from './common-options';
8
9
  import { withCommonContractDefaults, getSelfArg } from './common-options';
@@ -17,6 +18,7 @@ export const defaults: Required<FungibleOptions> = {
17
18
  symbol: 'MTK',
18
19
  burnable: false,
19
20
  pausable: false,
21
+ upgradeable: false,
20
22
  premint: '0',
21
23
  mintable: false,
22
24
  access: commonDefaults.access, // TODO: Determine whether Access Control options should be visible in the UI before they are implemented as modules
@@ -32,6 +34,7 @@ export interface FungibleOptions extends CommonContractOptions {
32
34
  symbol: string;
33
35
  burnable?: boolean;
34
36
  pausable?: boolean;
37
+ upgradeable?: boolean;
35
38
  premint?: string;
36
39
  mintable?: boolean;
37
40
  }
@@ -42,6 +45,7 @@ function withDefaults(opts: FungibleOptions): Required<FungibleOptions> {
42
45
  ...withCommonContractDefaults(opts),
43
46
  burnable: opts.burnable ?? defaults.burnable,
44
47
  pausable: opts.pausable ?? defaults.pausable,
48
+ upgradeable: opts.upgradeable ?? defaults.upgradeable,
45
49
  premint: opts.premint || defaults.premint,
46
50
  mintable: opts.mintable ?? defaults.mintable,
47
51
  };
@@ -62,6 +66,10 @@ export function buildFungible(opts: FungibleOptions): Contract {
62
66
  addPausable(c, allOpts.access);
63
67
  }
64
68
 
69
+ if (allOpts.upgradeable) {
70
+ addUpgradeable(c, allOpts.access);
71
+ }
72
+
65
73
  if (allOpts.burnable) {
66
74
  addBurnable(c, allOpts.pausable);
67
75
  }
@@ -83,8 +91,8 @@ function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boo
83
91
  );
84
92
 
85
93
  // Set token functions
86
- c.addUseClause('openzeppelin_fungible_token', 'self', { alias: 'fungible' });
87
- c.addUseClause('openzeppelin_fungible_token', 'FungibleToken');
94
+ c.addUseClause('stellar_fungible', 'self', { alias: 'fungible' });
95
+ c.addUseClause('stellar_fungible', 'FungibleToken');
88
96
  c.addUseClause('soroban_sdk', 'contract');
89
97
  c.addUseClause('soroban_sdk', 'contractimpl');
90
98
  c.addUseClause('soroban_sdk', 'Address');
@@ -93,46 +101,46 @@ function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boo
93
101
  c.addUseClause('soroban_sdk', 'Symbol');
94
102
 
95
103
  const fungibleTokenTrait = {
96
- name: 'FungibleToken',
97
- for: c.name,
104
+ traitName: 'FungibleToken',
105
+ structName: c.name,
98
106
  tags: ['contractimpl'],
99
107
  };
100
108
 
101
- c.addFunction(fungibleTokenTrait, functions.total_supply);
102
- c.addFunction(fungibleTokenTrait, functions.balance);
103
- c.addFunction(fungibleTokenTrait, functions.allowance);
104
- c.addFunction(fungibleTokenTrait, functions.transfer);
105
- c.addFunction(fungibleTokenTrait, functions.transfer_from);
106
- c.addFunction(fungibleTokenTrait, functions.approve);
107
- c.addFunction(fungibleTokenTrait, functions.decimals);
108
- c.addFunction(fungibleTokenTrait, functions.name);
109
- c.addFunction(fungibleTokenTrait, functions.symbol);
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
118
 
111
119
  if (pausable) {
112
- c.addUseClause('openzeppelin_pausable_macros', 'when_not_paused');
113
- c.addFunctionTag(fungibleTokenTrait, functions.transfer, 'when_not_paused');
114
- c.addFunctionTag(fungibleTokenTrait, functions.transfer_from, 'when_not_paused');
120
+ c.addUseClause('stellar_pausable_macros', 'when_not_paused');
121
+ c.addFunctionTag(functions.transfer, 'when_not_paused', fungibleTokenTrait);
122
+ c.addFunctionTag(functions.transfer_from, 'when_not_paused', fungibleTokenTrait);
115
123
  }
116
124
  }
117
125
 
118
126
  function addBurnable(c: ContractBuilder, pausable: boolean) {
119
- c.addUseClause('openzeppelin_fungible_token', 'burnable::FungibleBurnable');
127
+ c.addUseClause('stellar_fungible', 'burnable::FungibleBurnable');
120
128
  c.addUseClause('soroban_sdk', 'Address');
121
129
 
122
130
  const fungibleBurnableTrait = {
123
- name: 'FungibleBurnable',
124
- for: c.name,
131
+ traitName: 'FungibleBurnable',
132
+ structName: c.name,
125
133
  tags: ['contractimpl'],
126
134
  section: 'Extensions',
127
135
  };
128
136
 
129
- c.addFunction(fungibleBurnableTrait, functions.burn);
130
- c.addFunction(fungibleBurnableTrait, functions.burn_from);
137
+ c.addTraitFunction(fungibleBurnableTrait, functions.burn);
138
+ c.addTraitFunction(fungibleBurnableTrait, functions.burn_from);
131
139
 
132
140
  if (pausable) {
133
- c.addUseClause('openzeppelin_pausable_macros', 'when_not_paused');
134
- c.addFunctionTag(fungibleBurnableTrait, functions.burn, 'when_not_paused');
135
- c.addFunctionTag(fungibleBurnableTrait, functions.burn_from, 'when_not_paused');
141
+ c.addUseClause('stellar_pausable_macros', 'when_not_paused');
142
+ c.addFunctionTag(functions.burn, 'when_not_paused', fungibleBurnableTrait);
143
+ c.addFunctionTag(functions.burn_from, 'when_not_paused', fungibleBurnableTrait);
136
144
  }
137
145
  }
138
146
 
@@ -149,7 +157,7 @@ function addPremint(c: ContractBuilder, amount: string) {
149
157
  // TODO: handle signed int?
150
158
  const premintAbsolute = toUint(getInitialSupply(amount, 18), 'premint', 'u128');
151
159
 
152
- c.addUseClause('openzeppelin_fungible_token', 'mintable::FungibleMintable');
160
+ c.addUseClause('stellar_fungible', 'mintable::FungibleMintable');
153
161
  c.addUseClause('soroban_sdk', 'Address');
154
162
 
155
163
  c.addConstructorArgument({ name: 'recipient', type: 'Address' });
@@ -199,21 +207,21 @@ export function getInitialSupply(premint: string, decimals: number): string {
199
207
  }
200
208
 
201
209
  function addMintable(c: ContractBuilder, access: Access, pausable: boolean) {
202
- c.addUseClause('openzeppelin_fungible_token', 'mintable::FungibleMintable');
210
+ c.addUseClause('stellar_fungible', 'mintable::FungibleMintable');
203
211
 
204
212
  const fungibleMintableTrait = {
205
- name: 'FungibleMintable',
206
- for: c.name,
213
+ traitName: 'FungibleMintable',
214
+ structName: c.name,
207
215
  tags: ['contractimpl'],
208
216
  section: 'Extensions',
209
217
  };
210
218
 
211
- c.addFunction(fungibleMintableTrait, functions.mint);
219
+ c.addTraitFunction(fungibleMintableTrait, functions.mint);
212
220
 
213
221
  requireAccessControl(c, fungibleMintableTrait, functions.mint, access);
214
222
 
215
223
  if (pausable) {
216
- c.addFunctionTag(fungibleMintableTrait, functions.mint, 'when_not_paused');
224
+ c.addFunctionTag(functions.mint, 'when_not_paused', fungibleMintableTrait);
217
225
  }
218
226
  }
219
227
 
@@ -10,6 +10,7 @@ const blueprint = {
10
10
  symbol: ['MTK'],
11
11
  burnable: booleans,
12
12
  pausable: booleans,
13
+ upgradeable: booleans,
13
14
  mintable: booleans,
14
15
  premint: ['1'],
15
16
  access: accessOptions,
@@ -0,0 +1,24 @@
1
+ import type { NonFungibleOptions } from '../non-fungible';
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: ['MyToken'],
10
+ symbol: ['MTK'],
11
+ burnable: booleans,
12
+ pausable: booleans,
13
+ upgradeable: booleans,
14
+ enumerable: booleans,
15
+ consecutive: booleans,
16
+ sequential: booleans,
17
+ mintable: booleans,
18
+ access: accessOptions,
19
+ info: infoOptions,
20
+ };
21
+
22
+ export function* generateNonFungibleOptions(): Generator<Required<NonFungibleOptions>> {
23
+ yield* generateAlternatives(blueprint);
24
+ }
@@ -3,6 +3,7 @@ import path from 'path';
3
3
  import crypto from 'crypto';
4
4
 
5
5
  import { generateFungibleOptions } from './fungible';
6
+ import { generateNonFungibleOptions } from './non-fungible';
6
7
  import type { GenericOptions, KindedOptions } from '../build-generic';
7
8
  import { buildGeneric } from '../build-generic';
8
9
  import { printContract } from '../print';
@@ -17,6 +18,12 @@ export function* generateOptions(kind?: Kind): Generator<GenericOptions> {
17
18
  yield { kind: 'Fungible', ...kindOpts };
18
19
  }
19
20
  }
21
+
22
+ if (!kind || kind === 'NonFungible') {
23
+ for (const kindOpts of generateNonFungibleOptions()) {
24
+ yield { kind: 'NonFungible', ...kindOpts };
25
+ }
26
+ }
20
27
  }
21
28
 
22
29
  interface GeneratedContract {
package/src/index.ts CHANGED
@@ -22,3 +22,4 @@ export { sanitizeKind } from './kind';
22
22
  export { contractsVersion, contractsVersionTag, compatibleContractsSemver } from './utils/version';
23
23
 
24
24
  export { fungible } from './api';
25
+ export { nonFungible } from './api';
package/src/kind.ts CHANGED
@@ -4,7 +4,7 @@ export type Kind = GenericOptions['kind'];
4
4
 
5
5
  export function sanitizeKind(kind: unknown): Kind {
6
6
  if (typeof kind === 'string') {
7
- const sanitized = kind.replace(/^(ERC|.)/i, c => c.toUpperCase());
7
+ const sanitized = kind.replace(/^(ERC|.)/i, c => c.toUpperCase()).replace(/^(NonFungible)$/i, 'NonFungible');
8
8
  if (isKind(sanitized)) {
9
9
  return sanitized;
10
10
  }
@@ -15,6 +15,7 @@ export function sanitizeKind(kind: unknown): Kind {
15
15
  function isKind<T>(value: Kind | T): value is Kind {
16
16
  switch (value) {
17
17
  case 'Fungible':
18
+ case 'NonFungible':
18
19
  return true;
19
20
 
20
21
  default: {
@@ -0,0 +1,410 @@
1
+ import type { Contract } from './contract';
2
+ import { ContractBuilder } from './contract';
3
+ import { type Access, requireAccessControl, setAccessControl } from './set-access-control';
4
+ import { addPausable } from './add-pausable';
5
+ import { addUpgradeable } from './add-upgradeable';
6
+ import { defineFunctions } from './utils/define-functions';
7
+ import type { CommonContractOptions } from './common-options';
8
+ import { withCommonContractDefaults, getSelfArg } from './common-options';
9
+ import { setInfo } from './set-info';
10
+ import type { OptionsErrorMessages } from './error';
11
+ import { OptionsError } from './error';
12
+ import { contractDefaults as commonDefaults } from './common-options';
13
+ import { printContract } from './print';
14
+ import { toByteArray } from './utils/convert-strings';
15
+
16
+ export const defaults: Required<NonFungibleOptions> = {
17
+ name: 'MyToken',
18
+ symbol: 'MTK',
19
+ burnable: false,
20
+ enumerable: false,
21
+ consecutive: false,
22
+ pausable: false,
23
+ upgradeable: false,
24
+ mintable: false,
25
+ sequential: false,
26
+ access: commonDefaults.access, // TODO: Determine whether Access Control options should be visible in the UI before they are implemented as modules
27
+ info: commonDefaults.info,
28
+ } as const;
29
+
30
+ export function printNonFungible(opts: NonFungibleOptions = defaults): string {
31
+ return printContract(buildNonFungible(opts));
32
+ }
33
+
34
+ export interface NonFungibleOptions extends CommonContractOptions {
35
+ name: string;
36
+ symbol: string;
37
+ burnable?: boolean;
38
+ enumerable?: boolean;
39
+ consecutive?: boolean;
40
+ pausable?: boolean;
41
+ upgradeable?: boolean;
42
+ mintable?: boolean;
43
+ sequential?: boolean;
44
+ }
45
+
46
+ function withDefaults(opts: NonFungibleOptions): Required<NonFungibleOptions> {
47
+ return {
48
+ ...opts,
49
+ ...withCommonContractDefaults(opts),
50
+ burnable: opts.burnable ?? defaults.burnable,
51
+ consecutive: opts.consecutive ?? defaults.consecutive,
52
+ enumerable: opts.enumerable ?? defaults.enumerable,
53
+ pausable: opts.pausable ?? defaults.pausable,
54
+ upgradeable: opts.upgradeable ?? defaults.upgradeable,
55
+ mintable: opts.mintable ?? defaults.mintable,
56
+ sequential: opts.sequential ?? defaults.sequential,
57
+ };
58
+ }
59
+
60
+ export function buildNonFungible(opts: NonFungibleOptions): Contract {
61
+ const c = new ContractBuilder(opts.name);
62
+
63
+ const allOpts = withDefaults(opts);
64
+
65
+ const errors: OptionsErrorMessages = {};
66
+
67
+ if (allOpts.enumerable && allOpts.consecutive) {
68
+ errors.enumerable = 'Enumerable cannot be used with Consecutive extension';
69
+ errors.consecutive = 'Consecutive cannot be used with Enumerable extension';
70
+ }
71
+
72
+ if (allOpts.consecutive && allOpts.mintable) {
73
+ errors.consecutive = 'Consecutive cannot be used with Mintable extension';
74
+ errors.mintable = 'Mintable cannot be used with Consecutive extension';
75
+ }
76
+
77
+ if (allOpts.consecutive && allOpts.sequential) {
78
+ errors.consecutive = 'Consecutive cannot be used with Sequential minting';
79
+ errors.sequential = 'Sequential minting cannot be used with Consecutive extension';
80
+ }
81
+
82
+ if (Object.keys(errors).length > 0) {
83
+ throw new OptionsError(errors);
84
+ }
85
+
86
+ addBase(c, toByteArray(allOpts.name), toByteArray(allOpts.symbol), allOpts.pausable);
87
+
88
+ if (allOpts.pausable) {
89
+ addPausable(c, allOpts.access);
90
+ }
91
+
92
+ if (allOpts.upgradeable) {
93
+ addUpgradeable(c, allOpts.access);
94
+ }
95
+
96
+ if (allOpts.burnable) {
97
+ addBurnable(c, allOpts.pausable);
98
+ }
99
+
100
+ if (allOpts.enumerable) {
101
+ addEnumerable(c, allOpts.burnable);
102
+ }
103
+
104
+ if (allOpts.consecutive) {
105
+ addConsecutive(c, allOpts.pausable, allOpts.access);
106
+ }
107
+
108
+ if (allOpts.mintable) {
109
+ addMintable(c, allOpts.enumerable, allOpts.pausable, allOpts.sequential, allOpts.access);
110
+ }
111
+
112
+ setAccessControl(c, allOpts.access);
113
+ setInfo(c, allOpts.info);
114
+
115
+ return c;
116
+ }
117
+
118
+ function addBase(c: ContractBuilder, name: string, symbol: string, pausable: boolean) {
119
+ // 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
+ );
123
+
124
+ // Set token functions
125
+ c.addUseClause('stellar_non_fungible', 'Base');
126
+ c.addUseClause('stellar_non_fungible', 'NonFungibleToken');
127
+ c.addUseClause('soroban_sdk', 'contract');
128
+ c.addUseClause('soroban_sdk', 'contractimpl');
129
+ c.addUseClause('soroban_sdk', 'Address');
130
+ c.addUseClause('soroban_sdk', 'String');
131
+ c.addUseClause('soroban_sdk', 'Env');
132
+
133
+ const nonFungibleTokenTrait = {
134
+ traitName: 'NonFungibleToken',
135
+ structName: c.name,
136
+ tags: ['contractimpl'],
137
+ assocType: 'type ContractType = Base;',
138
+ };
139
+
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);
153
+
154
+ if (pausable) {
155
+ c.addUseClause('stellar_pausable_macros', 'when_not_paused');
156
+ c.addFunctionTag(baseFunctions.transfer, 'when_not_paused', nonFungibleTokenTrait);
157
+ c.addFunctionTag(baseFunctions.transfer_from, 'when_not_paused', nonFungibleTokenTrait);
158
+ }
159
+ }
160
+
161
+ function addBurnable(c: ContractBuilder, pausable: boolean) {
162
+ c.addUseClause('stellar_non_fungible', 'burnable::NonFungibleBurnable');
163
+ c.addUseClause('soroban_sdk', 'Address');
164
+
165
+ const nonFungibleBurnableTrait = {
166
+ traitName: 'NonFungibleBurnable',
167
+ structName: c.name,
168
+ tags: ['contractimpl'],
169
+ section: 'Extensions',
170
+ };
171
+
172
+ c.addTraitFunction(nonFungibleBurnableTrait, burnableFunctions.burn);
173
+ c.addTraitFunction(nonFungibleBurnableTrait, burnableFunctions.burn_from);
174
+
175
+ if (pausable) {
176
+ c.addUseClause('stellar_pausable_macros', 'when_not_paused');
177
+ c.addFunctionTag(burnableFunctions.burn, 'when_not_paused', nonFungibleBurnableTrait);
178
+ c.addFunctionTag(burnableFunctions.burn_from, 'when_not_paused', nonFungibleBurnableTrait);
179
+ }
180
+ }
181
+
182
+ function addEnumerable(c: ContractBuilder, burnable: boolean) {
183
+ c.addUseClause('stellar_non_fungible', 'enumerable::{NonFungibleEnumerable, Enumerable}');
184
+ //c.addUseClause('stellar_default_impl_macro', 'default_impl');
185
+
186
+ const nonFungibleEnumerableTrait = {
187
+ traitName: 'NonFungibleEnumerable',
188
+ structName: c.name,
189
+ tags: ['defaultimpl', 'contractimpl'],
190
+ section: 'Extensions',
191
+ };
192
+ c.addTraitImplBlock(nonFungibleEnumerableTrait);
193
+
194
+ c.overrideAssocType('NonFungibleToken', 'type ContractType = Enumerable;');
195
+
196
+ if (burnable) {
197
+ c.overrideAssocType('NonFungibleBurnable', 'type ContractType = Enumerable;');
198
+ }
199
+
200
+ // Below is not required due to `defaultimpl` macro. If we require to customize the functions,
201
+ // then we should:
202
+ // 1. get rid of the `defaultimpl` macro form `tags` above,
203
+ // 2. get rid of `c.addImplementedTrait(nonFungibleEnumerableTrait);` line,
204
+ // 3. uncomment the section below:
205
+ // 4. uncomment `get_owner_token_id` and `get_token_id` from `enumerableFunctions` definition
206
+ /*
207
+ c.addFunction(nonFungibleEnumerableTrait, enumerableFunctions.total_supply);
208
+ c.addFunction(nonFungibleEnumerableTrait, enumerableFunctions.get_owner_token_id);
209
+ c.addFunction(nonFungibleEnumerableTrait, enumerableFunctions.get_token_id);
210
+ */
211
+ }
212
+
213
+ function addConsecutive(c: ContractBuilder, pausable: boolean, access: Access) {
214
+ c.addUseClause('stellar_non_fungible', 'consecutive::{NonFungibleConsecutive, Consecutive}');
215
+ c.addUseClause('stellar_non_fungible', 'ContractOverrides');
216
+
217
+ const nonFungibleConsecutiveTrait = {
218
+ traitName: 'NonFungibleConsecutive',
219
+ structName: c.name,
220
+ tags: ['contractimpl'],
221
+ section: 'Extensions',
222
+ };
223
+
224
+ c.addTraitImplBlock(nonFungibleConsecutiveTrait);
225
+
226
+ c.overrideAssocType('NonFungibleToken', 'type ContractType = Consecutive;');
227
+
228
+ c.addFreeFunction(consecutiveFunctions.batch_mint);
229
+ if (pausable) {
230
+ c.addFunctionTag(consecutiveFunctions.batch_mint, 'when_not_paused');
231
+ }
232
+
233
+ requireAccessControl(c, undefined, consecutiveFunctions.batch_mint, access);
234
+ }
235
+
236
+ function addMintable(c: ContractBuilder, enumerable: boolean, pausable: boolean, sequential: boolean, access: Access) {
237
+ if (!enumerable) {
238
+ if (sequential) {
239
+ c.addUseClause('stellar_non_fungible', 'Base::sequential_mint');
240
+ c.addFreeFunction(baseFunctions.sequential_mint);
241
+ requireAccessControl(c, undefined, baseFunctions.sequential_mint, access);
242
+ if (pausable) {
243
+ c.addFunctionTag(baseFunctions.sequential_mint, 'when_not_paused');
244
+ }
245
+ } else {
246
+ c.addUseClause('stellar_non_fungible', 'Base::mint');
247
+ c.addFreeFunction(baseFunctions.mint);
248
+ requireAccessControl(c, undefined, baseFunctions.mint, access);
249
+ if (pausable) {
250
+ c.addFunctionTag(baseFunctions.mint, 'when_not_paused');
251
+ }
252
+ }
253
+ }
254
+
255
+ if (enumerable) {
256
+ if (sequential) {
257
+ c.addFreeFunction(enumerableFunctions.sequential_mint);
258
+ requireAccessControl(c, undefined, enumerableFunctions.sequential_mint, access);
259
+ if (pausable) {
260
+ c.addFunctionTag(enumerableFunctions.sequential_mint, 'when_not_paused');
261
+ }
262
+ } else {
263
+ c.addFreeFunction(enumerableFunctions.non_sequential_mint);
264
+ requireAccessControl(c, undefined, enumerableFunctions.non_sequential_mint, access);
265
+ if (pausable) {
266
+ c.addFunctionTag(enumerableFunctions.non_sequential_mint, 'when_not_paused');
267
+ }
268
+ }
269
+ }
270
+ }
271
+
272
+ const baseFunctions = defineFunctions({
273
+ // NonFungible Trait
274
+ balance: {
275
+ args: [getSelfArg(), { name: 'owner', type: 'Address' }],
276
+ returns: 'u32',
277
+ code: ['Self::ContractType::balance(e, &owner)'],
278
+ },
279
+ owner_of: {
280
+ args: [getSelfArg(), { name: 'token_id', type: 'u32' }],
281
+ returns: 'Address',
282
+ code: ['Self::ContractType::owner_of(e, token_id)'],
283
+ },
284
+ transfer: {
285
+ args: [
286
+ getSelfArg(),
287
+ { name: 'from', type: 'Address' },
288
+ { name: 'to', type: 'Address' },
289
+ { name: 'token_id', type: 'u32' },
290
+ ],
291
+ code: ['Self::ContractType::transfer(e, &from, &to, token_id);'],
292
+ },
293
+ transfer_from: {
294
+ args: [
295
+ getSelfArg(),
296
+ { name: 'spender', type: 'Address' },
297
+ { name: 'from', type: 'Address' },
298
+ { name: 'to', type: 'Address' },
299
+ { name: 'token_id', type: 'u32' },
300
+ ],
301
+ code: ['Self::ContractType::transfer_from(e, &spender, &from, &to, token_id);'],
302
+ },
303
+ approve: {
304
+ args: [
305
+ getSelfArg(),
306
+ { name: 'approver', type: 'Address' },
307
+ { name: 'approved', type: 'Address' },
308
+ { name: 'token_id', type: 'u32' },
309
+ { name: 'live_until_ledger', type: 'u32' },
310
+ ],
311
+ code: ['Self::ContractType::approve(e, &approver, &approved, token_id, live_until_ledger)'],
312
+ },
313
+ approve_for_all: {
314
+ args: [
315
+ getSelfArg(),
316
+ { name: 'owner', type: 'Address' },
317
+ { name: 'operator', type: 'Address' },
318
+ { name: 'live_until_ledger', type: 'u32' },
319
+ ],
320
+ code: ['Self::ContractType::approve_for_all(e, &owner, &operator, live_until_ledger)'],
321
+ },
322
+ get_approved: {
323
+ args: [getSelfArg(), { name: 'token_id', type: 'u32' }],
324
+ returns: 'Option<Address>',
325
+ code: ['Self::ContractType::get_approved(e, token_id)'],
326
+ },
327
+ is_approved_for_all: {
328
+ args: [getSelfArg(), { name: 'owner', type: 'Address' }, { name: 'operator', type: 'Address' }],
329
+ returns: 'bool',
330
+ code: ['Self::ContractType::is_approved_for_all(e, &owner, &operator)'],
331
+ },
332
+ name: {
333
+ args: [getSelfArg()],
334
+ returns: 'String',
335
+ code: ['Self::ContractType::name(e)'],
336
+ },
337
+ symbol: {
338
+ args: [getSelfArg()],
339
+ returns: 'String',
340
+ code: ['Self::ContractType::symbol(e)'],
341
+ },
342
+ token_uri: {
343
+ args: [getSelfArg(), { name: 'token_id', type: 'u32' }],
344
+ returns: 'String',
345
+ code: ['Self::ContractType::token_uri(e, token_id)'],
346
+ },
347
+
348
+ // Mint
349
+ mint: {
350
+ args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'token_id', type: 'u32' }],
351
+ code: ['Base::mint(e, &to, token_id);'],
352
+ },
353
+ sequential_mint: {
354
+ args: [getSelfArg(), { name: 'to', type: 'Address' }],
355
+ code: ['Base::sequential_mint(e, &to);'],
356
+ },
357
+ });
358
+
359
+ const burnableFunctions = defineFunctions({
360
+ burn: {
361
+ args: [getSelfArg(), { name: 'from', type: 'Address' }, { name: 'token_id', type: 'u32' }],
362
+ code: ['Self::ContractType::burn(e, &from, token_id)'],
363
+ },
364
+ burn_from: {
365
+ args: [
366
+ getSelfArg(),
367
+ { name: 'spender', type: 'Address' },
368
+ { name: 'from', type: 'Address' },
369
+ { name: 'token_id', type: 'u32' },
370
+ ],
371
+ code: ['Self::ContractType::burn_from(e, &spender, &from, token_id)'],
372
+ },
373
+ });
374
+
375
+ const enumerableFunctions = defineFunctions({
376
+ total_supply: {
377
+ args: [getSelfArg()],
378
+ returns: 'u32',
379
+ code: ['non_fungible::enumerable::Enumerable::total_supply(e)'],
380
+ },
381
+ // These are not currently used, see addEnumerable() above
382
+ /*
383
+ get_owner_token_id: {
384
+ args: [getSelfArg(), { name: 'owner', type: 'Address' }, { name: 'index', type: 'u32' }],
385
+ returns: 'u32',
386
+ code: ['Enumerable::get_owner_token_id(e, &owner, index)'],
387
+ },
388
+ get_token_id: {
389
+ args: [getSelfArg(), { name: 'index', type: 'u32' }],
390
+ returns: 'u32',
391
+ code: ['Enumerable::get_token_id(e, index)'],
392
+ },
393
+ */
394
+ non_sequential_mint: {
395
+ args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'token_id', type: 'u32' }],
396
+ code: ['Enumerable::non_sequential_mint(e, &to, token_id);'], // TODO: unify `mint` name in Stellar-Contracts across extensions
397
+ },
398
+ sequential_mint: {
399
+ args: [getSelfArg(), { name: 'to', type: 'Address' }],
400
+ code: ['Enumerable::sequential_mint(e, &to);'],
401
+ },
402
+ });
403
+
404
+ const consecutiveFunctions = defineFunctions({
405
+ batch_mint: {
406
+ args: [getSelfArg(), { name: 'to', type: 'Address' }, { name: 'amount', type: 'u32' }],
407
+ returns: 'u32',
408
+ code: ['Consecutive::batch_mint(e, &to, amount);'],
409
+ },
410
+ });