@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.
- package/dist/add-pausable.d.ts.map +1 -1
- package/dist/add-pausable.js +29 -8
- package/dist/add-pausable.js.map +1 -1
- package/dist/add-upgradeable.d.ts.map +1 -1
- package/dist/add-upgradeable.js +14 -4
- package/dist/add-upgradeable.js.map +1 -1
- package/dist/api.d.ts +5 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +9 -1
- package/dist/api.js.map +1 -1
- package/dist/build-generic.d.ts +5 -1
- package/dist/build-generic.d.ts.map +1 -1
- package/dist/build-generic.js +3 -0
- package/dist/build-generic.js.map +1 -1
- package/dist/contract.d.ts +1 -1
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +9 -1
- package/dist/contract.js.map +1 -1
- package/dist/fungible.d.ts +5 -2
- package/dist/fungible.d.ts.map +1 -1
- package/dist/fungible.js +86 -55
- package/dist/fungible.js.map +1 -1
- package/dist/generate/sources.d.ts.map +1 -1
- package/dist/generate/sources.js +6 -0
- package/dist/generate/sources.js.map +1 -1
- package/dist/generate/stablecoin.d.ts +3 -0
- package/dist/generate/stablecoin.d.ts.map +1 -0
- package/dist/generate/stablecoin.js +24 -0
- package/dist/generate/stablecoin.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/kind.js +1 -0
- package/dist/kind.js.map +1 -1
- package/dist/non-fungible.d.ts +1 -0
- package/dist/non-fungible.d.ts.map +1 -1
- package/dist/non-fungible.js +101 -81
- package/dist/non-fungible.js.map +1 -1
- package/dist/print.js +5 -5
- package/dist/print.js.map +1 -1
- package/dist/set-access-control.d.ts +7 -4
- package/dist/set-access-control.d.ts.map +1 -1
- package/dist/set-access-control.js +57 -15
- package/dist/set-access-control.js.map +1 -1
- package/dist/stablecoin.d.ts +11 -0
- package/dist/stablecoin.d.ts.map +1 -0
- package/dist/stablecoin.js +103 -0
- package/dist/stablecoin.js.map +1 -0
- package/dist/utils/define-functions.d.ts +4 -2
- package/dist/utils/define-functions.d.ts.map +1 -1
- package/dist/utils/define-functions.js +7 -1
- package/dist/utils/define-functions.js.map +1 -1
- package/dist/utils/version.d.ts +3 -3
- package/dist/utils/version.js +2 -2
- package/dist/zip-rust.d.ts +2 -1
- package/dist/zip-rust.d.ts.map +1 -1
- package/dist/zip-rust.js +8 -5
- package/dist/zip-rust.js.map +1 -1
- package/dist/zip-scaffold.d.ts +2 -2
- package/dist/zip-scaffold.d.ts.map +1 -1
- package/dist/zip-scaffold.js +14 -158
- package/dist/zip-scaffold.js.map +1 -1
- package/dist/zip-shared.d.ts +4 -17
- package/dist/zip-shared.d.ts.map +1 -1
- package/dist/zip-shared.js +25 -19
- package/dist/zip-shared.js.map +1 -1
- package/package.json +1 -1
- package/src/add-pausable.ts +31 -9
- package/src/add-upgradeable.ts +17 -5
- package/src/api.ts +27 -4
- package/src/build-generic.ts +6 -0
- package/src/contract.ts +9 -2
- package/src/fungible.ts +90 -61
- package/src/generate/sources.ts +7 -0
- package/src/generate/stablecoin.ts +23 -0
- package/src/index.ts +2 -0
- package/src/kind.ts +1 -0
- package/src/non-fungible.ts +108 -87
- package/src/print.ts +5 -5
- package/src/set-access-control.ts +72 -19
- package/src/stablecoin.ts +124 -0
- package/src/utils/define-functions.ts +11 -4
- package/src/utils/version.ts +2 -2
- package/src/zip-rust.ts +10 -6
- package/src/zip-scaffold.ts +15 -169
- 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,
|
|
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
|
|
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('
|
|
95
|
-
c.addUseClause('
|
|
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.
|
|
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('
|
|
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('
|
|
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('
|
|
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(`
|
|
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
|
-
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
296
|
+
code: ['Self::ContractType::decimals(e)'],
|
|
278
297
|
},
|
|
279
298
|
name: {
|
|
280
299
|
args: [getSelfArg()],
|
|
281
300
|
returns: 'String',
|
|
282
|
-
code: ['
|
|
301
|
+
code: ['Self::ContractType::name(e)'],
|
|
283
302
|
},
|
|
284
303
|
symbol: {
|
|
285
304
|
args: [getSelfArg()],
|
|
286
305
|
returns: 'String',
|
|
287
|
-
code: ['
|
|
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: ['
|
|
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: ['
|
|
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: ['
|
|
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
|
});
|
package/src/generate/sources.ts
CHANGED
|
@@ -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
package/src/non-fungible.ts
CHANGED
|
@@ -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
|
-
|
|
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('
|
|
126
|
-
c.addUseClause('
|
|
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
|
-
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
184
|
-
c.addUseClause('
|
|
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('
|
|
212
|
-
c.addUseClause('
|
|
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
|
-
|
|
213
|
+
const mintFn = access === 'ownable' ? consecutiveFunctions.batch_mint : consecutiveFunctions.batch_mint_with_caller;
|
|
214
|
+
c.addFreeFunction(mintFn);
|
|
226
215
|
if (pausable) {
|
|
227
|
-
c.addFunctionTag(
|
|
216
|
+
c.addFunctionTag(mintFn, 'when_not_paused');
|
|
228
217
|
}
|
|
229
218
|
|
|
230
|
-
requireAccessControl(c, undefined,
|
|
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
|
-
|
|
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
|
-
|
|
237
|
-
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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);'],
|
|
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
|
});
|