mainnet-js 1.0.7 → 1.0.8
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.0.7.js → mainnet-1.0.8.js} +17 -7
- package/dist/module/config.d.ts +4 -0
- package/dist/module/config.d.ts.map +1 -0
- package/dist/module/config.js +4 -0
- package/dist/module/config.js.map +1 -0
- package/dist/module/index.d.ts +1 -0
- package/dist/module/index.d.ts.map +1 -1
- package/dist/module/index.js +2 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.d.ts +6 -2
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +69 -45
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/network/interface.d.ts +11 -8
- package/dist/module/network/interface.d.ts.map +1 -1
- package/dist/module/transaction/Wif.d.ts +1 -1
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +15 -7
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/util/deriveCashaddr.d.ts +1 -0
- package/dist/module/util/deriveCashaddr.d.ts.map +1 -1
- package/dist/module/util/deriveCashaddr.js +5 -0
- package/dist/module/util/deriveCashaddr.js.map +1 -1
- package/dist/module/wallet/Util.d.ts.map +1 -1
- package/dist/module/wallet/Util.js +1 -0
- package/dist/module/wallet/Util.js.map +1 -1
- package/dist/module/wallet/Wif.d.ts +3 -0
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +14 -20
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/interface.d.ts +1 -0
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js +4 -3
- package/dist/module/wallet/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/config.ts +3 -0
- package/src/index.ts +3 -0
- package/src/network/ElectrumNetworkProvider.ts +99 -51
- package/src/network/interface.ts +12 -12
- package/src/transaction/Wif.ts +23 -8
- package/src/util/deriveCashaddr.ts +6 -0
- package/src/wallet/Cashtokens.test.ts +148 -6
- package/src/wallet/Util.ts +1 -0
- package/src/wallet/Wif.test.ts +5 -4
- package/src/wallet/Wif.ts +29 -21
- package/src/wallet/interface.ts +1 -0
- package/src/wallet/model.ts +5 -2
package/src/network/interface.ts
CHANGED
|
@@ -19,23 +19,21 @@ export interface ElectrumClusterParams {
|
|
|
19
19
|
timeout: number;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
export interface ElectrumTokenData {
|
|
23
|
+
amount: string;
|
|
24
|
+
category: string;
|
|
25
|
+
nft?: {
|
|
26
|
+
capability?: NFTCapability;
|
|
27
|
+
commitment?: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
export interface ElectrumUtxo {
|
|
23
32
|
tx_pos: number;
|
|
24
33
|
value: number;
|
|
25
34
|
tx_hash: string;
|
|
26
35
|
height: number;
|
|
27
|
-
token_data
|
|
28
|
-
| {
|
|
29
|
-
amount: string;
|
|
30
|
-
category: string;
|
|
31
|
-
nft:
|
|
32
|
-
| {
|
|
33
|
-
capability: NFTCapability | undefined;
|
|
34
|
-
commitment: string | undefined;
|
|
35
|
-
}
|
|
36
|
-
| undefined;
|
|
37
|
-
}
|
|
38
|
-
| undefined;
|
|
36
|
+
token_data?: ElectrumTokenData;
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
export interface ElectrumRawTransaction {
|
|
@@ -65,12 +63,14 @@ export interface ElectrumRawTransactionVin {
|
|
|
65
63
|
vout: number;
|
|
66
64
|
value?: number; // optional extention by mainnet.cash
|
|
67
65
|
address?: string; // optional extension by mainnet.cash
|
|
66
|
+
tokenData?: ElectrumTokenData; // optional extension by mainnet.cash
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
export interface ElectrumRawTransactionVout {
|
|
71
70
|
n: number;
|
|
72
71
|
scriptPubKey: ElectrumRawTransactionVoutScriptPubKey;
|
|
73
72
|
value: number;
|
|
73
|
+
tokenData?: ElectrumTokenData;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
export interface ElectrumRawTransactionVoutScriptPubKey {
|
package/src/transaction/Wif.ts
CHANGED
|
@@ -286,7 +286,8 @@ export async function getSuitableUtxos(
|
|
|
286
286
|
amountRequired: BigInt | undefined,
|
|
287
287
|
bestHeight: number,
|
|
288
288
|
feePaidBy: FeePaidByEnum,
|
|
289
|
-
requests: SendRequestType[]
|
|
289
|
+
requests: SendRequestType[],
|
|
290
|
+
ensureUtxos: UtxoI[] = []
|
|
290
291
|
): Promise<UtxoI[]> {
|
|
291
292
|
let suitableUtxos: UtxoI[] = [];
|
|
292
293
|
let amountAvailable = BigInt(0);
|
|
@@ -294,6 +295,16 @@ export async function getSuitableUtxos(
|
|
|
294
295
|
const tokenRequests = requests.filter(
|
|
295
296
|
(val) => val instanceof TokenSendRequest
|
|
296
297
|
) as TokenSendRequest[];
|
|
298
|
+
|
|
299
|
+
// if we do a new token genesis, we shall filter all token utxos out
|
|
300
|
+
const isTokenGenesis = tokenRequests.some(
|
|
301
|
+
(val) => !val.tokenId || (val as any)._isGenesis
|
|
302
|
+
);
|
|
303
|
+
const bchOnlyTransfer = tokenRequests.length === 0;
|
|
304
|
+
let filteredInputs =
|
|
305
|
+
isTokenGenesis || bchOnlyTransfer
|
|
306
|
+
? inputs.slice(0).filter((val) => !val.token)
|
|
307
|
+
: inputs.slice();
|
|
297
308
|
const tokenIds = tokenRequests
|
|
298
309
|
.map((val) => val.tokenId)
|
|
299
310
|
.filter((value, index, array) => array.indexOf(value) === index);
|
|
@@ -304,8 +315,6 @@ export async function getSuitableUtxos(
|
|
|
304
315
|
tokenAmountsRequired.push({ tokenId, requiredAmount });
|
|
305
316
|
}
|
|
306
317
|
|
|
307
|
-
let filteredInputs = inputs.slice(0);
|
|
308
|
-
|
|
309
318
|
// find suitable token inputs first
|
|
310
319
|
for (const { tokenId, requiredAmount } of tokenAmountsRequired) {
|
|
311
320
|
let tokenAmountAvailable = 0;
|
|
@@ -325,10 +334,10 @@ export async function getSuitableUtxos(
|
|
|
325
334
|
}
|
|
326
335
|
}
|
|
327
336
|
|
|
328
|
-
// find plain outputs
|
|
337
|
+
// find plain bch outputs
|
|
329
338
|
for (const u of filteredInputs) {
|
|
330
339
|
if (u.token) {
|
|
331
|
-
|
|
340
|
+
continue;
|
|
332
341
|
}
|
|
333
342
|
|
|
334
343
|
if (u.coinbase && u.height && bestHeight) {
|
|
@@ -347,14 +356,20 @@ export async function getSuitableUtxos(
|
|
|
347
356
|
}
|
|
348
357
|
}
|
|
349
358
|
|
|
359
|
+
const addEnsured = (suitableUtxos) => {
|
|
360
|
+
return [...suitableUtxos, ...ensureUtxos].filter(
|
|
361
|
+
(val, index, array) => array.indexOf(val) === index
|
|
362
|
+
);
|
|
363
|
+
};
|
|
364
|
+
|
|
350
365
|
// if the fee is split with a feePaidBy option, skip checking change.
|
|
351
366
|
if (feePaidBy && feePaidBy != FeePaidByEnum.change) {
|
|
352
|
-
return suitableUtxos;
|
|
367
|
+
return addEnsured(suitableUtxos);
|
|
353
368
|
}
|
|
354
369
|
|
|
355
370
|
// If the amount needed is met, or no amount is given, return
|
|
356
371
|
if (typeof amountRequired === "undefined") {
|
|
357
|
-
return suitableUtxos;
|
|
372
|
+
return addEnsured(suitableUtxos);
|
|
358
373
|
} else if (amountAvailable < amountRequired) {
|
|
359
374
|
let e = Error(
|
|
360
375
|
`Amount required was not met, ${amountRequired} satoshis needed, ${amountAvailable} satoshis available`
|
|
@@ -365,7 +380,7 @@ export async function getSuitableUtxos(
|
|
|
365
380
|
};
|
|
366
381
|
throw e;
|
|
367
382
|
} else {
|
|
368
|
-
return suitableUtxos;
|
|
383
|
+
return addEnsured(suitableUtxos);
|
|
369
384
|
}
|
|
370
385
|
}
|
|
371
386
|
|
|
@@ -131,3 +131,9 @@ export function isTokenaddr(address: string): boolean {
|
|
|
131
131
|
].indexOf(result.version) !== -1
|
|
132
132
|
);
|
|
133
133
|
}
|
|
134
|
+
|
|
135
|
+
export function checkTokenaddr(cashaddr: string, enforce: boolean) {
|
|
136
|
+
if (enforce && !isTokenaddr(cashaddr)) {
|
|
137
|
+
throw new Error("Error trying to send to a non-tokenaware cash address");
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { RegTestWallet, TestNetWallet, Wallet } from "./Wif";
|
|
2
2
|
import { initProviders, disconnectProviders } from "../network/Connection";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
SendRequest,
|
|
5
|
+
SendResponse,
|
|
6
|
+
TokenMintRequest,
|
|
7
|
+
TokenSendRequest,
|
|
8
|
+
} from "./model";
|
|
4
9
|
import { Network, NFTCapability } from "../interface";
|
|
5
10
|
import { binToHex, utf8ToBin } from "@bitauth/libauth";
|
|
6
11
|
import { delay } from "../util";
|
|
12
|
+
import { Config } from "../config";
|
|
7
13
|
|
|
8
14
|
beforeAll(async () => {
|
|
9
15
|
await initProviders();
|
|
@@ -194,9 +200,11 @@ describe(`Test cashtokens`, () => {
|
|
|
194
200
|
const response = await alice.tokenMint(tokenId, [
|
|
195
201
|
new TokenMintRequest({
|
|
196
202
|
cashaddr: alice.cashaddr!,
|
|
203
|
+
commitment: "test",
|
|
197
204
|
}),
|
|
198
205
|
new TokenMintRequest({
|
|
199
206
|
cashaddr: alice.cashaddr!,
|
|
207
|
+
commitment: "test2",
|
|
200
208
|
}),
|
|
201
209
|
]);
|
|
202
210
|
expect(await alice.getTokenBalance(tokenId)).toBe(0);
|
|
@@ -313,7 +321,7 @@ describe(`Test cashtokens`, () => {
|
|
|
313
321
|
expect(tokenId).toEqual(response.tokenIds![0]);
|
|
314
322
|
});
|
|
315
323
|
|
|
316
|
-
test("Test explicit burning of FT
|
|
324
|
+
test("Test explicit burning of FT and NFT", async () => {
|
|
317
325
|
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
318
326
|
const genesisResponse = await alice.tokenGenesis({
|
|
319
327
|
cashaddr: alice.cashaddr!,
|
|
@@ -439,13 +447,15 @@ describe(`Test cashtokens`, () => {
|
|
|
439
447
|
expect(bobUtxos[1].satoshis).toBe(3349);
|
|
440
448
|
});
|
|
441
449
|
|
|
442
|
-
test("Test cashtoken waiting and watching
|
|
450
|
+
test("Test cashtoken waiting and watching", async () => {
|
|
443
451
|
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
444
452
|
const bob = await RegTestWallet.newRandom();
|
|
445
453
|
|
|
446
454
|
const genesisResponse = await alice.tokenGenesis({
|
|
447
455
|
amount: 100,
|
|
448
456
|
value: 5000,
|
|
457
|
+
capability: NFTCapability.minting,
|
|
458
|
+
commitment: "test",
|
|
449
459
|
cashaddr: alice.cashaddr!,
|
|
450
460
|
});
|
|
451
461
|
|
|
@@ -457,16 +467,17 @@ describe(`Test cashtokens`, () => {
|
|
|
457
467
|
expect(tokenUtxos[0].satoshis).toBe(5000);
|
|
458
468
|
|
|
459
469
|
let seenBalance = 0;
|
|
470
|
+
let sendResponse: SendResponse = {};
|
|
460
471
|
setTimeout(
|
|
461
|
-
() =>
|
|
462
|
-
alice.send([
|
|
472
|
+
async () =>
|
|
473
|
+
(sendResponse = await alice.send([
|
|
463
474
|
new TokenSendRequest({
|
|
464
475
|
cashaddr: bob.cashaddr!,
|
|
465
476
|
amount: 100,
|
|
466
477
|
tokenId: tokenId,
|
|
467
478
|
value: 1500,
|
|
468
479
|
}),
|
|
469
|
-
]),
|
|
480
|
+
])),
|
|
470
481
|
0
|
|
471
482
|
);
|
|
472
483
|
|
|
@@ -474,10 +485,141 @@ describe(`Test cashtokens`, () => {
|
|
|
474
485
|
seenBalance = balance;
|
|
475
486
|
});
|
|
476
487
|
|
|
488
|
+
let bobTxId = ".";
|
|
489
|
+
const txCancel = bob.watchAddressTokenTransactions((tx) => {
|
|
490
|
+
bobTxId = tx.txid;
|
|
491
|
+
});
|
|
492
|
+
|
|
477
493
|
const balance = await bob.waitForTokenBalance(tokenId, 100);
|
|
494
|
+
await delay(500);
|
|
478
495
|
expect(balance).toBe(100);
|
|
479
496
|
expect(seenBalance).toBe(100);
|
|
497
|
+
expect(sendResponse.txId).toBe(bobTxId);
|
|
480
498
|
await cancel();
|
|
499
|
+
await txCancel();
|
|
481
500
|
await delay(500);
|
|
482
501
|
});
|
|
502
|
+
|
|
503
|
+
test("Test double genesis should not burn tokens", async () => {
|
|
504
|
+
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
505
|
+
const bob = await RegTestWallet.newRandom();
|
|
506
|
+
|
|
507
|
+
// prepare inputs for two token geneses
|
|
508
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
509
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
510
|
+
|
|
511
|
+
const genesisResponse = await bob.tokenGenesis({
|
|
512
|
+
amount: 100,
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
const tokenId = genesisResponse.tokenIds![0];
|
|
516
|
+
const tokenBalance = await bob.getTokenBalance(tokenId);
|
|
517
|
+
|
|
518
|
+
expect(tokenBalance).toBe(100);
|
|
519
|
+
const tokenUtxos = await bob.getTokenUtxos(tokenId);
|
|
520
|
+
expect(tokenUtxos.length).toBe(1);
|
|
521
|
+
|
|
522
|
+
const genesis2Response = await bob.tokenGenesis({
|
|
523
|
+
amount: 200,
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
const tokenId2 = genesis2Response.tokenIds![0];
|
|
527
|
+
const tokenBalance2 = await bob.getTokenBalance(tokenId2);
|
|
528
|
+
expect(tokenBalance2).toBe(200);
|
|
529
|
+
const tokenUtxos2 = await bob.getTokenUtxos(tokenId2);
|
|
530
|
+
expect(tokenUtxos2.length).toBe(1);
|
|
531
|
+
|
|
532
|
+
expect((await bob.getTokenUtxos()).length).toBe(2);
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
test("Test sending tokens should not burn tokens", async () => {
|
|
536
|
+
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
537
|
+
const bob = await RegTestWallet.newRandom();
|
|
538
|
+
|
|
539
|
+
// prepare inputs for two token geneses
|
|
540
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
541
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
542
|
+
|
|
543
|
+
const genesisResponse = await bob.tokenGenesis({
|
|
544
|
+
amount: 100,
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const tokenId = genesisResponse.tokenIds![0];
|
|
548
|
+
const tokenBalance = await bob.getTokenBalance(tokenId);
|
|
549
|
+
|
|
550
|
+
expect(tokenBalance).toBe(100);
|
|
551
|
+
const tokenUtxos = await bob.getTokenUtxos(tokenId);
|
|
552
|
+
expect(tokenUtxos.length).toBe(1);
|
|
553
|
+
|
|
554
|
+
const genesis2Response = await bob.tokenGenesis({
|
|
555
|
+
amount: 200,
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
const tokenId2 = genesis2Response.tokenIds![0];
|
|
559
|
+
const tokenBalance2 = await bob.getTokenBalance(tokenId2);
|
|
560
|
+
expect(tokenBalance2).toBe(200);
|
|
561
|
+
const tokenUtxos2 = await bob.getTokenUtxos(tokenId2);
|
|
562
|
+
expect(tokenUtxos2.length).toBe(1);
|
|
563
|
+
|
|
564
|
+
expect((await bob.getTokenUtxos()).length).toBe(2);
|
|
565
|
+
|
|
566
|
+
const charlie = await RegTestWallet.newRandom();
|
|
567
|
+
await bob.send({
|
|
568
|
+
cashaddr: charlie.cashaddr!,
|
|
569
|
+
tokenId: tokenId,
|
|
570
|
+
amount: 50,
|
|
571
|
+
});
|
|
572
|
+
expect((await bob.getTokenUtxos()).length).toBe(2);
|
|
573
|
+
expect((await charlie.getTokenUtxos()).length).toBe(1);
|
|
574
|
+
expect(await bob.getTokenBalance(tokenId)).toBe(50);
|
|
575
|
+
expect(await charlie.getTokenBalance(tokenId)).toBe(50);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
test("Test sending bch should not burn tokens", async () => {
|
|
579
|
+
const alice = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
580
|
+
const bob = await RegTestWallet.newRandom();
|
|
581
|
+
|
|
582
|
+
// prepare inputs for two token geneses
|
|
583
|
+
await alice.send({ cashaddr: bob.cashaddr!, value: 10000, unit: "sat" });
|
|
584
|
+
|
|
585
|
+
const genesisResponse = await bob.tokenGenesis({
|
|
586
|
+
amount: 100,
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
const tokenId = genesisResponse.tokenIds![0];
|
|
590
|
+
const tokenBalance = await bob.getTokenBalance(tokenId);
|
|
591
|
+
|
|
592
|
+
expect(tokenBalance).toBe(100);
|
|
593
|
+
const tokenUtxos = await bob.getTokenUtxos(tokenId);
|
|
594
|
+
expect(tokenUtxos.length).toBe(1);
|
|
595
|
+
|
|
596
|
+
await bob.send({ cashaddr: alice.cashaddr!, value: 1000, unit: "sat" });
|
|
597
|
+
|
|
598
|
+
const tokenBalance2 = await bob.getTokenBalance(tokenId);
|
|
599
|
+
expect(tokenBalance2).toBe(100);
|
|
600
|
+
const tokenUtxos2 = await bob.getTokenUtxos(tokenId);
|
|
601
|
+
expect(tokenUtxos2.length).toBe(1);
|
|
602
|
+
});
|
|
603
|
+
|
|
604
|
+
test("Test enforcing tokenaddresses", async () => {
|
|
605
|
+
const bob = await RegTestWallet.newRandom();
|
|
606
|
+
|
|
607
|
+
const previousValue = Config.ValidateTokenAddresses;
|
|
608
|
+
|
|
609
|
+
const wrap = (addr) => {
|
|
610
|
+
return new Promise(() => {
|
|
611
|
+
return new TokenSendRequest({ cashaddr: addr, tokenId: "" });
|
|
612
|
+
});
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
Config.ValidateTokenAddresses = false;
|
|
616
|
+
expect(wrap(bob.cashaddr)).resolves.not.toThrow();
|
|
617
|
+
expect(wrap(bob.tokenaddr)).resolves.not.toThrow();
|
|
618
|
+
|
|
619
|
+
Config.ValidateTokenAddresses = true;
|
|
620
|
+
expect(wrap(bob.cashaddr)).rejects.toThrow();
|
|
621
|
+
expect(wrap(bob.tokenaddr)).resolves.not.toThrow();
|
|
622
|
+
|
|
623
|
+
Config.ValidateTokenAddresses = previousValue;
|
|
624
|
+
});
|
|
483
625
|
});
|
package/src/wallet/Util.ts
CHANGED
package/src/wallet/Wif.test.ts
CHANGED
|
@@ -806,11 +806,11 @@ describe(`Wallet subscriptions`, () => {
|
|
|
806
806
|
});
|
|
807
807
|
|
|
808
808
|
let bobWatchResult = false;
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
).watchAddressStatus(bob.getDepositAddress(), (_status) => {
|
|
809
|
+
let bobTransactionId = "";
|
|
810
|
+
const bobWatchCancel = bob.watchAddress((txHash) => {
|
|
812
811
|
bobWatchCancel();
|
|
813
812
|
bobWatchResult = true;
|
|
813
|
+
bobTransactionId = txHash;
|
|
814
814
|
});
|
|
815
815
|
|
|
816
816
|
let bobBalanceWatchResult = false;
|
|
@@ -847,7 +847,7 @@ describe(`Wallet subscriptions`, () => {
|
|
|
847
847
|
blockNumberWaitResult = true;
|
|
848
848
|
}, 0);
|
|
849
849
|
|
|
850
|
-
await alice.send({
|
|
850
|
+
const sendResponse = await alice.send({
|
|
851
851
|
cashaddr: bob.getDepositAddress(),
|
|
852
852
|
value: 0.001,
|
|
853
853
|
unit: "bch",
|
|
@@ -862,6 +862,7 @@ describe(`Wallet subscriptions`, () => {
|
|
|
862
862
|
expect(waitBalanceResult).toBe(true);
|
|
863
863
|
expect(aliceWatchResult).toBe(true);
|
|
864
864
|
expect(bobWatchResult).toBe(true);
|
|
865
|
+
expect(bobTransactionId).toBe(sendResponse.txId);
|
|
865
866
|
expect(bobBalanceWatchResult).toBe(true);
|
|
866
867
|
expect(blockWatchResult).toBe(true);
|
|
867
868
|
expect(blockWaitResult).toBe(true);
|
package/src/wallet/Wif.ts
CHANGED
|
@@ -711,25 +711,32 @@ export class Wallet extends BaseWallet {
|
|
|
711
711
|
return this.getBalanceFromUtxos();
|
|
712
712
|
}
|
|
713
713
|
|
|
714
|
-
//
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
//
|
|
714
|
+
// watching for any transaction hash of this wallet
|
|
715
|
+
public watchAddress(callback: (txHash: string) => void): CancelWatchFn {
|
|
716
|
+
return (this.provider! as ElectrumNetworkProvider).watchAddress(
|
|
717
|
+
this.getDepositAddress(),
|
|
718
|
+
callback
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// watching for any transaction of this wallet
|
|
723
|
+
public watchAddressTransactions(
|
|
724
|
+
callback: (tx: ElectrumRawTransaction) => void
|
|
725
|
+
): CancelWatchFn {
|
|
726
|
+
return (this.provider! as ElectrumNetworkProvider).watchAddressTransactions(
|
|
727
|
+
this.getDepositAddress(),
|
|
728
|
+
callback
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// watching for cashtoken transaction of this wallet
|
|
733
|
+
public watchAddressTokenTransactions(
|
|
734
|
+
callback: (tx: ElectrumRawTransaction) => void
|
|
735
|
+
): CancelWatchFn {
|
|
736
|
+
return (
|
|
737
|
+
this.provider! as ElectrumNetworkProvider
|
|
738
|
+
).watchAddressTokenTransactions(this.getDepositAddress(), callback);
|
|
739
|
+
}
|
|
733
740
|
|
|
734
741
|
// sets up a callback to be called upon wallet's balance change
|
|
735
742
|
// can be cancelled by calling the function returned from this one
|
|
@@ -1195,7 +1202,8 @@ export class Wallet extends BaseWallet {
|
|
|
1195
1202
|
BigInt(spendAmount) + BigInt(feeEstimate),
|
|
1196
1203
|
bestHeight,
|
|
1197
1204
|
feePaidBy,
|
|
1198
|
-
sendRequests
|
|
1205
|
+
sendRequests,
|
|
1206
|
+
options?.ensureUtxos || []
|
|
1199
1207
|
);
|
|
1200
1208
|
if (fundingUtxos.length === 0) {
|
|
1201
1209
|
throw Error(
|
|
@@ -1603,7 +1611,7 @@ export class Wallet extends BaseWallet {
|
|
|
1603
1611
|
return this.send([opReturn, ...changeSendRequests], {
|
|
1604
1612
|
checkTokenQuantities: false,
|
|
1605
1613
|
queryBalance: false,
|
|
1606
|
-
|
|
1614
|
+
ensureUtxos: utxoIds.length > 0 ? utxoIds : undefined,
|
|
1607
1615
|
});
|
|
1608
1616
|
}
|
|
1609
1617
|
|
package/src/wallet/interface.ts
CHANGED
|
@@ -54,6 +54,7 @@ export interface SendRequestOptionsI {
|
|
|
54
54
|
awaitTransactionPropagation?: boolean;
|
|
55
55
|
feePaidBy?: FeePaidByEnum;
|
|
56
56
|
checkTokenQuantities?: boolean; // true
|
|
57
|
+
ensureUtxos?: UtxoI[]; // ensure these inputs will be consumed in the transaction
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
export interface MnemonicI {
|
package/src/wallet/model.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { UnitEnum } from "../enum.js";
|
|
|
4
4
|
import { NFTCapability, UtxoI } from "../interface.js";
|
|
5
5
|
import { DELIMITER } from "../constant.js";
|
|
6
6
|
import { utf8ToBin } from "@bitauth/libauth";
|
|
7
|
+
import { Config } from "../config.js";
|
|
8
|
+
import { checkTokenaddr } from "../util/deriveCashaddr.js";
|
|
7
9
|
|
|
8
10
|
// These are the minimal models used to provide types for the express server
|
|
9
11
|
//
|
|
@@ -116,6 +118,8 @@ export class TokenSendRequest {
|
|
|
116
118
|
capability?: NFTCapability;
|
|
117
119
|
commitment?: string;
|
|
118
120
|
}) {
|
|
121
|
+
checkTokenaddr(cashaddr, Config.ValidateTokenAddresses);
|
|
122
|
+
|
|
119
123
|
this.cashaddr = cashaddr;
|
|
120
124
|
this.value = value;
|
|
121
125
|
this.amount = amount || 0;
|
|
@@ -142,8 +146,7 @@ export class TokenMintRequest {
|
|
|
142
146
|
cashaddr?: string;
|
|
143
147
|
value?: number;
|
|
144
148
|
}) {
|
|
145
|
-
|
|
146
|
-
this.capability = capability || NFTCapability.none;
|
|
149
|
+
this.capability = capability;
|
|
147
150
|
this.commitment = commitment;
|
|
148
151
|
this.cashaddr = cashaddr;
|
|
149
152
|
this.value = value;
|