@buildonspark/issuer-sdk 0.1.13 → 0.1.14
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
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.14",
|
|
4
4
|
"description": "Spark Issuer SDK for token issuance",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"types": "tsc"
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
|
-
"@buildonspark/spark-sdk": "0.6.
|
|
85
|
+
"@buildonspark/spark-sdk": "0.6.4",
|
|
86
86
|
"@noble/curves": "^1.8.0",
|
|
87
87
|
"@scure/btc-signer": "^1.5.0",
|
|
88
88
|
"buffer": "^6.0.3"
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
decodeBech32mTokenIdentifier,
|
|
3
|
+
filterTokenBalanceForTokenIdentifier,
|
|
4
|
+
} from "@buildonspark/spark-sdk";
|
|
5
|
+
import { OutputWithPreviousTransactionData } from "@buildonspark/spark-sdk/proto/spark_token";
|
|
2
6
|
import { jest } from "@jest/globals";
|
|
3
7
|
import { IssuerSparkWalletTesting } from "../utils/issuer-test-wallet.js";
|
|
4
8
|
import { SparkWalletTesting } from "@buildonspark/spark-sdk/test-utils";
|
|
@@ -44,7 +48,7 @@ describe.each(TEST_CONFIGS)(
|
|
|
44
48
|
expect(userBalance.ownedBalance).toBeGreaterThanOrEqual(tokenAmount);
|
|
45
49
|
});
|
|
46
50
|
|
|
47
|
-
it("should create, mint, and
|
|
51
|
+
it("should create, mint, and batch transfer tokens", async () => {
|
|
48
52
|
const tokenAmount: bigint = 999n;
|
|
49
53
|
|
|
50
54
|
const { wallet: issuerWallet } =
|
|
@@ -59,11 +63,10 @@ describe.each(TEST_CONFIGS)(
|
|
|
59
63
|
maxSupply: 1_000_000n,
|
|
60
64
|
});
|
|
61
65
|
|
|
62
|
-
const { wallet:
|
|
63
|
-
{
|
|
66
|
+
const { wallet: destinationWallet1 } =
|
|
67
|
+
await SparkWalletTesting.initialize({
|
|
64
68
|
options: config,
|
|
65
|
-
}
|
|
66
|
-
);
|
|
69
|
+
});
|
|
67
70
|
|
|
68
71
|
const { wallet: destinationWallet2 } =
|
|
69
72
|
await SparkWalletTesting.initialize({
|
|
@@ -87,7 +90,7 @@ describe.each(TEST_CONFIGS)(
|
|
|
87
90
|
{
|
|
88
91
|
tokenAmount: tokenAmount / 3n,
|
|
89
92
|
tokenIdentifier,
|
|
90
|
-
receiverSparkAddress: await
|
|
93
|
+
receiverSparkAddress: await destinationWallet1.getSparkAddress(),
|
|
91
94
|
},
|
|
92
95
|
{
|
|
93
96
|
tokenAmount: tokenAmount / 3n,
|
|
@@ -105,7 +108,7 @@ describe.each(TEST_CONFIGS)(
|
|
|
105
108
|
.balance;
|
|
106
109
|
expect(sourceBalanceAfter).toEqual(sourceBalanceBefore - tokenAmount);
|
|
107
110
|
|
|
108
|
-
const balanceObj = await
|
|
111
|
+
const balanceObj = await destinationWallet1.getBalance();
|
|
109
112
|
const destinationBalance = filterTokenBalanceForTokenIdentifier(
|
|
110
113
|
balanceObj?.tokenBalances,
|
|
111
114
|
tokenIdentifier!,
|
|
@@ -124,5 +127,580 @@ describe.each(TEST_CONFIGS)(
|
|
|
124
127
|
);
|
|
125
128
|
expect(destinationBalance3.ownedBalance).toEqual(tokenAmount / 3n);
|
|
126
129
|
});
|
|
130
|
+
|
|
131
|
+
it("should create, mint, and batch transfer multiple token types", async () => {
|
|
132
|
+
const tokenConfigs = [
|
|
133
|
+
{ amount: 1000n, ticker: "MTT1" },
|
|
134
|
+
{ amount: 2000n, ticker: "MTT2" },
|
|
135
|
+
{ amount: 1500n, ticker: "MTT3" },
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
const issuerWallets = await Promise.all(
|
|
139
|
+
tokenConfigs.map(async ({ ticker }) => {
|
|
140
|
+
const { wallet } = await IssuerSparkWalletTesting.initialize({
|
|
141
|
+
options: config,
|
|
142
|
+
});
|
|
143
|
+
await wallet.createToken({
|
|
144
|
+
tokenName: `${name}${ticker}`,
|
|
145
|
+
tokenTicker: ticker,
|
|
146
|
+
decimals: 0,
|
|
147
|
+
isFreezable: false,
|
|
148
|
+
maxSupply: 10_000_000n,
|
|
149
|
+
});
|
|
150
|
+
return wallet;
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const { wallet: intermediateWallet } =
|
|
155
|
+
await SparkWalletTesting.initialize({
|
|
156
|
+
options: config,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const destinationWallets = await Promise.all(
|
|
160
|
+
tokenConfigs.map(() =>
|
|
161
|
+
SparkWalletTesting.initialize({ options: config }).then(
|
|
162
|
+
(r) => r.wallet,
|
|
163
|
+
),
|
|
164
|
+
),
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
await Promise.all(
|
|
168
|
+
issuerWallets.map((wallet, i) =>
|
|
169
|
+
wallet.mintTokens(tokenConfigs[i].amount),
|
|
170
|
+
),
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const tokenIdentifiers = await Promise.all(
|
|
174
|
+
issuerWallets.map(async (wallet) => {
|
|
175
|
+
const balance = await wallet.getIssuerTokenBalance();
|
|
176
|
+
expect(balance.tokenIdentifier).toBeDefined();
|
|
177
|
+
return balance.tokenIdentifier!;
|
|
178
|
+
}),
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
const intermediateAddress = await intermediateWallet.getSparkAddress();
|
|
182
|
+
for (let i = 0; i < issuerWallets.length; i++) {
|
|
183
|
+
await issuerWallets[i].transferTokens({
|
|
184
|
+
tokenAmount: tokenConfigs[i].amount,
|
|
185
|
+
tokenIdentifier: tokenIdentifiers[i],
|
|
186
|
+
receiverSparkAddress: intermediateAddress,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const intermediateBalanceObj = await intermediateWallet.getBalance();
|
|
191
|
+
for (let i = 0; i < tokenConfigs.length; i++) {
|
|
192
|
+
const balance = filterTokenBalanceForTokenIdentifier(
|
|
193
|
+
intermediateBalanceObj?.tokenBalances,
|
|
194
|
+
tokenIdentifiers[i],
|
|
195
|
+
);
|
|
196
|
+
expect(balance.ownedBalance).toEqual(tokenConfigs[i].amount);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
await intermediateWallet.batchTransferTokens(
|
|
200
|
+
await Promise.all(
|
|
201
|
+
tokenConfigs.map(async ({ amount }, i) => ({
|
|
202
|
+
tokenAmount: amount,
|
|
203
|
+
tokenIdentifier: tokenIdentifiers[i],
|
|
204
|
+
receiverSparkAddress: await destinationWallets[i].getSparkAddress(),
|
|
205
|
+
})),
|
|
206
|
+
),
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
for (let i = 0; i < destinationWallets.length; i++) {
|
|
210
|
+
const balanceObj = await destinationWallets[i].getBalance();
|
|
211
|
+
const balance = filterTokenBalanceForTokenIdentifier(
|
|
212
|
+
balanceObj?.tokenBalances,
|
|
213
|
+
tokenIdentifiers[i],
|
|
214
|
+
);
|
|
215
|
+
expect(balance.ownedBalance).toEqual(tokenConfigs[i].amount);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const finalIntermediateBalanceObj = await intermediateWallet.getBalance();
|
|
219
|
+
for (const tokenIdentifier of tokenIdentifiers) {
|
|
220
|
+
const balance = filterTokenBalanceForTokenIdentifier(
|
|
221
|
+
finalIntermediateBalanceObj?.tokenBalances,
|
|
222
|
+
tokenIdentifier,
|
|
223
|
+
);
|
|
224
|
+
expect(balance.ownedBalance).toEqual(0n);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("should fail when transferring more tokens than available balance", async () => {
|
|
229
|
+
const mintAmount: bigint = 1000n;
|
|
230
|
+
const transferAmount: bigint = 2000n;
|
|
231
|
+
|
|
232
|
+
const { wallet: issuerWallet } =
|
|
233
|
+
await IssuerSparkWalletTesting.initialize({
|
|
234
|
+
options: config,
|
|
235
|
+
});
|
|
236
|
+
await issuerWallet.createToken({
|
|
237
|
+
tokenName: `${name}INS`,
|
|
238
|
+
tokenTicker: "INS",
|
|
239
|
+
decimals: 0,
|
|
240
|
+
isFreezable: false,
|
|
241
|
+
maxSupply: 10_000_000n,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const { wallet: destinationWallet1 } =
|
|
245
|
+
await SparkWalletTesting.initialize({
|
|
246
|
+
options: config,
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
await issuerWallet.mintTokens(mintAmount);
|
|
250
|
+
const tokenIdentifier = await issuerWallet.getIssuerTokenIdentifier();
|
|
251
|
+
|
|
252
|
+
await expect(
|
|
253
|
+
issuerWallet.transferTokens({
|
|
254
|
+
tokenAmount: transferAmount,
|
|
255
|
+
tokenIdentifier: tokenIdentifier!,
|
|
256
|
+
receiverSparkAddress: await destinationWallet1.getSparkAddress(),
|
|
257
|
+
}),
|
|
258
|
+
).rejects.toThrow(/Insufficient token amount/);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("should fail when batch transferring more tokens than available balance", async () => {
|
|
262
|
+
const mintAmount: bigint = 1000n;
|
|
263
|
+
const transferAmount: bigint = 2000n;
|
|
264
|
+
|
|
265
|
+
const { wallet: issuerWallet } =
|
|
266
|
+
await IssuerSparkWalletTesting.initialize({
|
|
267
|
+
options: config,
|
|
268
|
+
});
|
|
269
|
+
await issuerWallet.createToken({
|
|
270
|
+
tokenName: `${name}INS`,
|
|
271
|
+
tokenTicker: "INS",
|
|
272
|
+
decimals: 0,
|
|
273
|
+
isFreezable: false,
|
|
274
|
+
maxSupply: 10_000_000n,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const { wallet: destinationWallet1 } =
|
|
278
|
+
await SparkWalletTesting.initialize({
|
|
279
|
+
options: config,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const { wallet: destinationWallet2 } =
|
|
283
|
+
await SparkWalletTesting.initialize({
|
|
284
|
+
options: config,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
await issuerWallet.mintTokens(mintAmount);
|
|
288
|
+
const tokenIdentifier = await issuerWallet.getIssuerTokenIdentifier();
|
|
289
|
+
|
|
290
|
+
await expect(
|
|
291
|
+
issuerWallet.batchTransferTokens([
|
|
292
|
+
{
|
|
293
|
+
tokenAmount: transferAmount,
|
|
294
|
+
tokenIdentifier: tokenIdentifier!,
|
|
295
|
+
receiverSparkAddress: await destinationWallet1.getSparkAddress(),
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
tokenAmount: transferAmount,
|
|
299
|
+
tokenIdentifier: tokenIdentifier!,
|
|
300
|
+
receiverSparkAddress: await destinationWallet2.getSparkAddress(),
|
|
301
|
+
},
|
|
302
|
+
]),
|
|
303
|
+
).rejects.toThrow(/Insufficient token amount/);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it("should fail batch transfer when one token type has insufficient balance", async () => {
|
|
307
|
+
const tokenAmount1: bigint = 1000n;
|
|
308
|
+
const tokenAmount2: bigint = 500n;
|
|
309
|
+
|
|
310
|
+
const { wallet: issuerWallet1 } =
|
|
311
|
+
await IssuerSparkWalletTesting.initialize({
|
|
312
|
+
options: config,
|
|
313
|
+
});
|
|
314
|
+
await issuerWallet1.createToken({
|
|
315
|
+
tokenName: `${name}BF1`,
|
|
316
|
+
tokenTicker: "BF1",
|
|
317
|
+
decimals: 0,
|
|
318
|
+
isFreezable: false,
|
|
319
|
+
maxSupply: 10_000_000n,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const { wallet: issuerWallet2 } =
|
|
323
|
+
await IssuerSparkWalletTesting.initialize({
|
|
324
|
+
options: config,
|
|
325
|
+
});
|
|
326
|
+
await issuerWallet2.createToken({
|
|
327
|
+
tokenName: `${name}BF2`,
|
|
328
|
+
tokenTicker: "BF2",
|
|
329
|
+
decimals: 0,
|
|
330
|
+
isFreezable: false,
|
|
331
|
+
maxSupply: 10_000_000n,
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
const { wallet: intermediateWallet } =
|
|
335
|
+
await SparkWalletTesting.initialize({
|
|
336
|
+
options: config,
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
const { wallet: destinationWallet1 } =
|
|
340
|
+
await SparkWalletTesting.initialize({
|
|
341
|
+
options: config,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const { wallet: destinationWallet2 } =
|
|
345
|
+
await SparkWalletTesting.initialize({
|
|
346
|
+
options: config,
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
await issuerWallet1.mintTokens(tokenAmount1);
|
|
350
|
+
await issuerWallet2.mintTokens(tokenAmount2);
|
|
351
|
+
|
|
352
|
+
const issuerBalance1 = await issuerWallet1.getIssuerTokenBalance();
|
|
353
|
+
const issuerBalance2 = await issuerWallet2.getIssuerTokenBalance();
|
|
354
|
+
|
|
355
|
+
const tokenIdentifier1 = issuerBalance1.tokenIdentifier!;
|
|
356
|
+
const tokenIdentifier2 = issuerBalance2.tokenIdentifier!;
|
|
357
|
+
|
|
358
|
+
await issuerWallet1.transferTokens({
|
|
359
|
+
tokenAmount: tokenAmount1,
|
|
360
|
+
tokenIdentifier: tokenIdentifier1,
|
|
361
|
+
receiverSparkAddress: await intermediateWallet.getSparkAddress(),
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
await issuerWallet2.transferTokens({
|
|
365
|
+
tokenAmount: tokenAmount2,
|
|
366
|
+
tokenIdentifier: tokenIdentifier2,
|
|
367
|
+
receiverSparkAddress: await intermediateWallet.getSparkAddress(),
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
await expect(
|
|
371
|
+
intermediateWallet.batchTransferTokens([
|
|
372
|
+
{
|
|
373
|
+
tokenAmount: tokenAmount1,
|
|
374
|
+
tokenIdentifier: tokenIdentifier1,
|
|
375
|
+
receiverSparkAddress: await destinationWallet1.getSparkAddress(),
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
tokenAmount: tokenAmount2 * 2n,
|
|
379
|
+
tokenIdentifier: tokenIdentifier2,
|
|
380
|
+
receiverSparkAddress: await destinationWallet2.getSparkAddress(),
|
|
381
|
+
},
|
|
382
|
+
]),
|
|
383
|
+
).rejects.toThrow(/Insufficient token amount/);
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it("should fail batch transfer when requesting token type wallet doesn't own", async () => {
|
|
387
|
+
const tokenAmount: bigint = 1000n;
|
|
388
|
+
|
|
389
|
+
const { wallet: issuerWallet1 } =
|
|
390
|
+
await IssuerSparkWalletTesting.initialize({
|
|
391
|
+
options: config,
|
|
392
|
+
});
|
|
393
|
+
await issuerWallet1.createToken({
|
|
394
|
+
tokenName: `${name}OWN`,
|
|
395
|
+
tokenTicker: "OWN",
|
|
396
|
+
decimals: 0,
|
|
397
|
+
isFreezable: false,
|
|
398
|
+
maxSupply: 10_000_000n,
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
const { wallet: issuerWallet2 } =
|
|
402
|
+
await IssuerSparkWalletTesting.initialize({
|
|
403
|
+
options: config,
|
|
404
|
+
});
|
|
405
|
+
await issuerWallet2.createToken({
|
|
406
|
+
tokenName: `${name}NWN`,
|
|
407
|
+
tokenTicker: "NWN",
|
|
408
|
+
decimals: 0,
|
|
409
|
+
isFreezable: false,
|
|
410
|
+
maxSupply: 10_000_000n,
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
const { wallet: intermediateWallet } =
|
|
414
|
+
await SparkWalletTesting.initialize({
|
|
415
|
+
options: config,
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
const { wallet: destinationWallet } = await SparkWalletTesting.initialize(
|
|
419
|
+
{
|
|
420
|
+
options: config,
|
|
421
|
+
},
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
await issuerWallet1.mintTokens(tokenAmount);
|
|
425
|
+
await issuerWallet2.mintTokens(tokenAmount);
|
|
426
|
+
|
|
427
|
+
const issuerBalance1 = await issuerWallet1.getIssuerTokenBalance();
|
|
428
|
+
const issuerBalance2 = await issuerWallet2.getIssuerTokenBalance();
|
|
429
|
+
|
|
430
|
+
const tokenIdentifier1 = issuerBalance1.tokenIdentifier!;
|
|
431
|
+
const tokenIdentifier2 = issuerBalance2.tokenIdentifier!;
|
|
432
|
+
|
|
433
|
+
await issuerWallet1.transferTokens({
|
|
434
|
+
tokenAmount: tokenAmount,
|
|
435
|
+
tokenIdentifier: tokenIdentifier1,
|
|
436
|
+
receiverSparkAddress: await intermediateWallet.getSparkAddress(),
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
await expect(
|
|
440
|
+
intermediateWallet.batchTransferTokens([
|
|
441
|
+
{
|
|
442
|
+
tokenAmount: tokenAmount,
|
|
443
|
+
tokenIdentifier: tokenIdentifier1,
|
|
444
|
+
receiverSparkAddress: await destinationWallet.getSparkAddress(),
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
tokenAmount: tokenAmount,
|
|
448
|
+
tokenIdentifier: tokenIdentifier2,
|
|
449
|
+
receiverSparkAddress: await destinationWallet.getSparkAddress(),
|
|
450
|
+
},
|
|
451
|
+
]),
|
|
452
|
+
).rejects.toThrow(/Insufficient token amount/);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
it("should fail when transfer amounts sum exceeds balance for same token type", async () => {
|
|
456
|
+
const mintAmount: bigint = 1000n;
|
|
457
|
+
|
|
458
|
+
const { wallet: issuerWallet } =
|
|
459
|
+
await IssuerSparkWalletTesting.initialize({
|
|
460
|
+
options: config,
|
|
461
|
+
});
|
|
462
|
+
await issuerWallet.createToken({
|
|
463
|
+
tokenName: `${name}SUM`,
|
|
464
|
+
tokenTicker: "SUM",
|
|
465
|
+
decimals: 0,
|
|
466
|
+
isFreezable: false,
|
|
467
|
+
maxSupply: 10_000_000n,
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
const { wallet: destinationWallet1 } =
|
|
471
|
+
await SparkWalletTesting.initialize({
|
|
472
|
+
options: config,
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
const { wallet: destinationWallet2 } =
|
|
476
|
+
await SparkWalletTesting.initialize({
|
|
477
|
+
options: config,
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
await issuerWallet.mintTokens(mintAmount);
|
|
481
|
+
const tokenIdentifier = await issuerWallet.getIssuerTokenIdentifier();
|
|
482
|
+
|
|
483
|
+
await expect(
|
|
484
|
+
issuerWallet.batchTransferTokens([
|
|
485
|
+
{
|
|
486
|
+
tokenAmount: 600n,
|
|
487
|
+
tokenIdentifier: tokenIdentifier!,
|
|
488
|
+
receiverSparkAddress: await destinationWallet1.getSparkAddress(),
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
tokenAmount: 600n,
|
|
492
|
+
tokenIdentifier: tokenIdentifier!,
|
|
493
|
+
receiverSparkAddress: await destinationWallet2.getSparkAddress(),
|
|
494
|
+
},
|
|
495
|
+
]),
|
|
496
|
+
).rejects.toThrow(/Insufficient token amount/);
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it("should fail when transferring with unavailable selected TTXOs", async () => {
|
|
500
|
+
const mintAmount: bigint = 1000n;
|
|
501
|
+
|
|
502
|
+
const { wallet: issuerWallet } =
|
|
503
|
+
await IssuerSparkWalletTesting.initialize({
|
|
504
|
+
options: config,
|
|
505
|
+
});
|
|
506
|
+
await issuerWallet.createToken({
|
|
507
|
+
tokenName: `${name}UNA`,
|
|
508
|
+
tokenTicker: "UNA",
|
|
509
|
+
decimals: 0,
|
|
510
|
+
isFreezable: false,
|
|
511
|
+
maxSupply: 10_000_000n,
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
const { wallet: destinationWallet } = await SparkWalletTesting.initialize(
|
|
515
|
+
{
|
|
516
|
+
options: config,
|
|
517
|
+
},
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
await issuerWallet.mintTokens(mintAmount);
|
|
521
|
+
const tokenIdentifier = await issuerWallet.getIssuerTokenIdentifier();
|
|
522
|
+
const { tokenIdentifier: rawTokenIdentifier } =
|
|
523
|
+
decodeBech32mTokenIdentifier(tokenIdentifier!);
|
|
524
|
+
|
|
525
|
+
const fakeOutput: OutputWithPreviousTransactionData = {
|
|
526
|
+
output: {
|
|
527
|
+
id: "non-existent-output-id",
|
|
528
|
+
ownerPublicKey: new Uint8Array(33),
|
|
529
|
+
tokenIdentifier: rawTokenIdentifier,
|
|
530
|
+
tokenAmount: new Uint8Array([
|
|
531
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0xe8,
|
|
532
|
+
]),
|
|
533
|
+
},
|
|
534
|
+
previousTransactionHash: new Uint8Array(32),
|
|
535
|
+
previousTransactionVout: 0,
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
await expect(
|
|
539
|
+
issuerWallet.transferTokens({
|
|
540
|
+
tokenAmount: mintAmount,
|
|
541
|
+
tokenIdentifier: tokenIdentifier!,
|
|
542
|
+
receiverSparkAddress: await destinationWallet.getSparkAddress(),
|
|
543
|
+
selectedOutputs: [fakeOutput],
|
|
544
|
+
}),
|
|
545
|
+
).rejects.toThrow(/Insufficient input amount for token/);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
it("should fail when selected output token type does not match receiver token type", async () => {
|
|
549
|
+
const mintAmount: bigint = 1000n;
|
|
550
|
+
|
|
551
|
+
const { wallet: issuerWallet1 } =
|
|
552
|
+
await IssuerSparkWalletTesting.initialize({
|
|
553
|
+
options: config,
|
|
554
|
+
});
|
|
555
|
+
await issuerWallet1.createToken({
|
|
556
|
+
tokenName: `${name}MIS1`,
|
|
557
|
+
tokenTicker: "MIS1",
|
|
558
|
+
decimals: 0,
|
|
559
|
+
isFreezable: false,
|
|
560
|
+
maxSupply: 10_000_000n,
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
const { wallet: issuerWallet2 } =
|
|
564
|
+
await IssuerSparkWalletTesting.initialize({
|
|
565
|
+
options: config,
|
|
566
|
+
});
|
|
567
|
+
await issuerWallet2.createToken({
|
|
568
|
+
tokenName: `${name}MIS2`,
|
|
569
|
+
tokenTicker: "MIS2",
|
|
570
|
+
decimals: 0,
|
|
571
|
+
isFreezable: false,
|
|
572
|
+
maxSupply: 10_000_000n,
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
const { wallet: destinationWallet } = await SparkWalletTesting.initialize(
|
|
576
|
+
{
|
|
577
|
+
options: config,
|
|
578
|
+
},
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
await issuerWallet1.mintTokens(mintAmount);
|
|
582
|
+
await issuerWallet2.mintTokens(mintAmount);
|
|
583
|
+
|
|
584
|
+
const tokenIdentifier1 = await issuerWallet1.getIssuerTokenIdentifier();
|
|
585
|
+
const tokenIdentifier2 = await issuerWallet2.getIssuerTokenIdentifier();
|
|
586
|
+
const { tokenIdentifier: rawTokenIdentifier2 } =
|
|
587
|
+
decodeBech32mTokenIdentifier(tokenIdentifier2!);
|
|
588
|
+
|
|
589
|
+
const fakeOutputWithWrongToken: OutputWithPreviousTransactionData = {
|
|
590
|
+
output: {
|
|
591
|
+
id: "fake-output-id",
|
|
592
|
+
ownerPublicKey: new Uint8Array(33),
|
|
593
|
+
tokenIdentifier: rawTokenIdentifier2,
|
|
594
|
+
tokenAmount: new Uint8Array([
|
|
595
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0xe8,
|
|
596
|
+
]),
|
|
597
|
+
},
|
|
598
|
+
previousTransactionHash: new Uint8Array(32),
|
|
599
|
+
previousTransactionVout: 0,
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
await expect(
|
|
603
|
+
issuerWallet1.transferTokens({
|
|
604
|
+
tokenAmount: mintAmount,
|
|
605
|
+
tokenIdentifier: tokenIdentifier1!,
|
|
606
|
+
receiverSparkAddress: await destinationWallet.getSparkAddress(),
|
|
607
|
+
selectedOutputs: [fakeOutputWithWrongToken],
|
|
608
|
+
}),
|
|
609
|
+
).rejects.toThrow(/Insufficient input amount for token/);
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
it("should fail batch transfer when one token type is frozen", async () => {
|
|
613
|
+
const tokenAmount: bigint = 1000n;
|
|
614
|
+
|
|
615
|
+
const { wallet: issuerWallet1 } =
|
|
616
|
+
await IssuerSparkWalletTesting.initialize({
|
|
617
|
+
options: config,
|
|
618
|
+
});
|
|
619
|
+
await issuerWallet1.createToken({
|
|
620
|
+
tokenName: `${name}FRZ1`,
|
|
621
|
+
tokenTicker: "FRZ1",
|
|
622
|
+
decimals: 0,
|
|
623
|
+
isFreezable: true,
|
|
624
|
+
maxSupply: 10_000_000n,
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
const { wallet: issuerWallet2 } =
|
|
628
|
+
await IssuerSparkWalletTesting.initialize({
|
|
629
|
+
options: config,
|
|
630
|
+
});
|
|
631
|
+
await issuerWallet2.createToken({
|
|
632
|
+
tokenName: `${name}FRZ2`,
|
|
633
|
+
tokenTicker: "FRZ2",
|
|
634
|
+
decimals: 0,
|
|
635
|
+
isFreezable: true,
|
|
636
|
+
maxSupply: 10_000_000n,
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
const { wallet: intermediateWallet } =
|
|
640
|
+
await SparkWalletTesting.initialize({
|
|
641
|
+
options: config,
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
const { wallet: destinationWallet } = await SparkWalletTesting.initialize(
|
|
645
|
+
{
|
|
646
|
+
options: config,
|
|
647
|
+
},
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
await issuerWallet1.mintTokens(tokenAmount);
|
|
651
|
+
await issuerWallet2.mintTokens(tokenAmount);
|
|
652
|
+
|
|
653
|
+
const issuerBalance1 = await issuerWallet1.getIssuerTokenBalance();
|
|
654
|
+
const issuerBalance2 = await issuerWallet2.getIssuerTokenBalance();
|
|
655
|
+
const tokenIdentifier1 = issuerBalance1.tokenIdentifier!;
|
|
656
|
+
const tokenIdentifier2 = issuerBalance2.tokenIdentifier!;
|
|
657
|
+
|
|
658
|
+
const intermediateAddress = await intermediateWallet.getSparkAddress();
|
|
659
|
+
await issuerWallet1.transferTokens({
|
|
660
|
+
tokenAmount,
|
|
661
|
+
tokenIdentifier: tokenIdentifier1,
|
|
662
|
+
receiverSparkAddress: intermediateAddress,
|
|
663
|
+
});
|
|
664
|
+
await issuerWallet2.transferTokens({
|
|
665
|
+
tokenAmount,
|
|
666
|
+
tokenIdentifier: tokenIdentifier2,
|
|
667
|
+
receiverSparkAddress: intermediateAddress,
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
const intermediateBalanceObj = await intermediateWallet.getBalance();
|
|
671
|
+
expect(
|
|
672
|
+
filterTokenBalanceForTokenIdentifier(
|
|
673
|
+
intermediateBalanceObj?.tokenBalances,
|
|
674
|
+
tokenIdentifier1,
|
|
675
|
+
).ownedBalance,
|
|
676
|
+
).toEqual(tokenAmount);
|
|
677
|
+
expect(
|
|
678
|
+
filterTokenBalanceForTokenIdentifier(
|
|
679
|
+
intermediateBalanceObj?.tokenBalances,
|
|
680
|
+
tokenIdentifier2,
|
|
681
|
+
).ownedBalance,
|
|
682
|
+
).toEqual(tokenAmount);
|
|
683
|
+
|
|
684
|
+
await issuerWallet1.freezeTokens({
|
|
685
|
+
tokenIdentifier: tokenIdentifier1,
|
|
686
|
+
sparkAddress: intermediateAddress,
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
const destinationAddress = await destinationWallet.getSparkAddress();
|
|
690
|
+
await expect(
|
|
691
|
+
intermediateWallet.batchTransferTokens([
|
|
692
|
+
{
|
|
693
|
+
tokenAmount,
|
|
694
|
+
tokenIdentifier: tokenIdentifier1,
|
|
695
|
+
receiverSparkAddress: destinationAddress,
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
tokenAmount,
|
|
699
|
+
tokenIdentifier: tokenIdentifier2,
|
|
700
|
+
receiverSparkAddress: destinationAddress,
|
|
701
|
+
},
|
|
702
|
+
]),
|
|
703
|
+
).rejects.toThrow();
|
|
704
|
+
});
|
|
127
705
|
},
|
|
128
706
|
);
|