@buildonspark/issuer-sdk 0.1.0 → 0.1.2
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/CHANGELOG.md +23 -0
- package/dist/index.browser.d.ts +5 -1
- package/dist/index.browser.js +36 -11
- package/dist/index.node.cjs +36 -11
- package/dist/index.node.d.cts +5 -1
- package/dist/index.node.d.ts +5 -1
- package/dist/index.node.js +36 -11
- package/dist/native/index.react-native.cjs +36 -11
- package/dist/native/index.react-native.d.cts +5 -1
- package/dist/native/index.react-native.d.ts +5 -1
- package/dist/native/index.react-native.js +36 -11
- package/dist/proto/spark.d.cts +1 -1
- package/dist/proto/spark.d.ts +1 -1
- package/package.json +3 -3
- package/src/issuer-wallet/issuer-spark-wallet.ts +16 -1
- package/src/issuer-wallet/types.ts +2 -0
- package/src/services/token-transactions.ts +4 -0
- package/src/tests/integration/nft-creation.test.ts +86 -0
- package/src/tests/integration/test-configs.ts +32 -0
- package/src/tests/integration/token-creation.test.ts +1 -16
- package/src/tests/integration/token-invoices.test.ts +1 -17
- package/src/tests/integration/token-lifecycle.test.ts +2 -20
- package/src/tests/integration/token-minting.test.ts +1 -16
- package/src/tests/integration/token-monitoring.test.ts +5 -22
- package/src/tests/integration/token-outputs.test.ts +2 -20
- package/src/tests/integration/token-transfers.test.ts +2 -20
- package/src/utils/create-validation.ts +13 -0
|
@@ -38,6 +38,8 @@ type IssuerTokenMetadata = {
|
|
|
38
38
|
maxSupply: bigint;
|
|
39
39
|
/** Whether the token is freezable */
|
|
40
40
|
isFreezable: boolean;
|
|
41
|
+
/** Extra metadata of the token */
|
|
42
|
+
extraMetadata?: Uint8Array;
|
|
41
43
|
};
|
|
42
44
|
interface TokenDistribution {
|
|
43
45
|
totalCirculatingSupply: bigint;
|
|
@@ -90,18 +92,20 @@ declare abstract class IssuerSparkWallet extends SparkWallet {
|
|
|
90
92
|
* @param params.decimals - The number of decimal places for the token.
|
|
91
93
|
* @param params.isFreezable - Whether the token can be frozen.
|
|
92
94
|
* @param [params.maxSupply=0n] - (Optional) The maximum supply of the token. Defaults to <code>0n</code>.
|
|
95
|
+
* @param params.extraMetadata - (Optional) This can be used to store additional bytes data to be associated with a token, like image data.
|
|
93
96
|
*
|
|
94
97
|
* @returns The transaction ID of the announcement.
|
|
95
98
|
*
|
|
96
99
|
* @throws {SparkValidationError} If `decimals` is not a safe integer or other validation fails.
|
|
97
100
|
* @throws {SparkRequestError} If the announcement transaction cannot be broadcast.
|
|
98
101
|
*/
|
|
99
|
-
createToken({ tokenName, tokenTicker, decimals, isFreezable, maxSupply, }: {
|
|
102
|
+
createToken({ tokenName, tokenTicker, decimals, isFreezable, maxSupply, extraMetadata, }: {
|
|
100
103
|
tokenName: string;
|
|
101
104
|
tokenTicker: string;
|
|
102
105
|
decimals: number;
|
|
103
106
|
isFreezable: boolean;
|
|
104
107
|
maxSupply?: bigint;
|
|
108
|
+
extraMetadata?: Uint8Array;
|
|
105
109
|
}): Promise<string>;
|
|
106
110
|
/**
|
|
107
111
|
* Mints new tokens
|
|
@@ -215,7 +215,7 @@ var IssuerTokenTransactionService = class extends TokenTransactionService {
|
|
|
215
215
|
]
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
|
-
async constructCreateTokenTransaction(tokenPublicKey, tokenName, tokenTicker, decimals, maxSupply, isFreezable) {
|
|
218
|
+
async constructCreateTokenTransaction(tokenPublicKey, tokenName, tokenTicker, decimals, maxSupply, isFreezable, extraMetadata) {
|
|
219
219
|
return {
|
|
220
220
|
version: 2,
|
|
221
221
|
network: this.config.getNetworkProto(),
|
|
@@ -227,7 +227,8 @@ var IssuerTokenTransactionService = class extends TokenTransactionService {
|
|
|
227
227
|
tokenTicker,
|
|
228
228
|
decimals,
|
|
229
229
|
maxSupply: numberToBytesBE(maxSupply, 16),
|
|
230
|
-
isFreezable
|
|
230
|
+
isFreezable,
|
|
231
|
+
extraMetadata
|
|
231
232
|
}
|
|
232
233
|
},
|
|
233
234
|
tokenOutputs: [],
|
|
@@ -237,7 +238,7 @@ var IssuerTokenTransactionService = class extends TokenTransactionService {
|
|
|
237
238
|
invoiceAttachments: []
|
|
238
239
|
};
|
|
239
240
|
}
|
|
240
|
-
async constructPartialCreateTokenTransaction(tokenPublicKey, tokenName, tokenTicker, decimals, maxSupply, isFreezable) {
|
|
241
|
+
async constructPartialCreateTokenTransaction(tokenPublicKey, tokenName, tokenTicker, decimals, maxSupply, isFreezable, extraMetadata) {
|
|
241
242
|
return {
|
|
242
243
|
version: 3,
|
|
243
244
|
tokenTransactionMetadata: {
|
|
@@ -255,7 +256,8 @@ var IssuerTokenTransactionService = class extends TokenTransactionService {
|
|
|
255
256
|
tokenTicker,
|
|
256
257
|
decimals,
|
|
257
258
|
maxSupply: numberToBytesBE(maxSupply, 16),
|
|
258
|
-
isFreezable
|
|
259
|
+
isFreezable,
|
|
260
|
+
extraMetadata
|
|
259
261
|
}
|
|
260
262
|
},
|
|
261
263
|
partialTokenOutputs: []
|
|
@@ -274,7 +276,8 @@ var MIN_SYMBOL_SIZE = 3;
|
|
|
274
276
|
var MAX_SYMBOL_SIZE = 6;
|
|
275
277
|
var MAX_DECIMALS = 255;
|
|
276
278
|
var MAXIMUM_MAX_SUPPLY = (1n << 128n) - 1n;
|
|
277
|
-
|
|
279
|
+
var MAX_TOKEN_CONTENT_SIZE = 1024;
|
|
280
|
+
function validateTokenParameters(tokenName, tokenTicker, decimals, maxSupply, extraMetadata) {
|
|
278
281
|
if (!isNfcNormalized(tokenName)) {
|
|
279
282
|
throw new SparkValidationError2("Token name must be NFC-normalised UTF-8", {
|
|
280
283
|
field: "tokenName",
|
|
@@ -333,6 +336,16 @@ function validateTokenParameters(tokenName, tokenTicker, decimals, maxSupply) {
|
|
|
333
336
|
expected: `>=0 and <=${MAXIMUM_MAX_SUPPLY.toString()}`
|
|
334
337
|
});
|
|
335
338
|
}
|
|
339
|
+
if (extraMetadata && extraMetadata.length > MAX_TOKEN_CONTENT_SIZE) {
|
|
340
|
+
throw new SparkValidationError2(
|
|
341
|
+
`Extra metadata must be less than ${MAX_TOKEN_CONTENT_SIZE} bytes`,
|
|
342
|
+
{
|
|
343
|
+
field: "extraMetadata",
|
|
344
|
+
value: extraMetadata.length,
|
|
345
|
+
expected: `<${MAX_TOKEN_CONTENT_SIZE}`
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
}
|
|
336
349
|
}
|
|
337
350
|
|
|
338
351
|
// src/issuer-wallet/issuer-spark-wallet.ts
|
|
@@ -398,7 +411,8 @@ var IssuerSparkWallet = class extends SparkWallet {
|
|
|
398
411
|
tokenTicker: metadata.tokenTicker,
|
|
399
412
|
decimals: metadata.decimals,
|
|
400
413
|
maxSupply: bytesToNumberBE(metadata.maxSupply),
|
|
401
|
-
isFreezable: metadata.isFreezable
|
|
414
|
+
isFreezable: metadata.isFreezable,
|
|
415
|
+
extraMetadata: metadata.extraMetadata ? new Uint8Array(metadata.extraMetadata) : void 0
|
|
402
416
|
};
|
|
403
417
|
}
|
|
404
418
|
const sparkTokenClient = await this.connectionManager.createSparkTokenClient(
|
|
@@ -433,7 +447,8 @@ var IssuerSparkWallet = class extends SparkWallet {
|
|
|
433
447
|
tokenTicker: metadata.tokenTicker,
|
|
434
448
|
decimals: metadata.decimals,
|
|
435
449
|
maxSupply: bytesToNumberBE(metadata.maxSupply),
|
|
436
|
-
isFreezable: metadata.isFreezable
|
|
450
|
+
isFreezable: metadata.isFreezable,
|
|
451
|
+
extraMetadata: metadata.extraMetadata
|
|
437
452
|
};
|
|
438
453
|
} catch (error) {
|
|
439
454
|
throw new SparkRequestError2("Failed to fetch token metadata", { error });
|
|
@@ -460,6 +475,7 @@ var IssuerSparkWallet = class extends SparkWallet {
|
|
|
460
475
|
* @param params.decimals - The number of decimal places for the token.
|
|
461
476
|
* @param params.isFreezable - Whether the token can be frozen.
|
|
462
477
|
* @param [params.maxSupply=0n] - (Optional) The maximum supply of the token. Defaults to <code>0n</code>.
|
|
478
|
+
* @param params.extraMetadata - (Optional) This can be used to store additional bytes data to be associated with a token, like image data.
|
|
463
479
|
*
|
|
464
480
|
* @returns The transaction ID of the announcement.
|
|
465
481
|
*
|
|
@@ -471,9 +487,16 @@ var IssuerSparkWallet = class extends SparkWallet {
|
|
|
471
487
|
tokenTicker,
|
|
472
488
|
decimals,
|
|
473
489
|
isFreezable,
|
|
474
|
-
maxSupply = 0n
|
|
490
|
+
maxSupply = 0n,
|
|
491
|
+
extraMetadata
|
|
475
492
|
}) {
|
|
476
|
-
validateTokenParameters(
|
|
493
|
+
validateTokenParameters(
|
|
494
|
+
tokenName,
|
|
495
|
+
tokenTicker,
|
|
496
|
+
decimals,
|
|
497
|
+
maxSupply,
|
|
498
|
+
extraMetadata
|
|
499
|
+
);
|
|
477
500
|
const issuerPublicKey = await super.getIdentityPublicKey();
|
|
478
501
|
if (this.config.getTokenTransactionVersion() === "V2") {
|
|
479
502
|
const tokenTransaction = await this.issuerTokenTransactionService.constructCreateTokenTransaction(
|
|
@@ -482,7 +505,8 @@ var IssuerSparkWallet = class extends SparkWallet {
|
|
|
482
505
|
tokenTicker,
|
|
483
506
|
decimals,
|
|
484
507
|
maxSupply,
|
|
485
|
-
isFreezable
|
|
508
|
+
isFreezable,
|
|
509
|
+
extraMetadata
|
|
486
510
|
);
|
|
487
511
|
return await this.issuerTokenTransactionService.broadcastTokenTransaction(
|
|
488
512
|
tokenTransaction
|
|
@@ -494,7 +518,8 @@ var IssuerSparkWallet = class extends SparkWallet {
|
|
|
494
518
|
tokenTicker,
|
|
495
519
|
decimals,
|
|
496
520
|
maxSupply,
|
|
497
|
-
isFreezable
|
|
521
|
+
isFreezable,
|
|
522
|
+
extraMetadata
|
|
498
523
|
);
|
|
499
524
|
return await this.issuerTokenTransactionService.broadcastTokenTransactionV3(
|
|
500
525
|
partialTokenTransaction
|
package/dist/proto/spark.d.cts
CHANGED
package/dist/proto/spark.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buildonspark/issuer-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Spark Issuer SDK for token issuance",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.browser.js",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"types": "tsc"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@buildonspark/spark-sdk": "0.5.
|
|
79
|
+
"@buildonspark/spark-sdk": "0.5.2",
|
|
80
80
|
"@noble/curves": "^1.8.0",
|
|
81
81
|
"@scure/btc-signer": "^1.5.0",
|
|
82
82
|
"buffer": "^6.0.3"
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"jest": "^29.7.0",
|
|
91
91
|
"madge": "^8.0.0",
|
|
92
92
|
"node-fetch": "^3.3.2",
|
|
93
|
-
"prettier": "^3.
|
|
93
|
+
"prettier": "^3.7.4",
|
|
94
94
|
"publint": "^0.3.9",
|
|
95
95
|
"react": "19.0.0",
|
|
96
96
|
"react-native": "0.79.4",
|
|
@@ -97,6 +97,9 @@ export abstract class IssuerSparkWallet extends SparkWallet {
|
|
|
97
97
|
decimals: metadata.decimals,
|
|
98
98
|
maxSupply: bytesToNumberBE(metadata.maxSupply),
|
|
99
99
|
isFreezable: metadata.isFreezable,
|
|
100
|
+
extraMetadata: metadata.extraMetadata
|
|
101
|
+
? new Uint8Array(metadata.extraMetadata)
|
|
102
|
+
: undefined,
|
|
100
103
|
};
|
|
101
104
|
}
|
|
102
105
|
|
|
@@ -135,6 +138,7 @@ export abstract class IssuerSparkWallet extends SparkWallet {
|
|
|
135
138
|
decimals: metadata.decimals,
|
|
136
139
|
maxSupply: bytesToNumberBE(metadata.maxSupply),
|
|
137
140
|
isFreezable: metadata.isFreezable,
|
|
141
|
+
extraMetadata: metadata.extraMetadata,
|
|
138
142
|
};
|
|
139
143
|
} catch (error) {
|
|
140
144
|
throw new SparkRequestError("Failed to fetch token metadata", { error });
|
|
@@ -164,6 +168,7 @@ export abstract class IssuerSparkWallet extends SparkWallet {
|
|
|
164
168
|
* @param params.decimals - The number of decimal places for the token.
|
|
165
169
|
* @param params.isFreezable - Whether the token can be frozen.
|
|
166
170
|
* @param [params.maxSupply=0n] - (Optional) The maximum supply of the token. Defaults to <code>0n</code>.
|
|
171
|
+
* @param params.extraMetadata - (Optional) This can be used to store additional bytes data to be associated with a token, like image data.
|
|
167
172
|
*
|
|
168
173
|
* @returns The transaction ID of the announcement.
|
|
169
174
|
*
|
|
@@ -176,14 +181,22 @@ export abstract class IssuerSparkWallet extends SparkWallet {
|
|
|
176
181
|
decimals,
|
|
177
182
|
isFreezable,
|
|
178
183
|
maxSupply = 0n,
|
|
184
|
+
extraMetadata,
|
|
179
185
|
}: {
|
|
180
186
|
tokenName: string;
|
|
181
187
|
tokenTicker: string;
|
|
182
188
|
decimals: number;
|
|
183
189
|
isFreezable: boolean;
|
|
184
190
|
maxSupply?: bigint;
|
|
191
|
+
extraMetadata?: Uint8Array;
|
|
185
192
|
}): Promise<string> {
|
|
186
|
-
validateTokenParameters(
|
|
193
|
+
validateTokenParameters(
|
|
194
|
+
tokenName,
|
|
195
|
+
tokenTicker,
|
|
196
|
+
decimals,
|
|
197
|
+
maxSupply,
|
|
198
|
+
extraMetadata,
|
|
199
|
+
);
|
|
187
200
|
|
|
188
201
|
const issuerPublicKey = await super.getIdentityPublicKey();
|
|
189
202
|
|
|
@@ -196,6 +209,7 @@ export abstract class IssuerSparkWallet extends SparkWallet {
|
|
|
196
209
|
decimals,
|
|
197
210
|
maxSupply,
|
|
198
211
|
isFreezable,
|
|
212
|
+
extraMetadata,
|
|
199
213
|
);
|
|
200
214
|
|
|
201
215
|
return await this.issuerTokenTransactionService.broadcastTokenTransaction(
|
|
@@ -210,6 +224,7 @@ export abstract class IssuerSparkWallet extends SparkWallet {
|
|
|
210
224
|
decimals,
|
|
211
225
|
maxSupply,
|
|
212
226
|
isFreezable,
|
|
227
|
+
extraMetadata,
|
|
213
228
|
);
|
|
214
229
|
|
|
215
230
|
return await this.issuerTokenTransactionService.broadcastTokenTransactionV3(
|
|
@@ -90,6 +90,7 @@ export class IssuerTokenTransactionService extends TokenTransactionService {
|
|
|
90
90
|
decimals: number,
|
|
91
91
|
maxSupply: bigint,
|
|
92
92
|
isFreezable: boolean,
|
|
93
|
+
extraMetadata: Uint8Array | undefined,
|
|
93
94
|
): Promise<TokenTransaction> {
|
|
94
95
|
return {
|
|
95
96
|
version: 2,
|
|
@@ -103,6 +104,7 @@ export class IssuerTokenTransactionService extends TokenTransactionService {
|
|
|
103
104
|
decimals: decimals,
|
|
104
105
|
maxSupply: numberToBytesBE(maxSupply, 16),
|
|
105
106
|
isFreezable: isFreezable,
|
|
107
|
+
extraMetadata: extraMetadata,
|
|
106
108
|
},
|
|
107
109
|
},
|
|
108
110
|
tokenOutputs: [],
|
|
@@ -121,6 +123,7 @@ export class IssuerTokenTransactionService extends TokenTransactionService {
|
|
|
121
123
|
decimals: number,
|
|
122
124
|
maxSupply: bigint,
|
|
123
125
|
isFreezable: boolean,
|
|
126
|
+
extraMetadata?: Uint8Array,
|
|
124
127
|
): Promise<PartialTokenTransaction> {
|
|
125
128
|
return {
|
|
126
129
|
version: 3,
|
|
@@ -142,6 +145,7 @@ export class IssuerTokenTransactionService extends TokenTransactionService {
|
|
|
142
145
|
decimals: decimals,
|
|
143
146
|
maxSupply: numberToBytesBE(maxSupply, 16),
|
|
144
147
|
isFreezable: isFreezable,
|
|
148
|
+
extraMetadata: extraMetadata,
|
|
145
149
|
},
|
|
146
150
|
},
|
|
147
151
|
partialTokenOutputs: [],
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jest } from "@jest/globals";
|
|
2
|
+
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
3
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
4
|
+
import { MAX_TOKEN_CONTENT_SIZE } from "../../utils/create-validation.js";
|
|
5
|
+
|
|
6
|
+
describe.each(TEST_CONFIGS)(
|
|
7
|
+
"nft creation tests - $name",
|
|
8
|
+
({ name, config }) => {
|
|
9
|
+
jest.setTimeout(80000);
|
|
10
|
+
|
|
11
|
+
it("should create an nft", async () => {
|
|
12
|
+
const { wallet: issuerWallet } =
|
|
13
|
+
await IssuerSparkWalletTesting.initialize({
|
|
14
|
+
options: config,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const tokenName = `${name}NFT`;
|
|
18
|
+
const tokenTicker = "NFT";
|
|
19
|
+
const extraMetadata = new Uint8Array([1, 2, 3]);
|
|
20
|
+
const createTransactionId = await issuerWallet.createToken({
|
|
21
|
+
tokenName,
|
|
22
|
+
tokenTicker,
|
|
23
|
+
decimals: 0,
|
|
24
|
+
isFreezable: false,
|
|
25
|
+
maxSupply: 1n,
|
|
26
|
+
extraMetadata,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
expect(typeof createTransactionId).toBe("string");
|
|
30
|
+
expect(createTransactionId.length).toBeGreaterThan(0);
|
|
31
|
+
|
|
32
|
+
const metadata = await issuerWallet.getIssuerTokenMetadata();
|
|
33
|
+
expect(metadata.tokenName).toEqual(tokenName);
|
|
34
|
+
expect(metadata.tokenTicker).toEqual(tokenTicker);
|
|
35
|
+
expect(metadata.maxSupply).toEqual(1n);
|
|
36
|
+
expect(metadata.decimals).toEqual(0);
|
|
37
|
+
expect(Array.from(metadata.extraMetadata!)).toEqual(
|
|
38
|
+
Array.from(extraMetadata),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const txId = await issuerWallet.mintTokens(1n);
|
|
42
|
+
expect(typeof txId).toBe("string");
|
|
43
|
+
expect(txId.length).toBeGreaterThan(0);
|
|
44
|
+
|
|
45
|
+
const tokenIdentifier = await issuerWallet.getIssuerTokenIdentifier();
|
|
46
|
+
expect(tokenIdentifier).toBeDefined();
|
|
47
|
+
expect(tokenIdentifier!.length).toBeGreaterThan(0);
|
|
48
|
+
|
|
49
|
+
const { balance: satsBalance, tokenBalances: tokenBalancesMap } =
|
|
50
|
+
await issuerWallet.getBalance();
|
|
51
|
+
expect(satsBalance).toEqual(0n);
|
|
52
|
+
expect(tokenBalancesMap.size).toEqual(1);
|
|
53
|
+
expect(tokenBalancesMap.get(tokenIdentifier)).toBeDefined();
|
|
54
|
+
expect(tokenBalancesMap.get(tokenIdentifier)?.balance).toEqual(1n);
|
|
55
|
+
|
|
56
|
+
const tokenMetadata =
|
|
57
|
+
tokenBalancesMap.get(tokenIdentifier)?.tokenMetadata;
|
|
58
|
+
expect(tokenMetadata).toBeDefined();
|
|
59
|
+
expect(tokenMetadata?.tokenName).toEqual(tokenName);
|
|
60
|
+
expect(tokenMetadata?.tokenTicker).toEqual(tokenTicker);
|
|
61
|
+
expect(tokenMetadata?.maxSupply).toEqual(1n);
|
|
62
|
+
expect(tokenMetadata?.decimals).toEqual(0);
|
|
63
|
+
expect(tokenMetadata?.extraMetadata).toEqual(extraMetadata);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should fail to create an nft with extra metadata longer than MAX_TOKEN_CONTENT_SIZE bytes", async () => {
|
|
67
|
+
const { wallet: issuerWallet } =
|
|
68
|
+
await IssuerSparkWalletTesting.initialize({
|
|
69
|
+
options: config,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const extraMetadata = new Uint8Array(MAX_TOKEN_CONTENT_SIZE + 1);
|
|
73
|
+
|
|
74
|
+
await expect(
|
|
75
|
+
issuerWallet.createToken({
|
|
76
|
+
tokenName: "NFTLONGMETADATA",
|
|
77
|
+
tokenTicker: "NFTLONG",
|
|
78
|
+
decimals: 0,
|
|
79
|
+
isFreezable: false,
|
|
80
|
+
maxSupply: 1n,
|
|
81
|
+
extraMetadata,
|
|
82
|
+
}),
|
|
83
|
+
).rejects.toThrow();
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ConfigOptions, WalletConfig } from "@buildonspark/spark-sdk";
|
|
2
|
+
|
|
3
|
+
export const TOKENS_SCHNORR_V2_CONFIG: Required<ConfigOptions> = {
|
|
4
|
+
...WalletConfig.LOCAL,
|
|
5
|
+
tokenSignatures: "SCHNORR",
|
|
6
|
+
tokenTransactionVersion: "V2",
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const TOKENS_SCHNORR_V3_CONFIG: Required<ConfigOptions> = {
|
|
10
|
+
...WalletConfig.LOCAL,
|
|
11
|
+
tokenSignatures: "SCHNORR",
|
|
12
|
+
tokenTransactionVersion: "V3",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const TOKENS_ECDSA_V2_CONFIG: Required<ConfigOptions> = {
|
|
16
|
+
...WalletConfig.LOCAL,
|
|
17
|
+
tokenSignatures: "ECDSA",
|
|
18
|
+
tokenTransactionVersion: "V2",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const TOKENS_ECDSA_V3_CONFIG: Required<ConfigOptions> = {
|
|
22
|
+
...WalletConfig.LOCAL,
|
|
23
|
+
tokenSignatures: "ECDSA",
|
|
24
|
+
tokenTransactionVersion: "V3",
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const TEST_CONFIGS = [
|
|
28
|
+
{ name: "E2", config: TOKENS_ECDSA_V2_CONFIG },
|
|
29
|
+
{ name: "E3", config: TOKENS_ECDSA_V3_CONFIG },
|
|
30
|
+
{ name: "S2", config: TOKENS_SCHNORR_V2_CONFIG },
|
|
31
|
+
{ name: "S3", config: TOKENS_SCHNORR_V3_CONFIG },
|
|
32
|
+
];
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
-
import { ConfigOptions, WalletConfig } from "@buildonspark/spark-sdk";
|
|
2
1
|
import { jest } from "@jest/globals";
|
|
3
2
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
4
|
-
|
|
5
|
-
export const TOKENS_SCHNORR_CONFIG: Required<ConfigOptions> = {
|
|
6
|
-
...WalletConfig.LOCAL,
|
|
7
|
-
tokenSignatures: "SCHNORR",
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const TOKENS_ECDSA_CONFIG: Required<ConfigOptions> = {
|
|
11
|
-
...WalletConfig.LOCAL,
|
|
12
|
-
tokenSignatures: "ECDSA",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const TEST_CONFIGS = [
|
|
16
|
-
{ name: "TE", config: TOKENS_ECDSA_CONFIG },
|
|
17
|
-
{ name: "TS", config: TOKENS_SCHNORR_CONFIG },
|
|
18
|
-
];
|
|
3
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
19
4
|
|
|
20
5
|
describe.each(TEST_CONFIGS)(
|
|
21
6
|
"token creation tests - $name",
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ConfigOptions,
|
|
3
2
|
filterTokenBalanceForTokenIdentifier,
|
|
4
3
|
SparkRequestError,
|
|
5
|
-
WalletConfig,
|
|
6
4
|
} from "@buildonspark/spark-sdk";
|
|
7
5
|
import { jest } from "@jest/globals";
|
|
8
6
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
@@ -11,21 +9,7 @@ import {
|
|
|
11
9
|
SparkWalletTesting,
|
|
12
10
|
} from "@buildonspark/spark-sdk/test-utils";
|
|
13
11
|
import { InvoiceStatus } from "@buildonspark/spark-sdk/proto/spark";
|
|
14
|
-
|
|
15
|
-
export const TOKENS_SCHNORR_CONFIG: Required<ConfigOptions> = {
|
|
16
|
-
...WalletConfig.LOCAL,
|
|
17
|
-
tokenSignatures: "SCHNORR",
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const TOKENS_ECDSA_CONFIG: Required<ConfigOptions> = {
|
|
21
|
-
...WalletConfig.LOCAL,
|
|
22
|
-
tokenSignatures: "ECDSA",
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const TEST_CONFIGS = [
|
|
26
|
-
{ name: "TE", config: TOKENS_ECDSA_CONFIG },
|
|
27
|
-
{ name: "TS", config: TOKENS_SCHNORR_CONFIG },
|
|
28
|
-
];
|
|
12
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
29
13
|
|
|
30
14
|
describe.each(TEST_CONFIGS)(
|
|
31
15
|
"token invoice tests - $name",
|
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConfigOptions,
|
|
3
|
-
filterTokenBalanceForTokenIdentifier,
|
|
4
|
-
WalletConfig,
|
|
5
|
-
} from "@buildonspark/spark-sdk";
|
|
1
|
+
import { filterTokenBalanceForTokenIdentifier } from "@buildonspark/spark-sdk";
|
|
6
2
|
import { jest } from "@jest/globals";
|
|
7
3
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
8
4
|
import { SparkWalletTesting } from "@buildonspark/spark-sdk/test-utils";
|
|
9
|
-
|
|
10
|
-
export const TOKENS_SCHNORR_CONFIG: Required<ConfigOptions> = {
|
|
11
|
-
...WalletConfig.LOCAL,
|
|
12
|
-
tokenSignatures: "SCHNORR",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const TOKENS_ECDSA_CONFIG: Required<ConfigOptions> = {
|
|
16
|
-
...WalletConfig.LOCAL,
|
|
17
|
-
tokenSignatures: "ECDSA",
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const TEST_CONFIGS = [
|
|
21
|
-
{ name: "TE", config: TOKENS_ECDSA_CONFIG },
|
|
22
|
-
{ name: "TS", config: TOKENS_SCHNORR_CONFIG },
|
|
23
|
-
];
|
|
5
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
24
6
|
|
|
25
7
|
describe.each(TEST_CONFIGS)(
|
|
26
8
|
"token lifecycle tests - $name",
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
-
import { ConfigOptions, WalletConfig } from "@buildonspark/spark-sdk";
|
|
2
1
|
import { jest } from "@jest/globals";
|
|
3
2
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
4
|
-
|
|
5
|
-
export const TOKENS_SCHNORR_CONFIG: Required<ConfigOptions> = {
|
|
6
|
-
...WalletConfig.LOCAL,
|
|
7
|
-
tokenSignatures: "SCHNORR",
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const TOKENS_ECDSA_CONFIG: Required<ConfigOptions> = {
|
|
11
|
-
...WalletConfig.LOCAL,
|
|
12
|
-
tokenSignatures: "ECDSA",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const TEST_CONFIGS = [
|
|
16
|
-
{ name: "TE", config: TOKENS_ECDSA_CONFIG },
|
|
17
|
-
{ name: "TS", config: TOKENS_SCHNORR_CONFIG },
|
|
18
|
-
];
|
|
3
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
19
4
|
|
|
20
5
|
describe.each(TEST_CONFIGS)(
|
|
21
6
|
"token minting tests - $name",
|
|
@@ -1,27 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConfigOptions,
|
|
3
|
-
filterTokenBalanceForTokenIdentifier,
|
|
4
|
-
WalletConfig,
|
|
5
|
-
} from "@buildonspark/spark-sdk";
|
|
1
|
+
import { filterTokenBalanceForTokenIdentifier } from "@buildonspark/spark-sdk";
|
|
6
2
|
import { jest } from "@jest/globals";
|
|
7
3
|
import { bytesToHex } from "@noble/curves/utils";
|
|
8
4
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
9
5
|
import { SparkWalletTesting } from "@buildonspark/spark-sdk/test-utils";
|
|
10
|
-
|
|
11
|
-
export const TOKENS_SCHNORR_CONFIG: Required<ConfigOptions> = {
|
|
12
|
-
...WalletConfig.LOCAL,
|
|
13
|
-
tokenSignatures: "SCHNORR",
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const TOKENS_ECDSA_CONFIG: Required<ConfigOptions> = {
|
|
17
|
-
...WalletConfig.LOCAL,
|
|
18
|
-
tokenSignatures: "ECDSA",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const TEST_CONFIGS = [
|
|
22
|
-
{ name: "TE", config: TOKENS_ECDSA_CONFIG },
|
|
23
|
-
{ name: "TS", config: TOKENS_SCHNORR_CONFIG },
|
|
24
|
-
];
|
|
6
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
25
7
|
|
|
26
8
|
describe.each(TEST_CONFIGS)(
|
|
27
9
|
"token monitoring tests - $name",
|
|
@@ -202,9 +184,10 @@ describe.each(TEST_CONFIGS)(
|
|
|
202
184
|
}
|
|
203
185
|
|
|
204
186
|
for (let index = 0; index < 100; ++index) {
|
|
205
|
-
|
|
187
|
+
const dynamicAmount = BigInt(index + 1);
|
|
188
|
+
await issuerWallet.mintTokens(dynamicAmount);
|
|
206
189
|
await issuerWallet.transferTokens({
|
|
207
|
-
tokenAmount,
|
|
190
|
+
tokenAmount: dynamicAmount,
|
|
208
191
|
tokenIdentifier: tokenIdentifier!,
|
|
209
192
|
receiverSparkAddress: await userWallet.getSparkAddress(),
|
|
210
193
|
});
|
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConfigOptions,
|
|
3
|
-
filterTokenBalanceForTokenIdentifier,
|
|
4
|
-
WalletConfig,
|
|
5
|
-
} from "@buildonspark/spark-sdk";
|
|
1
|
+
import { filterTokenBalanceForTokenIdentifier } from "@buildonspark/spark-sdk";
|
|
6
2
|
import { jest } from "@jest/globals";
|
|
7
3
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
8
4
|
import { SparkWalletTesting } from "@buildonspark/spark-sdk/test-utils";
|
|
9
|
-
|
|
10
|
-
export const TOKENS_SCHNORR_CONFIG: Required<ConfigOptions> = {
|
|
11
|
-
...WalletConfig.LOCAL,
|
|
12
|
-
tokenSignatures: "SCHNORR",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const TOKENS_ECDSA_CONFIG: Required<ConfigOptions> = {
|
|
16
|
-
...WalletConfig.LOCAL,
|
|
17
|
-
tokenSignatures: "ECDSA",
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const TEST_CONFIGS = [
|
|
21
|
-
{ name: "TE", config: TOKENS_ECDSA_CONFIG },
|
|
22
|
-
{ name: "TS", config: TOKENS_SCHNORR_CONFIG },
|
|
23
|
-
];
|
|
5
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
24
6
|
|
|
25
7
|
describe.each(TEST_CONFIGS)(
|
|
26
8
|
"token output tests - $name",
|
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConfigOptions,
|
|
3
|
-
filterTokenBalanceForTokenIdentifier,
|
|
4
|
-
WalletConfig,
|
|
5
|
-
} from "@buildonspark/spark-sdk";
|
|
1
|
+
import { filterTokenBalanceForTokenIdentifier } from "@buildonspark/spark-sdk";
|
|
6
2
|
import { jest } from "@jest/globals";
|
|
7
3
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
8
4
|
import { SparkWalletTesting } from "@buildonspark/spark-sdk/test-utils";
|
|
9
|
-
|
|
10
|
-
export const TOKENS_SCHNORR_CONFIG: Required<ConfigOptions> = {
|
|
11
|
-
...WalletConfig.LOCAL,
|
|
12
|
-
tokenSignatures: "SCHNORR",
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const TOKENS_ECDSA_CONFIG: Required<ConfigOptions> = {
|
|
16
|
-
...WalletConfig.LOCAL,
|
|
17
|
-
tokenSignatures: "ECDSA",
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const TEST_CONFIGS = [
|
|
21
|
-
{ name: "TE", config: TOKENS_ECDSA_CONFIG },
|
|
22
|
-
{ name: "TS", config: TOKENS_SCHNORR_CONFIG },
|
|
23
|
-
];
|
|
5
|
+
import { TEST_CONFIGS } from "./test-configs.js";
|
|
24
6
|
|
|
25
7
|
describe.each(TEST_CONFIGS)(
|
|
26
8
|
"token transfer tests - $name",
|
|
@@ -18,12 +18,14 @@ const MIN_SYMBOL_SIZE = 3; // bytes
|
|
|
18
18
|
const MAX_SYMBOL_SIZE = 6; // bytes
|
|
19
19
|
const MAX_DECIMALS = 255; // fits into single byte
|
|
20
20
|
const MAXIMUM_MAX_SUPPLY = (1n << 128n) - 1n; // fits into 16 bytes (u128)
|
|
21
|
+
export const MAX_TOKEN_CONTENT_SIZE = 1024; // fits into 1024 bytes
|
|
21
22
|
|
|
22
23
|
export function validateTokenParameters(
|
|
23
24
|
tokenName: string,
|
|
24
25
|
tokenTicker: string,
|
|
25
26
|
decimals: number,
|
|
26
27
|
maxSupply: bigint,
|
|
28
|
+
extraMetadata?: Uint8Array,
|
|
27
29
|
) {
|
|
28
30
|
if (!isNfcNormalized(tokenName)) {
|
|
29
31
|
throw new SparkValidationError("Token name must be NFC-normalised UTF-8", {
|
|
@@ -92,4 +94,15 @@ export function validateTokenParameters(
|
|
|
92
94
|
expected: `>=0 and <=${MAXIMUM_MAX_SUPPLY.toString()}`,
|
|
93
95
|
});
|
|
94
96
|
}
|
|
97
|
+
|
|
98
|
+
if (extraMetadata && extraMetadata.length > MAX_TOKEN_CONTENT_SIZE) {
|
|
99
|
+
throw new SparkValidationError(
|
|
100
|
+
`Extra metadata must be less than ${MAX_TOKEN_CONTENT_SIZE} bytes`,
|
|
101
|
+
{
|
|
102
|
+
field: "extraMetadata",
|
|
103
|
+
value: extraMetadata.length,
|
|
104
|
+
expected: `<${MAX_TOKEN_CONTENT_SIZE}`,
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
}
|
|
95
108
|
}
|