mainnet-js 3.0.0 → 3.1.0
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-3.0.0.js → mainnet-3.1.0.js} +5 -5
- package/dist/module/history/getHistory.js +10 -10
- package/dist/module/history/getHistory.js.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.d.ts +6 -3
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +18 -11
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/network/NetworkProvider.d.ts +14 -6
- package/dist/module/network/NetworkProvider.d.ts.map +1 -1
- package/dist/module/network/index.d.ts +1 -1
- package/dist/module/network/index.d.ts.map +1 -1
- package/dist/module/network/interface.d.ts +4 -3
- package/dist/module/network/interface.d.ts.map +1 -1
- package/dist/module/wallet/Base.d.ts.map +1 -1
- package/dist/module/wallet/Base.js +1 -2
- package/dist/module/wallet/Base.js.map +1 -1
- package/dist/module/wallet/HDWallet.d.ts +9 -3
- package/dist/module/wallet/HDWallet.d.ts.map +1 -1
- package/dist/module/wallet/HDWallet.js +43 -24
- package/dist/module/wallet/HDWallet.js.map +1 -1
- package/dist/module/wallet/Util.d.ts +5 -3
- package/dist/module/wallet/Util.d.ts.map +1 -1
- package/dist/module/wallet/Util.js +28 -22
- package/dist/module/wallet/Util.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/history/getHistory.ts +15 -15
- package/src/network/ElectrumNetworkProvider.ts +61 -26
- package/src/network/NetworkProvider.ts +44 -6
- package/src/network/index.ts +5 -1
- package/src/network/interface.ts +8 -3
- package/src/wallet/Base.ts +1 -4
- package/src/wallet/HDWallet.test.ts +239 -0
- package/src/wallet/HDWallet.ts +49 -26
- package/src/wallet/Util.test.ts +5 -6
- package/src/wallet/Util.ts +67 -46
- package/src/wallet/Wif.test.ts +3 -9
package/src/wallet/HDWallet.ts
CHANGED
|
@@ -414,6 +414,12 @@ export class HDWallet extends BaseWallet {
|
|
|
414
414
|
if (newIndex > getCurrentIndex()) {
|
|
415
415
|
setCurrentIndex(newIndex);
|
|
416
416
|
}
|
|
417
|
+
|
|
418
|
+
// Maintain the gap: extend watched range if it shrank
|
|
419
|
+
const gap = statuses.length - getCurrentIndex();
|
|
420
|
+
if (gap < gapSize) {
|
|
421
|
+
await this.watchAddressType(isChange, gapSize);
|
|
422
|
+
}
|
|
417
423
|
}
|
|
418
424
|
|
|
419
425
|
// Notify wallet watchers of the status change
|
|
@@ -463,46 +469,63 @@ export class HDWallet extends BaseWallet {
|
|
|
463
469
|
* @returns Cancel function to stop watching
|
|
464
470
|
*/
|
|
465
471
|
public async watchStatus(
|
|
466
|
-
callback: (status: string | null, address: string) => void
|
|
472
|
+
callback: (status: string | null, address: string) => void,
|
|
473
|
+
debounce: number = 100
|
|
467
474
|
): Promise<CancelFn> {
|
|
468
475
|
await this.watchPromise;
|
|
469
476
|
|
|
470
|
-
|
|
477
|
+
let debounceTimer: ReturnType<typeof setTimeout> | undefined;
|
|
478
|
+
let pendingStatus: string | null = null;
|
|
479
|
+
let pendingAddress: string = "";
|
|
480
|
+
|
|
481
|
+
const debouncedCallback = (status: string | null, address: string) => {
|
|
482
|
+
pendingStatus = status;
|
|
483
|
+
pendingAddress = address;
|
|
484
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
485
|
+
debounceTimer = setTimeout(() => {
|
|
486
|
+
debounceTimer = undefined;
|
|
487
|
+
callback(pendingStatus, pendingAddress);
|
|
488
|
+
}, debounce);
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
this.walletWatchCallbacks.push(debouncedCallback);
|
|
471
492
|
|
|
472
493
|
return async () => {
|
|
473
|
-
|
|
494
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
495
|
+
const index = this.walletWatchCallbacks.indexOf(debouncedCallback);
|
|
474
496
|
if (index > -1) {
|
|
475
497
|
this.walletWatchCallbacks.splice(index, 1);
|
|
476
498
|
}
|
|
477
499
|
};
|
|
478
500
|
}
|
|
479
501
|
|
|
480
|
-
|
|
481
|
-
|
|
502
|
+
/**
|
|
503
|
+
* Watch wallet for new transactions (HD wallet override)
|
|
504
|
+
*
|
|
505
|
+
* Uses unfiltered history so that seenTxHashes always covers all known
|
|
506
|
+
* transactions, including those from newly discovered addresses when
|
|
507
|
+
* depositIndex/changeIndex extends and widens getRawHistory's scope.
|
|
508
|
+
*/
|
|
509
|
+
public override async watchTransactionHashes(
|
|
510
|
+
callback: (txHash: string) => void
|
|
482
511
|
): Promise<CancelFn> {
|
|
483
|
-
|
|
512
|
+
const seenTxHashes = new Set<string>();
|
|
513
|
+
|
|
484
514
|
return this.watchStatus(async () => {
|
|
485
|
-
|
|
486
|
-
debounceTimer = setTimeout(async () => {
|
|
487
|
-
debounceTimer = undefined;
|
|
488
|
-
const balance = await this.getBalance();
|
|
489
|
-
callback(balance);
|
|
490
|
-
}, 100);
|
|
491
|
-
});
|
|
492
|
-
}
|
|
515
|
+
const history = await this.getRawHistory();
|
|
493
516
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
callback(
|
|
505
|
-
}
|
|
517
|
+
const newTxHashes: string[] = [];
|
|
518
|
+
|
|
519
|
+
for (const tx of history) {
|
|
520
|
+
if (!seenTxHashes.has(tx.tx_hash)) {
|
|
521
|
+
seenTxHashes.add(tx.tx_hash);
|
|
522
|
+
newTxHashes.push(tx.tx_hash);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (newTxHashes.length > 0) {
|
|
527
|
+
newTxHashes.forEach((txHash) => callback(txHash));
|
|
528
|
+
}
|
|
506
529
|
});
|
|
507
530
|
}
|
|
508
531
|
|
package/src/wallet/Util.test.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { initProviders, disconnectProviders } from "../network";
|
|
2
|
-
import { ElectrumRawTransaction } from "../network/interface";
|
|
3
2
|
import { RegTestWallet, Wallet } from "./Wif";
|
|
4
3
|
|
|
5
4
|
beforeAll(async () => {
|
|
@@ -41,9 +40,9 @@ describe("Utility tests", () => {
|
|
|
41
40
|
test("Should get raw transaction", async () => {
|
|
42
41
|
let wallet = await RegTestWallet.fromId(process.env.ALICE_ID!);
|
|
43
42
|
const utxo = (await wallet.getUtxos())[0];
|
|
44
|
-
const transaction =
|
|
43
|
+
const transaction = await wallet.provider!.getRawTransactionObject(
|
|
45
44
|
utxo.txid
|
|
46
|
-
)
|
|
45
|
+
);
|
|
47
46
|
expect((await wallet.util.decodeTransaction(transaction.hash)).hash).toBe(
|
|
48
47
|
utxo.txid
|
|
49
48
|
);
|
|
@@ -67,15 +66,15 @@ describe("Utility tests", () => {
|
|
|
67
66
|
"0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
|
|
68
67
|
);
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
expect(decoded.vin[0].
|
|
69
|
+
// non-enriched vin entries don't carry vout fields (enforced by types)
|
|
70
|
+
expect((decoded.vin[0] as any).address).toBeUndefined();
|
|
72
71
|
});
|
|
73
72
|
|
|
74
73
|
test("Should decode a transaction and fetch input values and addresses", async () => {
|
|
75
74
|
const txHash =
|
|
76
75
|
"dc8f059900807c36941313f10b43ec049e23dfede4e09f8fbccc3871ed359fbe";
|
|
77
76
|
const decoded = await Wallet.util.decodeTransaction(txHash, true);
|
|
78
|
-
expect(decoded.vin[0].
|
|
77
|
+
expect(decoded.vin[0].scriptPubKey.addresses[0]).toBeDefined();
|
|
79
78
|
expect(decoded.vin[0].value).toBeDefined();
|
|
80
79
|
|
|
81
80
|
// uncomment next line
|
package/src/wallet/Util.ts
CHANGED
|
@@ -15,9 +15,9 @@ import { getNetworkProvider } from "../network/default.js";
|
|
|
15
15
|
import {
|
|
16
16
|
ElectrumRawTransaction,
|
|
17
17
|
ElectrumRawTransactionVin,
|
|
18
|
-
|
|
18
|
+
ElectrumRawTransactionVinWithValues,
|
|
19
19
|
ElectrumRawTransactionVout,
|
|
20
|
-
|
|
20
|
+
ElectrumRawTransactionWithInputValues,
|
|
21
21
|
} from "../network/interface.js";
|
|
22
22
|
import NetworkProvider from "../network/NetworkProvider.js";
|
|
23
23
|
import { getTransactionHash } from "../util/transaction.js";
|
|
@@ -49,10 +49,18 @@ export class Util {
|
|
|
49
49
|
return getTransactionHash(rawTransactionHex);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
public async decodeTransaction(
|
|
53
|
+
transactionHashOrHex: string,
|
|
54
|
+
loadInputValues: true
|
|
55
|
+
): Promise<ElectrumRawTransactionWithInputValues>;
|
|
56
|
+
public async decodeTransaction(
|
|
57
|
+
transactionHashOrHex: string,
|
|
58
|
+
loadInputValues?: false
|
|
59
|
+
): Promise<ElectrumRawTransaction>;
|
|
52
60
|
public async decodeTransaction(
|
|
53
61
|
transactionHashOrHex: string,
|
|
54
62
|
loadInputValues: boolean = false
|
|
55
|
-
): Promise<ElectrumRawTransaction> {
|
|
63
|
+
): Promise<ElectrumRawTransaction | ElectrumRawTransactionWithInputValues> {
|
|
56
64
|
let transactionHex: string;
|
|
57
65
|
let transactionBin: Uint8Array;
|
|
58
66
|
let txHash: string;
|
|
@@ -89,14 +97,15 @@ export class Util {
|
|
|
89
97
|
const transactionMap = new Map<string, ElectrumRawTransaction>();
|
|
90
98
|
transactions.forEach((val) => transactionMap.set(val.hash, val));
|
|
91
99
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
const enrichedVin: ElectrumRawTransactionVinWithValues[] =
|
|
101
|
+
transaction.vin.map((input) => {
|
|
102
|
+
const output = transactionMap
|
|
103
|
+
.get(input.txid)!
|
|
104
|
+
.vout.find((val) => val.n === input.vout)!;
|
|
105
|
+
return { ...input, ...output };
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return { ...transaction, vin: enrichedVin };
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
return transaction;
|
|
@@ -107,22 +116,30 @@ export class Util {
|
|
|
107
116
|
txHash: string,
|
|
108
117
|
txHex: string
|
|
109
118
|
): ElectrumRawTransaction {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
119
|
+
return {
|
|
120
|
+
blockhash: "",
|
|
121
|
+
blocktime: 0,
|
|
122
|
+
confirmations: 0,
|
|
123
|
+
time: 0,
|
|
124
|
+
hash: txHash,
|
|
125
|
+
hex: txHex,
|
|
126
|
+
txid: txHash,
|
|
127
|
+
locktime: transaction.locktime,
|
|
128
|
+
version: transaction.version,
|
|
129
|
+
size: txHex.length / 2,
|
|
130
|
+
vin: transaction.inputs.map(
|
|
131
|
+
(input): ElectrumRawTransactionVin => ({
|
|
132
|
+
scriptSig: {
|
|
133
|
+
asm: "",
|
|
134
|
+
hex: binToHex(input.unlockingBytecode),
|
|
135
|
+
},
|
|
136
|
+
sequence: input.sequenceNumber,
|
|
137
|
+
txid: binToHex(input.outpointTransactionHash),
|
|
138
|
+
vout: input.outpointIndex,
|
|
139
|
+
})
|
|
140
|
+
),
|
|
141
|
+
vout: transaction.outputs.map(
|
|
142
|
+
(output, index): ElectrumRawTransactionVout => ({
|
|
126
143
|
n: index,
|
|
127
144
|
scriptPubKey: {
|
|
128
145
|
addresses: [
|
|
@@ -132,7 +149,7 @@ export class Util {
|
|
|
132
149
|
output.lockingBytecode
|
|
133
150
|
).payload,
|
|
134
151
|
prefix: prefixFromNetworkMap[this.network],
|
|
135
|
-
})
|
|
152
|
+
}).address
|
|
136
153
|
: assertSuccess(
|
|
137
154
|
lockingBytecodeToCashAddress({
|
|
138
155
|
bytecode: output.lockingBytecode,
|
|
@@ -140,31 +157,35 @@ export class Util {
|
|
|
140
157
|
})
|
|
141
158
|
).address,
|
|
142
159
|
],
|
|
160
|
+
asm: "",
|
|
143
161
|
hex: binToHex(output.lockingBytecode),
|
|
144
|
-
|
|
162
|
+
reqSigs: 1,
|
|
163
|
+
type: "",
|
|
164
|
+
},
|
|
145
165
|
value: Number(output.valueSatoshis) / Number(bchParam.subUnits),
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
result.locktime = transaction.locktime;
|
|
151
|
-
result.version = transaction.version;
|
|
152
|
-
result.hash = txHash;
|
|
153
|
-
result.hex = txHex;
|
|
154
|
-
result.txid = txHash;
|
|
155
|
-
result.size = txHex.length / 2;
|
|
156
|
-
|
|
157
|
-
return result;
|
|
166
|
+
})
|
|
167
|
+
),
|
|
168
|
+
};
|
|
158
169
|
}
|
|
159
170
|
|
|
171
|
+
public static async decodeTransaction(
|
|
172
|
+
transactionHashOrHex: string,
|
|
173
|
+
loadInputValues: true,
|
|
174
|
+
network?: NetworkType
|
|
175
|
+
): Promise<ElectrumRawTransactionWithInputValues>;
|
|
176
|
+
public static async decodeTransaction(
|
|
177
|
+
transactionHashOrHex: string,
|
|
178
|
+
loadInputValues?: false,
|
|
179
|
+
network?: NetworkType
|
|
180
|
+
): Promise<ElectrumRawTransaction>;
|
|
160
181
|
public static async decodeTransaction(
|
|
161
182
|
transactionHashOrHex: string,
|
|
162
183
|
loadInputValues: boolean = false,
|
|
163
184
|
network?: NetworkType
|
|
164
|
-
): Promise<ElectrumRawTransaction> {
|
|
165
|
-
|
|
166
|
-
transactionHashOrHex,
|
|
167
|
-
|
|
168
|
-
);
|
|
185
|
+
): Promise<ElectrumRawTransaction | ElectrumRawTransactionWithInputValues> {
|
|
186
|
+
if (loadInputValues) {
|
|
187
|
+
return new this(network).decodeTransaction(transactionHashOrHex, true);
|
|
188
|
+
}
|
|
189
|
+
return new this(network).decodeTransaction(transactionHashOrHex);
|
|
169
190
|
}
|
|
170
191
|
}
|
package/src/wallet/Wif.test.ts
CHANGED
|
@@ -995,9 +995,7 @@ describe(`Wallet extrema behavior regression testing`, () => {
|
|
|
995
995
|
OpReturnData.from("MEMO\x10LÖL😅"),
|
|
996
996
|
{ cashaddr: wallet.cashaddr!, value: 546n },
|
|
997
997
|
]);
|
|
998
|
-
transaction =
|
|
999
|
-
result.txId!
|
|
1000
|
-
)) as ElectrumRawTransaction;
|
|
998
|
+
transaction = await wallet.provider!.getRawTransactionObject(result.txId!);
|
|
1001
999
|
expect(transaction.vout[0].scriptPubKey.asm).toContain("OP_RETURN");
|
|
1002
1000
|
expect(transaction.vout[0].scriptPubKey.hex.slice(4)).toBe(
|
|
1003
1001
|
binToHex(utf8ToBin("MEMO\x10LÖL😅"))
|
|
@@ -1007,9 +1005,7 @@ describe(`Wallet extrema behavior regression testing`, () => {
|
|
|
1007
1005
|
[wallet.cashaddr!, 546n],
|
|
1008
1006
|
["OP_RETURN", Uint8Array.from([0x00, 0x01, 0x02])],
|
|
1009
1007
|
]);
|
|
1010
|
-
transaction =
|
|
1011
|
-
result.txId!
|
|
1012
|
-
)) as ElectrumRawTransaction;
|
|
1008
|
+
transaction = await wallet.provider!.getRawTransactionObject(result.txId!);
|
|
1013
1009
|
expect(transaction.vout[1].scriptPubKey.asm).toContain("OP_RETURN");
|
|
1014
1010
|
expect([
|
|
1015
1011
|
...hexToBin(transaction.vout[1].scriptPubKey.hex.slice(4)),
|
|
@@ -1019,9 +1015,7 @@ describe(`Wallet extrema behavior regression testing`, () => {
|
|
|
1019
1015
|
OpReturnData.from(""),
|
|
1020
1016
|
OpReturnData.from(Uint8Array.from([])),
|
|
1021
1017
|
]);
|
|
1022
|
-
transaction =
|
|
1023
|
-
result.txId!
|
|
1024
|
-
)) as ElectrumRawTransaction;
|
|
1018
|
+
transaction = await wallet.provider!.getRawTransactionObject(result.txId!);
|
|
1025
1019
|
expect(transaction.vout[0].scriptPubKey.asm).toContain("OP_RETURN");
|
|
1026
1020
|
expect([...hexToBin(transaction.vout[0].scriptPubKey.hex)]).toStrictEqual([
|
|
1027
1021
|
0x6a, 0x00,
|