mainnet-js 1.1.0 → 1.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/dist/index.html +1 -1
- package/dist/{mainnet-1.1.0.js → mainnet-1.1.2.js} +4 -4
- package/dist/module/libauth.d.ts +1 -1
- package/dist/module/libauth.d.ts.map +1 -1
- package/dist/module/libauth.js +1 -1
- package/dist/module/libauth.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +42 -7
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +127 -106
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/wallet/Slp.d.ts.map +1 -1
- package/dist/module/wallet/Slp.js +11 -1
- package/dist/module/wallet/Slp.js.map +1 -1
- package/dist/module/wallet/Wif.d.ts +14 -6
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +131 -59
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/interface.d.ts +2 -0
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts +4 -0
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/libauth.ts +1 -0
- package/src/transaction/Wif.ts +200 -154
- package/src/wallet/Cashtokens.test.headless.js +162 -1
- package/src/wallet/Cashtokens.test.ts +338 -2
- package/src/wallet/Slp.ts +10 -7
- package/src/wallet/Wif.test.ts +101 -1
- package/src/wallet/Wif.ts +185 -98
- package/src/wallet/interface.ts +2 -0
- package/src/wallet/model.ts +6 -0
|
@@ -77,6 +77,8 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
77
77
|
new TokenSendRequest({
|
|
78
78
|
cashaddr: bob.cashaddr,
|
|
79
79
|
tokenId: tokenId,
|
|
80
|
+
capability: NFTCapability.mutable,
|
|
81
|
+
commitment: "abcd",
|
|
80
82
|
}),
|
|
81
83
|
]);
|
|
82
84
|
expect(await alice.getTokenBalance(tokenId)).toBe(0);
|
|
@@ -113,7 +115,7 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
113
115
|
commitment: "abcd02",
|
|
114
116
|
}),
|
|
115
117
|
])
|
|
116
|
-
).rejects.toThrow("
|
|
118
|
+
).rejects.toThrow("No suitable token utxos available to send token");
|
|
117
119
|
}, process.env.ALICE_ID);
|
|
118
120
|
});
|
|
119
121
|
|
|
@@ -135,6 +137,7 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
135
137
|
new TokenSendRequest({
|
|
136
138
|
cashaddr: alice.cashaddr,
|
|
137
139
|
tokenId: tokenId,
|
|
140
|
+
capability: NFTCapability.mutable,
|
|
138
141
|
commitment: "abcd02",
|
|
139
142
|
}),
|
|
140
143
|
]);
|
|
@@ -163,9 +166,13 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
163
166
|
const response = await alice.tokenMint(tokenId, [
|
|
164
167
|
new TokenMintRequest({
|
|
165
168
|
cashaddr: alice.cashaddr,
|
|
169
|
+
commitment: "test",
|
|
170
|
+
capability: NFTCapability.none,
|
|
166
171
|
}),
|
|
167
172
|
new TokenMintRequest({
|
|
168
173
|
cashaddr: alice.cashaddr,
|
|
174
|
+
commitment: "test2",
|
|
175
|
+
capability: NFTCapability.none,
|
|
169
176
|
}),
|
|
170
177
|
]);
|
|
171
178
|
expect(await alice.getTokenBalance(tokenId)).toBe(0);
|
|
@@ -197,9 +204,13 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
197
204
|
[
|
|
198
205
|
new TokenMintRequest({
|
|
199
206
|
cashaddr: alice.cashaddr,
|
|
207
|
+
capability: NFTCapability.none,
|
|
208
|
+
commitment: "0a",
|
|
200
209
|
}),
|
|
201
210
|
new TokenMintRequest({
|
|
202
211
|
cashaddr: alice.cashaddr,
|
|
212
|
+
capability: NFTCapability.none,
|
|
213
|
+
commitment: "0b",
|
|
203
214
|
}),
|
|
204
215
|
],
|
|
205
216
|
true
|
|
@@ -215,9 +226,13 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
215
226
|
[
|
|
216
227
|
new TokenMintRequest({
|
|
217
228
|
cashaddr: alice.cashaddr,
|
|
229
|
+
capability: NFTCapability.none,
|
|
230
|
+
commitment: "0c",
|
|
218
231
|
}),
|
|
219
232
|
new TokenMintRequest({
|
|
220
233
|
cashaddr: alice.cashaddr,
|
|
234
|
+
capability: NFTCapability.none,
|
|
235
|
+
commitment: "0d",
|
|
221
236
|
}),
|
|
222
237
|
],
|
|
223
238
|
false
|
|
@@ -234,12 +249,18 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
234
249
|
[
|
|
235
250
|
new TokenMintRequest({
|
|
236
251
|
cashaddr: alice.cashaddr,
|
|
252
|
+
capability: NFTCapability.none,
|
|
253
|
+
commitment: "0a",
|
|
237
254
|
}),
|
|
238
255
|
new TokenMintRequest({
|
|
239
256
|
cashaddr: alice.cashaddr,
|
|
257
|
+
capability: NFTCapability.none,
|
|
258
|
+
commitment: "0a",
|
|
240
259
|
}),
|
|
241
260
|
new TokenMintRequest({
|
|
242
261
|
cashaddr: alice.cashaddr,
|
|
262
|
+
capability: NFTCapability.none,
|
|
263
|
+
commitment: "0a",
|
|
243
264
|
}),
|
|
244
265
|
],
|
|
245
266
|
true
|
|
@@ -425,6 +446,8 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
425
446
|
const genesisResponse = await alice.tokenGenesis({
|
|
426
447
|
amount: 100,
|
|
427
448
|
value: 5000,
|
|
449
|
+
capability: NFTCapability.minting,
|
|
450
|
+
commitment: "test",
|
|
428
451
|
cashaddr: alice.cashaddr,
|
|
429
452
|
});
|
|
430
453
|
|
|
@@ -444,6 +467,8 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
444
467
|
amount: 100,
|
|
445
468
|
tokenId: tokenId,
|
|
446
469
|
value: 1500,
|
|
470
|
+
capability: NFTCapability.minting,
|
|
471
|
+
commitment: "test",
|
|
447
472
|
}),
|
|
448
473
|
]),
|
|
449
474
|
0
|
|
@@ -464,4 +489,140 @@ describe(`Wallet should function in the browser`, () => {
|
|
|
464
489
|
await Promise.all([cancel(), delay(1000)]);
|
|
465
490
|
}, process.env.ALICE_ID);
|
|
466
491
|
});
|
|
492
|
+
|
|
493
|
+
test("Should encode unsigned transactions", async () => {
|
|
494
|
+
await page.evaluate(async (id) => {
|
|
495
|
+
const binsAreEqual = (a, b) => {
|
|
496
|
+
if (a.length !== b.length) {
|
|
497
|
+
return false;
|
|
498
|
+
}
|
|
499
|
+
// eslint-disable-next-line functional/no-let, functional/no-loop-statement, no-plusplus
|
|
500
|
+
for (let i = 0; i < a.length; i++) {
|
|
501
|
+
if (a[i] !== b[i]) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return true;
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
const aliceWallet = await RegTestWallet.fromId(id);
|
|
509
|
+
const aliceWatchWallet = await RegTestWallet.watchOnly(
|
|
510
|
+
aliceWallet.cashaddr
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
{
|
|
514
|
+
const aliceUtxos = await aliceWallet.getAddressUtxos();
|
|
515
|
+
|
|
516
|
+
const { unsignedTransaction, sourceOutputs } =
|
|
517
|
+
await aliceWatchWallet.tokenGenesis(
|
|
518
|
+
{
|
|
519
|
+
capability: "minting",
|
|
520
|
+
commitment: "00",
|
|
521
|
+
},
|
|
522
|
+
undefined,
|
|
523
|
+
{ buildUnsigned: true }
|
|
524
|
+
);
|
|
525
|
+
const encodedTransaction = hexToBin(unsignedTransaction);
|
|
526
|
+
expect(encodedTransaction.length).toBeGreaterThan(0);
|
|
527
|
+
|
|
528
|
+
// check transaction was not submitted
|
|
529
|
+
expect(JSON.stringify(aliceUtxos)).toBe(
|
|
530
|
+
JSON.stringify(await aliceWallet.getAddressUtxos())
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
const decoded = libauth.decodeTransaction(encodedTransaction);
|
|
534
|
+
if (typeof decoded === "string") {
|
|
535
|
+
throw decoded;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
expect(
|
|
539
|
+
binsAreEqual(decoded.inputs[0].unlockingBytecode, Uint8Array.from([]))
|
|
540
|
+
).toBe(true);
|
|
541
|
+
expect(sourceOutputs.length).toBe(decoded.inputs.length);
|
|
542
|
+
expect(binToHex(decoded.outputs[0].token?.nft?.commitment)).toBe("00");
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const genesisResponse = await aliceWallet.tokenGenesis({
|
|
546
|
+
capability: "minting",
|
|
547
|
+
commitment: "00",
|
|
548
|
+
});
|
|
549
|
+
const tokenId = genesisResponse.tokenIds[0];
|
|
550
|
+
|
|
551
|
+
{
|
|
552
|
+
const aliceUtxos = await aliceWallet.getAddressUtxos();
|
|
553
|
+
|
|
554
|
+
const { unsignedTransaction, sourceOutputs } =
|
|
555
|
+
await aliceWatchWallet.tokenMint(
|
|
556
|
+
tokenId,
|
|
557
|
+
{
|
|
558
|
+
capability: "none",
|
|
559
|
+
commitment: "0a",
|
|
560
|
+
},
|
|
561
|
+
undefined,
|
|
562
|
+
{ buildUnsigned: true }
|
|
563
|
+
);
|
|
564
|
+
const encodedTransaction = hexToBin(unsignedTransaction);
|
|
565
|
+
expect(encodedTransaction.length).toBeGreaterThan(0);
|
|
566
|
+
|
|
567
|
+
// check transaction was not submitted
|
|
568
|
+
expect(JSON.stringify(aliceUtxos)).toBe(
|
|
569
|
+
JSON.stringify(await aliceWallet.getAddressUtxos())
|
|
570
|
+
);
|
|
571
|
+
|
|
572
|
+
const decoded = libauth.decodeTransaction(encodedTransaction);
|
|
573
|
+
if (typeof decoded === "string") {
|
|
574
|
+
throw decoded;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
expect(
|
|
578
|
+
binsAreEqual(decoded.inputs[0].unlockingBytecode, Uint8Array.from([]))
|
|
579
|
+
).toBe(true);
|
|
580
|
+
expect(sourceOutputs.length).toBe(decoded.inputs.length);
|
|
581
|
+
expect(binToHex(sourceOutputs[0].token?.nft?.commitment)).toBe("00");
|
|
582
|
+
expect(binToHex(decoded.outputs[0].token?.nft?.commitment)).toBe("00");
|
|
583
|
+
expect(binToHex(decoded.outputs[1].token?.nft?.commitment)).toBe("0a");
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
await aliceWallet.tokenMint(tokenId, {
|
|
587
|
+
capability: "none",
|
|
588
|
+
commitment: "0a",
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
{
|
|
592
|
+
const aliceUtxos = await aliceWallet.getAddressUtxos();
|
|
593
|
+
|
|
594
|
+
const { unsignedTransaction, sourceOutputs } =
|
|
595
|
+
await aliceWatchWallet.send(
|
|
596
|
+
[
|
|
597
|
+
new TokenSendRequest({
|
|
598
|
+
tokenId: tokenId,
|
|
599
|
+
capability: "none",
|
|
600
|
+
commitment: "0a",
|
|
601
|
+
cashaddr: aliceWallet.cashaddr,
|
|
602
|
+
}),
|
|
603
|
+
],
|
|
604
|
+
{ buildUnsigned: true }
|
|
605
|
+
);
|
|
606
|
+
const encodedTransaction = hexToBin(unsignedTransaction);
|
|
607
|
+
expect(encodedTransaction.length).toBeGreaterThan(0);
|
|
608
|
+
|
|
609
|
+
// check transaction was not submitted
|
|
610
|
+
expect(JSON.stringify(aliceUtxos)).toBe(
|
|
611
|
+
JSON.stringify(await aliceWallet.getAddressUtxos())
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
const decoded = libauth.decodeTransaction(encodedTransaction);
|
|
615
|
+
if (typeof decoded === "string") {
|
|
616
|
+
throw decoded;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
expect(
|
|
620
|
+
binsAreEqual(decoded.inputs[0].unlockingBytecode, Uint8Array.from([]))
|
|
621
|
+
).toBe(true);
|
|
622
|
+
expect(sourceOutputs.length).toBe(decoded.inputs.length);
|
|
623
|
+
expect(binToHex(sourceOutputs[0].token?.nft?.commitment)).toBe("0a");
|
|
624
|
+
expect(binToHex(decoded.outputs[0].token?.nft?.commitment)).toBe("0a");
|
|
625
|
+
}
|
|
626
|
+
}, process.env.ALICE_ID);
|
|
627
|
+
});
|
|
467
628
|
});
|
|
@@ -7,7 +7,13 @@ import {
|
|
|
7
7
|
TokenSendRequest,
|
|
8
8
|
} from "./model";
|
|
9
9
|
import { Network, NFTCapability } from "../interface";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
binToHex,
|
|
12
|
+
binsAreEqual,
|
|
13
|
+
decodeTransaction,
|
|
14
|
+
hexToBin,
|
|
15
|
+
utf8ToBin,
|
|
16
|
+
} from "@bitauth/libauth";
|
|
11
17
|
import { delay } from "../util";
|
|
12
18
|
import { Config } from "../config";
|
|
13
19
|
|
|
@@ -110,6 +116,8 @@ describe(`Test cashtokens`, () => {
|
|
|
110
116
|
expect(newTokenUtxos.length).toBe(2);
|
|
111
117
|
expect(await alice.getTokenBalance(tokenId)).toBe(75);
|
|
112
118
|
expect(await bob.getTokenBalance(tokenId)).toBe(25);
|
|
119
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(0);
|
|
120
|
+
expect((await bob.getAllNftTokenBalances())[tokenId] || 0).toBe(0);
|
|
113
121
|
});
|
|
114
122
|
|
|
115
123
|
test("Test NFT cashtoken genesis and sending", async () => {
|
|
@@ -132,6 +140,8 @@ describe(`Test cashtokens`, () => {
|
|
|
132
140
|
{
|
|
133
141
|
cashaddr: bob.cashaddr!,
|
|
134
142
|
tokenId: tokenId,
|
|
143
|
+
capability: NFTCapability.mutable,
|
|
144
|
+
commitment: "abcd",
|
|
135
145
|
} as any,
|
|
136
146
|
]);
|
|
137
147
|
expect(await alice.getTokenBalance(tokenId)).toBe(0);
|
|
@@ -167,7 +177,7 @@ describe(`Test cashtokens`, () => {
|
|
|
167
177
|
commitment: "abcd02",
|
|
168
178
|
}),
|
|
169
179
|
])
|
|
170
|
-
).rejects.toThrow("
|
|
180
|
+
).rejects.toThrow("No suitable token utxos available to send token");
|
|
171
181
|
});
|
|
172
182
|
|
|
173
183
|
test("Test mutable NFT cashtoken genesis and mutation", async () => {
|
|
@@ -187,6 +197,7 @@ describe(`Test cashtokens`, () => {
|
|
|
187
197
|
new TokenSendRequest({
|
|
188
198
|
cashaddr: alice.cashaddr!,
|
|
189
199
|
tokenId: tokenId,
|
|
200
|
+
capability: NFTCapability.mutable,
|
|
190
201
|
commitment: "abcd02",
|
|
191
202
|
}),
|
|
192
203
|
]);
|
|
@@ -219,6 +230,7 @@ describe(`Test cashtokens`, () => {
|
|
|
219
230
|
new TokenMintRequest({
|
|
220
231
|
cashaddr: alice.cashaddr!,
|
|
221
232
|
commitment: "test2",
|
|
233
|
+
capability: NFTCapability.none,
|
|
222
234
|
}),
|
|
223
235
|
]);
|
|
224
236
|
expect(await alice.getTokenBalance(tokenId)).toBe(0);
|
|
@@ -248,9 +260,13 @@ describe(`Test cashtokens`, () => {
|
|
|
248
260
|
[
|
|
249
261
|
new TokenMintRequest({
|
|
250
262
|
cashaddr: alice.cashaddr!,
|
|
263
|
+
capability: NFTCapability.none,
|
|
264
|
+
commitment: "0a",
|
|
251
265
|
}),
|
|
252
266
|
new TokenMintRequest({
|
|
253
267
|
cashaddr: alice.cashaddr!,
|
|
268
|
+
capability: NFTCapability.none,
|
|
269
|
+
commitment: "0b",
|
|
254
270
|
}),
|
|
255
271
|
],
|
|
256
272
|
true
|
|
@@ -266,9 +282,13 @@ describe(`Test cashtokens`, () => {
|
|
|
266
282
|
[
|
|
267
283
|
new TokenMintRequest({
|
|
268
284
|
cashaddr: alice.cashaddr!,
|
|
285
|
+
capability: NFTCapability.none,
|
|
286
|
+
commitment: "0c",
|
|
269
287
|
}),
|
|
270
288
|
new TokenMintRequest({
|
|
271
289
|
cashaddr: alice.cashaddr!,
|
|
290
|
+
capability: NFTCapability.none,
|
|
291
|
+
commitment: "0d",
|
|
272
292
|
}),
|
|
273
293
|
],
|
|
274
294
|
false
|
|
@@ -285,12 +305,18 @@ describe(`Test cashtokens`, () => {
|
|
|
285
305
|
[
|
|
286
306
|
new TokenMintRequest({
|
|
287
307
|
cashaddr: alice.cashaddr!,
|
|
308
|
+
capability: NFTCapability.none,
|
|
309
|
+
commitment: "0a",
|
|
288
310
|
}),
|
|
289
311
|
new TokenMintRequest({
|
|
290
312
|
cashaddr: alice.cashaddr!,
|
|
313
|
+
capability: NFTCapability.none,
|
|
314
|
+
commitment: "0a",
|
|
291
315
|
}),
|
|
292
316
|
new TokenMintRequest({
|
|
293
317
|
cashaddr: alice.cashaddr!,
|
|
318
|
+
capability: NFTCapability.none,
|
|
319
|
+
commitment: "0a",
|
|
294
320
|
}),
|
|
295
321
|
],
|
|
296
322
|
true
|
|
@@ -490,6 +516,8 @@ describe(`Test cashtokens`, () => {
|
|
|
490
516
|
amount: 100,
|
|
491
517
|
tokenId: tokenId,
|
|
492
518
|
value: 1500,
|
|
519
|
+
capability: NFTCapability.minting,
|
|
520
|
+
commitment: "test",
|
|
493
521
|
}),
|
|
494
522
|
])),
|
|
495
523
|
0
|
|
@@ -615,6 +643,314 @@ describe(`Test cashtokens`, () => {
|
|
|
615
643
|
expect(tokenUtxos2.length).toBe(1);
|
|
616
644
|
});
|
|
617
645
|
|
|
646
|
+
test("Test minting NFTs not burn tokens", async () => {
|
|
647
|
+
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
648
|
+
const bob = await RegTestWallet.newRandom();
|
|
649
|
+
const charlie = await RegTestWallet.newRandom();
|
|
650
|
+
|
|
651
|
+
// prepare inputs for two token geneses
|
|
652
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
653
|
+
|
|
654
|
+
const genesisResponse = await bob.tokenGenesis({
|
|
655
|
+
capability: "minting",
|
|
656
|
+
commitment: "",
|
|
657
|
+
});
|
|
658
|
+
|
|
659
|
+
const tokenId = genesisResponse.tokenIds![0];
|
|
660
|
+
|
|
661
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
662
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(1);
|
|
663
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(1);
|
|
664
|
+
|
|
665
|
+
await bob.tokenMint(tokenId, {
|
|
666
|
+
capability: "none",
|
|
667
|
+
commitment: "0a",
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
671
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(2);
|
|
672
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(2);
|
|
673
|
+
|
|
674
|
+
await bob.send(
|
|
675
|
+
new TokenSendRequest({
|
|
676
|
+
tokenId: tokenId,
|
|
677
|
+
capability: "none",
|
|
678
|
+
commitment: "0a",
|
|
679
|
+
cashaddr: charlie.cashaddr!,
|
|
680
|
+
})
|
|
681
|
+
);
|
|
682
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
683
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(1);
|
|
684
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(1);
|
|
685
|
+
|
|
686
|
+
expect(await charlie.getTokenBalance(tokenId)).toBe(0);
|
|
687
|
+
expect(await charlie.getNftTokenBalance(tokenId)).toBe(1);
|
|
688
|
+
expect((await charlie.getTokenUtxos(tokenId)).length).toBe(1);
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
test("Test sending NFTs after burning minting token", async () => {
|
|
692
|
+
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
693
|
+
const bob = await RegTestWallet.newRandom();
|
|
694
|
+
const charlie = await RegTestWallet.newRandom();
|
|
695
|
+
|
|
696
|
+
// prepare inputs for two token geneses
|
|
697
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
698
|
+
|
|
699
|
+
const genesisResponse = await bob.tokenGenesis({
|
|
700
|
+
capability: "minting",
|
|
701
|
+
commitment: "",
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
const tokenId = genesisResponse.tokenIds![0];
|
|
705
|
+
|
|
706
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
707
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(1);
|
|
708
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(1);
|
|
709
|
+
|
|
710
|
+
await bob.tokenMint(tokenId, {
|
|
711
|
+
capability: "none",
|
|
712
|
+
commitment: "0a",
|
|
713
|
+
});
|
|
714
|
+
|
|
715
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
716
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(2);
|
|
717
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(2);
|
|
718
|
+
|
|
719
|
+
await bob.tokenMint(tokenId, {
|
|
720
|
+
capability: "none",
|
|
721
|
+
commitment: "0b",
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
725
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(3);
|
|
726
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(3);
|
|
727
|
+
|
|
728
|
+
await bob.tokenBurn({
|
|
729
|
+
tokenId: tokenId,
|
|
730
|
+
capability: "minting",
|
|
731
|
+
commitment: "",
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
735
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(2);
|
|
736
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(2);
|
|
737
|
+
|
|
738
|
+
await bob.send(
|
|
739
|
+
new TokenSendRequest({
|
|
740
|
+
tokenId: tokenId,
|
|
741
|
+
capability: "none",
|
|
742
|
+
commitment: "0a",
|
|
743
|
+
cashaddr: charlie.cashaddr!,
|
|
744
|
+
})
|
|
745
|
+
);
|
|
746
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
747
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(1);
|
|
748
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(1);
|
|
749
|
+
|
|
750
|
+
expect(await charlie.getTokenBalance(tokenId)).toBe(0);
|
|
751
|
+
expect(await charlie.getNftTokenBalance(tokenId)).toBe(1);
|
|
752
|
+
expect((await charlie.getTokenUtxos(tokenId)).length).toBe(1);
|
|
753
|
+
|
|
754
|
+
await bob.send(
|
|
755
|
+
new TokenSendRequest({
|
|
756
|
+
tokenId: tokenId,
|
|
757
|
+
capability: "none",
|
|
758
|
+
commitment: "0b",
|
|
759
|
+
cashaddr: charlie.cashaddr!,
|
|
760
|
+
})
|
|
761
|
+
);
|
|
762
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
763
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(0);
|
|
764
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(0);
|
|
765
|
+
|
|
766
|
+
expect(await charlie.getTokenBalance(tokenId)).toBe(0);
|
|
767
|
+
expect(await charlie.getNftTokenBalance(tokenId)).toBe(2);
|
|
768
|
+
expect((await charlie.getTokenUtxos(tokenId)).length).toBe(2);
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
test("Test sending NFTs with empty commitment", async () => {
|
|
772
|
+
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
773
|
+
const bob = await RegTestWallet.newRandom();
|
|
774
|
+
const charlie = await RegTestWallet.newRandom();
|
|
775
|
+
|
|
776
|
+
// prepare inputs for two token geneses
|
|
777
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
778
|
+
|
|
779
|
+
const genesisResponse = await bob.tokenGenesis({
|
|
780
|
+
capability: "minting",
|
|
781
|
+
commitment: "00",
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
const tokenId = genesisResponse.tokenIds![0];
|
|
785
|
+
|
|
786
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
787
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(1);
|
|
788
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(1);
|
|
789
|
+
|
|
790
|
+
await bob.tokenMint(tokenId, {
|
|
791
|
+
capability: "none",
|
|
792
|
+
commitment: "0a",
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
796
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(2);
|
|
797
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(2);
|
|
798
|
+
|
|
799
|
+
await bob.tokenMint(tokenId, {
|
|
800
|
+
capability: "none",
|
|
801
|
+
commitment: "0b",
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
805
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(3);
|
|
806
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(3);
|
|
807
|
+
|
|
808
|
+
await bob.tokenBurn({
|
|
809
|
+
tokenId: tokenId,
|
|
810
|
+
capability: "minting",
|
|
811
|
+
commitment: "00",
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(0);
|
|
815
|
+
expect(await bob.getNftTokenBalance(tokenId)).toBe(2);
|
|
816
|
+
expect((await bob.getTokenUtxos(tokenId)).length).toBe(2);
|
|
817
|
+
|
|
818
|
+
await expect(
|
|
819
|
+
bob.send(
|
|
820
|
+
new TokenSendRequest({
|
|
821
|
+
tokenId: tokenId,
|
|
822
|
+
capability: "none",
|
|
823
|
+
commitment: "",
|
|
824
|
+
cashaddr: charlie.cashaddr!,
|
|
825
|
+
})
|
|
826
|
+
)
|
|
827
|
+
).rejects.toThrow(
|
|
828
|
+
"No suitable token utxos available to send token with id"
|
|
829
|
+
);
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
test("Should encode unsigned transactions", async () => {
|
|
833
|
+
const aliceWif = `wif:regtest:${process.env.PRIVATE_WIF!}`;
|
|
834
|
+
const aliceWallet = await RegTestWallet.fromId(aliceWif);
|
|
835
|
+
const aliceWatchWallet = await RegTestWallet.watchOnly(
|
|
836
|
+
aliceWallet.cashaddr!
|
|
837
|
+
);
|
|
838
|
+
|
|
839
|
+
{
|
|
840
|
+
const aliceUtxos = await aliceWallet.getAddressUtxos();
|
|
841
|
+
|
|
842
|
+
const { unsignedTransaction, sourceOutputs } =
|
|
843
|
+
await aliceWatchWallet.tokenGenesis(
|
|
844
|
+
{
|
|
845
|
+
capability: "minting",
|
|
846
|
+
commitment: "00",
|
|
847
|
+
},
|
|
848
|
+
undefined,
|
|
849
|
+
{ buildUnsigned: true }
|
|
850
|
+
);
|
|
851
|
+
const encodedTransaction = hexToBin(unsignedTransaction!);
|
|
852
|
+
expect(encodedTransaction.length).toBeGreaterThan(0);
|
|
853
|
+
|
|
854
|
+
// check transaction was not submitted
|
|
855
|
+
expect(JSON.stringify(aliceUtxos)).toBe(
|
|
856
|
+
JSON.stringify(await aliceWallet.getAddressUtxos())
|
|
857
|
+
);
|
|
858
|
+
|
|
859
|
+
const decoded = decodeTransaction(encodedTransaction);
|
|
860
|
+
if (typeof decoded === "string") {
|
|
861
|
+
throw decoded;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
expect(
|
|
865
|
+
binsAreEqual(decoded.inputs[0].unlockingBytecode, Uint8Array.from([]))
|
|
866
|
+
).toBe(true);
|
|
867
|
+
expect(sourceOutputs!.length).toBe(decoded.inputs.length);
|
|
868
|
+
expect(binToHex(decoded.outputs[0].token?.nft?.commitment!)).toBe("00");
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
const genesisResponse = await aliceWallet.tokenGenesis({
|
|
872
|
+
capability: "minting",
|
|
873
|
+
commitment: "00",
|
|
874
|
+
});
|
|
875
|
+
const tokenId = genesisResponse.tokenIds![0];
|
|
876
|
+
|
|
877
|
+
{
|
|
878
|
+
const aliceUtxos = await aliceWallet.getAddressUtxos();
|
|
879
|
+
|
|
880
|
+
const { unsignedTransaction, sourceOutputs } =
|
|
881
|
+
await aliceWatchWallet.tokenMint(
|
|
882
|
+
tokenId,
|
|
883
|
+
{
|
|
884
|
+
capability: "none",
|
|
885
|
+
commitment: "0a",
|
|
886
|
+
},
|
|
887
|
+
undefined,
|
|
888
|
+
{ buildUnsigned: true }
|
|
889
|
+
);
|
|
890
|
+
const encodedTransaction = hexToBin(unsignedTransaction!);
|
|
891
|
+
expect(encodedTransaction.length).toBeGreaterThan(0);
|
|
892
|
+
|
|
893
|
+
// check transaction was not submitted
|
|
894
|
+
expect(JSON.stringify(aliceUtxos)).toBe(
|
|
895
|
+
JSON.stringify(await aliceWallet.getAddressUtxos())
|
|
896
|
+
);
|
|
897
|
+
|
|
898
|
+
const decoded = decodeTransaction(encodedTransaction);
|
|
899
|
+
if (typeof decoded === "string") {
|
|
900
|
+
throw decoded;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
expect(
|
|
904
|
+
binsAreEqual(decoded.inputs[0].unlockingBytecode, Uint8Array.from([]))
|
|
905
|
+
).toBe(true);
|
|
906
|
+
expect(sourceOutputs!.length).toBe(decoded.inputs.length);
|
|
907
|
+
expect(binToHex(sourceOutputs![0].token?.nft?.commitment!)).toBe("00");
|
|
908
|
+
expect(binToHex(decoded.outputs[0].token?.nft?.commitment!)).toBe("00");
|
|
909
|
+
expect(binToHex(decoded.outputs[1].token?.nft?.commitment!)).toBe("0a");
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
await aliceWallet.tokenMint(tokenId, {
|
|
913
|
+
capability: "none",
|
|
914
|
+
commitment: "0a",
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
{
|
|
918
|
+
const aliceUtxos = await aliceWallet.getAddressUtxos();
|
|
919
|
+
|
|
920
|
+
const { unsignedTransaction, sourceOutputs } =
|
|
921
|
+
await aliceWatchWallet.send(
|
|
922
|
+
[
|
|
923
|
+
new TokenSendRequest({
|
|
924
|
+
tokenId: tokenId,
|
|
925
|
+
capability: "none",
|
|
926
|
+
commitment: "0a",
|
|
927
|
+
cashaddr: aliceWallet.cashaddr!,
|
|
928
|
+
}),
|
|
929
|
+
],
|
|
930
|
+
{ buildUnsigned: true }
|
|
931
|
+
);
|
|
932
|
+
const encodedTransaction = hexToBin(unsignedTransaction!);
|
|
933
|
+
expect(encodedTransaction.length).toBeGreaterThan(0);
|
|
934
|
+
|
|
935
|
+
// check transaction was not submitted
|
|
936
|
+
expect(JSON.stringify(aliceUtxos)).toBe(
|
|
937
|
+
JSON.stringify(await aliceWallet.getAddressUtxos())
|
|
938
|
+
);
|
|
939
|
+
|
|
940
|
+
const decoded = decodeTransaction(encodedTransaction);
|
|
941
|
+
if (typeof decoded === "string") {
|
|
942
|
+
throw decoded;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
expect(
|
|
946
|
+
binsAreEqual(decoded.inputs[0].unlockingBytecode, Uint8Array.from([]))
|
|
947
|
+
).toBe(true);
|
|
948
|
+
expect(sourceOutputs!.length).toBe(decoded.inputs.length);
|
|
949
|
+
expect(binToHex(sourceOutputs![0].token?.nft?.commitment!)).toBe("0a");
|
|
950
|
+
expect(binToHex(decoded.outputs[0].token?.nft?.commitment!)).toBe("0a");
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
|
|
618
954
|
test("Test enforcing token addresses", async () => {
|
|
619
955
|
const bob = await RegTestWallet.newRandom();
|
|
620
956
|
|
package/src/wallet/Slp.ts
CHANGED
|
@@ -682,6 +682,7 @@ export class Slp {
|
|
|
682
682
|
utxos: fundingBchUtxos,
|
|
683
683
|
sendRequests: slpOutputsResult.BchSendRequests,
|
|
684
684
|
privateKey: this.wallet.privateKey,
|
|
685
|
+
sourceAddress: this.wallet.cashaddr!,
|
|
685
686
|
relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
|
|
686
687
|
slpOutputs: slpOutputsResult.SlpOutputs,
|
|
687
688
|
feePaidBy: FeePaidByEnum.change,
|
|
@@ -709,19 +710,21 @@ export class Slp {
|
|
|
709
710
|
utxos: fundingUtxos,
|
|
710
711
|
sendRequests: slpOutputsResult.BchSendRequests,
|
|
711
712
|
privateKey: this.wallet.privateKey,
|
|
713
|
+
sourceAddress: this.wallet.cashaddr!,
|
|
712
714
|
relayFeePerByteInSatoshi: relayFeePerByteInSatoshi,
|
|
713
715
|
slpOutputs: slpOutputsResult.SlpOutputs,
|
|
714
716
|
feePaidBy: FeePaidByEnum.change,
|
|
715
717
|
});
|
|
716
718
|
|
|
717
|
-
const encodedTransaction = await buildEncodedTransaction(
|
|
718
|
-
fundingUtxos,
|
|
719
|
-
slpOutputsResult.BchSendRequests,
|
|
720
|
-
this.wallet.privateKey,
|
|
719
|
+
const { encodedTransaction } = await buildEncodedTransaction({
|
|
720
|
+
inputs: fundingUtxos,
|
|
721
|
+
outputs: slpOutputsResult.BchSendRequests,
|
|
722
|
+
signingKey: this.wallet.privateKey,
|
|
723
|
+
sourceAddress: this.wallet.cashaddr!,
|
|
721
724
|
fee,
|
|
722
|
-
false,
|
|
723
|
-
slpOutputsResult.SlpOutputs
|
|
724
|
-
);
|
|
725
|
+
discardChange: false,
|
|
726
|
+
slpOutputs: slpOutputsResult.SlpOutputs,
|
|
727
|
+
});
|
|
725
728
|
|
|
726
729
|
return this._submitTransaction(encodedTransaction, tokenId);
|
|
727
730
|
}
|