mainnet-js 2.7.31 → 3.0.0-next.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-2.7.31.js → mainnet-3.0.0-next.0.js} +718 -678
- package/dist/module/cache/MemoryCache.d.ts +0 -1
- package/dist/module/cache/MemoryCache.d.ts.map +1 -1
- package/dist/module/cache/MemoryCache.js +5 -7
- package/dist/module/cache/MemoryCache.js.map +1 -1
- package/dist/module/cache/index.d.ts +1 -0
- package/dist/module/cache/index.d.ts.map +1 -1
- package/dist/module/cache/index.js +1 -0
- package/dist/module/cache/index.js.map +1 -1
- package/dist/module/cache/walletCache.d.ts +39 -0
- package/dist/module/cache/walletCache.d.ts.map +1 -0
- package/dist/module/cache/walletCache.js +141 -0
- package/dist/module/cache/walletCache.js.map +1 -0
- package/dist/module/history/{electrumTransformer.d.ts → getHistory.d.ts} +3 -3
- package/dist/module/history/getHistory.d.ts.map +1 -0
- package/dist/module/history/{electrumTransformer.js → getHistory.js} +47 -14
- package/dist/module/history/getHistory.js.map +1 -0
- package/dist/module/index.d.ts +3 -1
- package/dist/module/index.d.ts.map +1 -1
- package/dist/module/index.js +3 -1
- package/dist/module/index.js.map +1 -1
- package/dist/module/interface.d.ts +7 -1
- package/dist/module/interface.d.ts.map +1 -1
- package/dist/module/interface.js.map +1 -1
- package/dist/module/message/interface.d.ts +2 -2
- package/dist/module/message/interface.d.ts.map +1 -1
- package/dist/module/message/interface.js +0 -3
- package/dist/module/message/interface.js.map +1 -1
- package/dist/module/message/signed.d.ts +5 -5
- package/dist/module/message/signed.d.ts.map +1 -1
- package/dist/module/message/signed.js +14 -14
- package/dist/module/message/signed.js.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.d.ts +2 -2
- package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
- package/dist/module/network/ElectrumNetworkProvider.js +2 -1
- package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
- package/dist/module/network/NetworkProvider.d.ts +2 -2
- package/dist/module/network/NetworkProvider.d.ts.map +1 -1
- package/dist/module/network/constant.js +4 -4
- package/dist/module/network/constant.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +21 -19
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +18 -15
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/util/checkUtxos.d.ts +2 -2
- package/dist/module/util/checkUtxos.d.ts.map +1 -1
- package/dist/module/util/checkUtxos.js +11 -12
- package/dist/module/util/checkUtxos.js.map +1 -1
- package/dist/module/util/deriveCashaddr.d.ts.map +1 -1
- package/dist/module/util/deriveCashaddr.js +6 -0
- package/dist/module/util/deriveCashaddr.js.map +1 -1
- package/dist/module/util/deriveNetwork.js +1 -1
- package/dist/module/util/deriveNetwork.js.map +1 -1
- package/dist/module/util/hd.d.ts +3 -0
- package/dist/module/util/hd.d.ts.map +1 -0
- package/dist/module/util/hd.js +11 -0
- package/dist/module/util/hd.js.map +1 -0
- package/dist/module/util/index.d.ts +1 -0
- package/dist/module/util/index.d.ts.map +1 -1
- package/dist/module/util/index.js +1 -0
- package/dist/module/util/index.js.map +1 -1
- package/dist/module/util/sumUtxoValue.d.ts +3 -3
- package/dist/module/util/sumUtxoValue.d.ts.map +1 -1
- package/dist/module/util/sumUtxoValue.js.map +1 -1
- package/dist/module/wallet/Base.d.ts +37 -93
- package/dist/module/wallet/Base.d.ts.map +1 -1
- package/dist/module/wallet/Base.js +83 -250
- package/dist/module/wallet/Base.js.map +1 -1
- package/dist/module/wallet/HDWallet.d.ts +164 -0
- package/dist/module/wallet/HDWallet.d.ts.map +1 -0
- package/dist/module/wallet/HDWallet.js +486 -0
- package/dist/module/wallet/HDWallet.js.map +1 -0
- package/dist/module/wallet/Watch.d.ts +151 -0
- package/dist/module/wallet/Watch.d.ts.map +1 -0
- package/dist/module/wallet/Watch.js +307 -0
- package/dist/module/wallet/Watch.js.map +1 -0
- package/dist/module/wallet/Wif.d.ts +23 -29
- package/dist/module/wallet/Wif.d.ts.map +1 -1
- package/dist/module/wallet/Wif.js +204 -267
- package/dist/module/wallet/Wif.js.map +1 -1
- package/dist/module/wallet/createWallet.d.ts +7 -1
- package/dist/module/wallet/createWallet.d.ts.map +1 -1
- package/dist/module/wallet/createWallet.js +26 -17
- package/dist/module/wallet/createWallet.js.map +1 -1
- package/dist/module/wallet/interface.d.ts +3 -3
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts +3 -3
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js +2 -18
- package/dist/module/wallet/model.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/cache/MemoryCache.ts +5 -5
- package/src/cache/index.ts +1 -0
- package/src/cache/walletCache.ts +252 -0
- package/src/history/{electrumTransformer.test.ts → getHistory.test.ts} +6 -19
- package/src/history/{electrumTransformer.ts → getHistory.ts} +63 -15
- package/src/index.ts +3 -1
- package/src/interface.ts +8 -1
- package/src/message/interface.ts +2 -28
- package/src/message/signed.test.ts +56 -48
- package/src/message/signed.ts +15 -18
- package/src/network/ElectrumNetworkProvider.ts +4 -4
- package/src/network/NetworkProvider.ts +2 -2
- package/src/network/Rpc.test.ts +1 -1
- package/src/network/constant.ts +4 -4
- package/src/transaction/Wif.ts +41 -35
- package/src/util/checkUtxos.ts +21 -26
- package/src/util/deriveCashaddr.ts +8 -0
- package/src/util/deriveNetwork.ts +1 -1
- package/src/util/derivePublicKeyHash.test.ts +0 -13
- package/src/util/hd.ts +16 -0
- package/src/util/index.ts +1 -0
- package/src/util/sumUtxoValue.ts +5 -5
- package/src/wallet/Base.ts +123 -332
- package/src/wallet/HDWallet.test.ts +372 -0
- package/src/wallet/HDWallet.ts +764 -0
- package/src/wallet/Watch.ts +447 -0
- package/src/wallet/Wif.ts +258 -283
- package/src/wallet/createWallet.ts +28 -18
- package/src/wallet/interface.ts +3 -3
- package/src/wallet/model.test.ts +2 -2
- package/src/wallet/model.ts +6 -23
- package/dist/module/history/electrumTransformer.d.ts.map +0 -1
- package/dist/module/history/electrumTransformer.js.map +0 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertSuccess,
|
|
3
|
+
CashAddressNetworkPrefix,
|
|
4
|
+
CashAddressType,
|
|
5
|
+
deriveHdPathRelative,
|
|
6
|
+
encodeCashAddress,
|
|
7
|
+
hash160,
|
|
8
|
+
HdPrivateNodeValid,
|
|
9
|
+
HdPublicNodeValid,
|
|
10
|
+
secp256k1,
|
|
11
|
+
} from "@bitauth/libauth";
|
|
12
|
+
import { Config } from "../config.js";
|
|
13
|
+
import { CacheProvider } from "./interface.js";
|
|
14
|
+
import { IndexedDbCache } from "./IndexedDbCache.js";
|
|
15
|
+
import { MemoryCache } from "./MemoryCache.js";
|
|
16
|
+
import { WebStorageCache } from "./WebStorageCache.js";
|
|
17
|
+
import { Utxo } from "../interface.js";
|
|
18
|
+
|
|
19
|
+
// export const addressCache: Record<string, {
|
|
20
|
+
// privateKey: Uint8Array | undefined,
|
|
21
|
+
// publicKey: Uint8Array,
|
|
22
|
+
// publicKeyHash: Uint8Array,
|
|
23
|
+
// index: number,
|
|
24
|
+
// change: boolean,
|
|
25
|
+
// }> = {};
|
|
26
|
+
|
|
27
|
+
export interface WalletCacheEntry {
|
|
28
|
+
address: string;
|
|
29
|
+
tokenAddress: string;
|
|
30
|
+
privateKey: Uint8Array | undefined;
|
|
31
|
+
publicKey: Uint8Array;
|
|
32
|
+
publicKeyHash: Uint8Array;
|
|
33
|
+
index: number;
|
|
34
|
+
change: boolean;
|
|
35
|
+
status: string | null;
|
|
36
|
+
utxos: Utxo[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// export const getPrivateKey = (
|
|
40
|
+
// hdNode: HdPrivateNodeValid,
|
|
41
|
+
// addressIndex: number,
|
|
42
|
+
// change: boolean,
|
|
43
|
+
// ): Uint8Array => {
|
|
44
|
+
// const node = deriveHdPathRelative(
|
|
45
|
+
// hdNode,
|
|
46
|
+
// `${change ? 1 : 0}/${addressIndex}`
|
|
47
|
+
// );
|
|
48
|
+
|
|
49
|
+
// return node.privateKey;
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
export interface WalletCacheI {
|
|
53
|
+
init(): Promise<void>;
|
|
54
|
+
persist(): Promise<void>;
|
|
55
|
+
getByIndex(addressIndex: number, change: boolean): WalletCacheEntry;
|
|
56
|
+
getByAddress(address: string): WalletCacheEntry | undefined;
|
|
57
|
+
setStatusAndUtxos(
|
|
58
|
+
address: string,
|
|
59
|
+
status: string | null,
|
|
60
|
+
utxos: Utxo[]
|
|
61
|
+
): void;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class WalletCache implements WalletCacheI {
|
|
65
|
+
private _storage: CacheProvider | undefined;
|
|
66
|
+
private walletCache: Record<string, WalletCacheEntry> = {};
|
|
67
|
+
private indexCache: Record<
|
|
68
|
+
string,
|
|
69
|
+
{
|
|
70
|
+
index: number;
|
|
71
|
+
change: boolean;
|
|
72
|
+
}
|
|
73
|
+
> = {};
|
|
74
|
+
private timeouts: NodeJS.Timeout[] = [];
|
|
75
|
+
|
|
76
|
+
get storage(): CacheProvider | undefined {
|
|
77
|
+
if (
|
|
78
|
+
!Config.UseMemoryCache &&
|
|
79
|
+
!Config.UseLocalStorageCache &&
|
|
80
|
+
!Config.UseIndexedDBCache
|
|
81
|
+
) {
|
|
82
|
+
this._storage = undefined;
|
|
83
|
+
return this._storage;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (Config.UseMemoryCache && !(this._storage instanceof MemoryCache)) {
|
|
87
|
+
this._storage = new MemoryCache();
|
|
88
|
+
return this._storage;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (
|
|
92
|
+
Config.UseLocalStorageCache &&
|
|
93
|
+
!(this._storage instanceof WebStorageCache)
|
|
94
|
+
) {
|
|
95
|
+
this._storage = new WebStorageCache();
|
|
96
|
+
return this._storage;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (
|
|
100
|
+
Config.UseIndexedDBCache &&
|
|
101
|
+
!(this._storage instanceof IndexedDbCache)
|
|
102
|
+
) {
|
|
103
|
+
this._storage = new IndexedDbCache();
|
|
104
|
+
return this._storage;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return this._storage;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
constructor(
|
|
111
|
+
public walletId: string,
|
|
112
|
+
public hdNode: HdPublicNodeValid | HdPrivateNodeValid,
|
|
113
|
+
public networkPrefix: string,
|
|
114
|
+
public writeTimeout: number = 2000
|
|
115
|
+
) {
|
|
116
|
+
if (!this.hdNode) {
|
|
117
|
+
throw new Error("HDNode is undefined");
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public async init() {
|
|
122
|
+
await this.storage?.init();
|
|
123
|
+
const data = await this.storage?.getItem(`walletCache-${this.walletId}`);
|
|
124
|
+
if (data) {
|
|
125
|
+
try {
|
|
126
|
+
const parsed = JSON.parse(data);
|
|
127
|
+
this.walletCache = parsed.walletCache || {};
|
|
128
|
+
this.indexCache = parsed.indexCache || {};
|
|
129
|
+
} catch (e) {
|
|
130
|
+
// ignore
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public async persist() {
|
|
136
|
+
this.timeouts.map(clearTimeout);
|
|
137
|
+
this.timeouts = [];
|
|
138
|
+
|
|
139
|
+
this.storage?.setItem(
|
|
140
|
+
`walletCache-${this.walletId}`,
|
|
141
|
+
JSON.stringify({
|
|
142
|
+
walletCache: this.walletCache,
|
|
143
|
+
indexCache: this.indexCache,
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public getByIndex(addressIndex: number, change: boolean) {
|
|
149
|
+
const id = `${this.walletId}-${addressIndex}-${change}`;
|
|
150
|
+
if (!this.walletCache[id]) {
|
|
151
|
+
const node = deriveHdPathRelative(
|
|
152
|
+
this.hdNode,
|
|
153
|
+
`${change ? 1 : 0}/${addressIndex}`
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const privateKey = "privateKey" in node ? node.privateKey : undefined;
|
|
157
|
+
const publicKey =
|
|
158
|
+
"publicKey" in node
|
|
159
|
+
? node.publicKey
|
|
160
|
+
: assertSuccess(secp256k1.derivePublicKeyUncompressed(privateKey!));
|
|
161
|
+
const publicKeyCompressed = assertSuccess(
|
|
162
|
+
secp256k1.compressPublicKey(publicKey)
|
|
163
|
+
);
|
|
164
|
+
const publicKeyHash = hash160(publicKeyCompressed);
|
|
165
|
+
|
|
166
|
+
const address = encodeCashAddress({
|
|
167
|
+
throwErrors: true,
|
|
168
|
+
prefix: this.networkPrefix as CashAddressNetworkPrefix,
|
|
169
|
+
type: CashAddressType.p2pkh,
|
|
170
|
+
payload: publicKeyHash,
|
|
171
|
+
}).address;
|
|
172
|
+
|
|
173
|
+
const tokenAddress = encodeCashAddress({
|
|
174
|
+
throwErrors: true,
|
|
175
|
+
prefix: this.networkPrefix as CashAddressNetworkPrefix,
|
|
176
|
+
type: CashAddressType.p2pkhWithTokens,
|
|
177
|
+
payload: publicKeyHash,
|
|
178
|
+
}).address;
|
|
179
|
+
|
|
180
|
+
this.walletCache[id] = {
|
|
181
|
+
address,
|
|
182
|
+
tokenAddress,
|
|
183
|
+
privateKey: privateKey,
|
|
184
|
+
publicKey,
|
|
185
|
+
publicKeyHash,
|
|
186
|
+
index: addressIndex,
|
|
187
|
+
change,
|
|
188
|
+
status: null,
|
|
189
|
+
utxos: [],
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
this.indexCache[address] = {
|
|
193
|
+
index: addressIndex,
|
|
194
|
+
change,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// batch new data into a single writeout
|
|
198
|
+
this.timeouts.push(
|
|
199
|
+
setTimeout(() => {
|
|
200
|
+
this.persist().catch(() => {});
|
|
201
|
+
}, this.writeTimeout)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return this.walletCache[id];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
public getByAddress(address: string) {
|
|
209
|
+
const { index, change } = this.indexCache[address] || {};
|
|
210
|
+
if (index === undefined || change === undefined) {
|
|
211
|
+
return undefined;
|
|
212
|
+
}
|
|
213
|
+
return this.getByIndex(index, change);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public setStatusAndUtxos(
|
|
217
|
+
address: string,
|
|
218
|
+
status: string | null,
|
|
219
|
+
utxos: Utxo[]
|
|
220
|
+
) {
|
|
221
|
+
const entry = this.getByAddress(address);
|
|
222
|
+
if (!entry) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const { index, change } = this.indexCache[address] || {};
|
|
227
|
+
if (index === undefined || change === undefined) {
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const key = `${this.walletId}-${index}-${change}`;
|
|
232
|
+
this.walletCache[key].status = status;
|
|
233
|
+
this.walletCache[key].utxos = utxos;
|
|
234
|
+
|
|
235
|
+
// batch new data into a single writeout
|
|
236
|
+
this.timeouts.push(
|
|
237
|
+
setTimeout(() => {
|
|
238
|
+
this.persist().catch(() => {});
|
|
239
|
+
}, this.writeTimeout)
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// export const getAddressFromCache = (
|
|
245
|
+
// walletId: string,
|
|
246
|
+
// hdNode: HdPublicNodeValid | HdPrivateNodeValid,
|
|
247
|
+
// networkPrefix: string,
|
|
248
|
+
// addressIndex: number,
|
|
249
|
+
// change: boolean,
|
|
250
|
+
// ): WalletCacheEntry => {
|
|
251
|
+
|
|
252
|
+
// };
|
|
@@ -2,14 +2,11 @@ import { RegTestWallet, Wallet } from "../wallet/Wif";
|
|
|
2
2
|
import { WalletTypeEnum } from "../wallet/enum";
|
|
3
3
|
import { createWallet } from "../wallet/createWallet";
|
|
4
4
|
import { mine } from "../mine";
|
|
5
|
-
import {
|
|
5
|
+
import { encodeCashAddress } from "@bitauth/libauth";
|
|
6
6
|
|
|
7
7
|
test("Should get miner history", async () => {
|
|
8
8
|
const alice = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF!);
|
|
9
|
-
const history = await
|
|
10
|
-
address: alice.getDepositAddress(),
|
|
11
|
-
provider: alice.provider!,
|
|
12
|
-
});
|
|
9
|
+
const history = await alice.getHistory();
|
|
13
10
|
expect(history.length).toBeGreaterThan(0);
|
|
14
11
|
});
|
|
15
12
|
|
|
@@ -61,10 +58,7 @@ test("Should get an address history", async () => {
|
|
|
61
58
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
62
59
|
|
|
63
60
|
// Build Bob's wallet from a public address, check his balance.
|
|
64
|
-
const bobHistory = await
|
|
65
|
-
address: bob.getDepositAddress(),
|
|
66
|
-
provider: bob.provider!,
|
|
67
|
-
});
|
|
61
|
+
const bobHistory = await bob.getHistory();
|
|
68
62
|
expect(bobHistory[0].valueChange).toBe(-2320);
|
|
69
63
|
expect(
|
|
70
64
|
bobHistory[0].outputs.some(
|
|
@@ -141,10 +135,7 @@ test("Should get a history with multi-party sends", async () => {
|
|
|
141
135
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
142
136
|
|
|
143
137
|
// Build Bob's wallet from a public address, check his balance.
|
|
144
|
-
const bobHistory = await
|
|
145
|
-
address: bob.getDepositAddress(),
|
|
146
|
-
provider: bob.provider!,
|
|
147
|
-
});
|
|
138
|
+
const bobHistory = await bob.getHistory();
|
|
148
139
|
|
|
149
140
|
expect(bobHistory[1].fee).toBeGreaterThan(120);
|
|
150
141
|
expect(bobHistory[1].fee).toBe(220);
|
|
@@ -227,9 +218,7 @@ test("Should cut results with a longer history to given count", async () => {
|
|
|
227
218
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
228
219
|
|
|
229
220
|
// Build Bob's wallet from a public address, check his balance.
|
|
230
|
-
const bobHistory = await
|
|
231
|
-
address: bob.getDepositAddress(),
|
|
232
|
-
provider: bob.provider!,
|
|
221
|
+
const bobHistory = await bob.getHistory({
|
|
233
222
|
unit: "sat",
|
|
234
223
|
start: 0,
|
|
235
224
|
count: 2,
|
|
@@ -296,9 +285,7 @@ test("Should handle input and fee from many utxos", async () => {
|
|
|
296
285
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
297
286
|
|
|
298
287
|
// Build Bob's wallet from a public address, check his balance.
|
|
299
|
-
const bobHistory = await
|
|
300
|
-
address: bob.getDepositAddress(),
|
|
301
|
-
provider: bob.provider!,
|
|
288
|
+
const bobHistory = await bob.getHistory({
|
|
302
289
|
unit: "sat",
|
|
303
290
|
});
|
|
304
291
|
|
|
@@ -22,8 +22,40 @@ type Transaction = TransactionCommon & {
|
|
|
22
22
|
hash: string;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export
|
|
26
|
-
|
|
25
|
+
// export type AddressTxI = TxI & {
|
|
26
|
+
// address: string;
|
|
27
|
+
// }
|
|
28
|
+
|
|
29
|
+
// export const getAddressHistory = async ({
|
|
30
|
+
// address,
|
|
31
|
+
// provider,
|
|
32
|
+
// unit = "sat",
|
|
33
|
+
// fromHeight = 0,
|
|
34
|
+
// toHeight = -1,
|
|
35
|
+
// start = 0,
|
|
36
|
+
// count = -1,
|
|
37
|
+
// }: {
|
|
38
|
+
// address: string;
|
|
39
|
+
// provider: NetworkProvider;
|
|
40
|
+
// unit?: UnitEnum;
|
|
41
|
+
// fromHeight?: number;
|
|
42
|
+
// toHeight?: number;
|
|
43
|
+
// start?: number;
|
|
44
|
+
// count?: number;
|
|
45
|
+
// }): Promise<TransactionHistoryItem[]> => {
|
|
46
|
+
// return getHistory({
|
|
47
|
+
// addresses: [address],
|
|
48
|
+
// provider,
|
|
49
|
+
// unit,
|
|
50
|
+
// fromHeight,
|
|
51
|
+
// toHeight,
|
|
52
|
+
// start,
|
|
53
|
+
// count,
|
|
54
|
+
// });
|
|
55
|
+
// }
|
|
56
|
+
|
|
57
|
+
export const getHistory = async ({
|
|
58
|
+
addresses,
|
|
27
59
|
provider,
|
|
28
60
|
unit = "sat",
|
|
29
61
|
fromHeight = 0,
|
|
@@ -31,7 +63,7 @@ export const getAddressHistory = async ({
|
|
|
31
63
|
start = 0,
|
|
32
64
|
count = -1,
|
|
33
65
|
}: {
|
|
34
|
-
|
|
66
|
+
addresses: string[];
|
|
35
67
|
provider: NetworkProvider;
|
|
36
68
|
unit?: UnitEnum;
|
|
37
69
|
fromHeight?: number;
|
|
@@ -39,24 +71,39 @@ export const getAddressHistory = async ({
|
|
|
39
71
|
start?: number;
|
|
40
72
|
count?: number;
|
|
41
73
|
}): Promise<TransactionHistoryItem[]> => {
|
|
74
|
+
if (!addresses.length) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
|
|
42
78
|
if (count === -1) {
|
|
43
79
|
count = 1e10;
|
|
44
80
|
}
|
|
45
81
|
|
|
46
|
-
const history = (
|
|
82
|
+
const history = (
|
|
83
|
+
await Promise.all(
|
|
84
|
+
addresses.map(async (address) =>
|
|
85
|
+
provider.getHistory(address, fromHeight, toHeight)
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
.flat()
|
|
90
|
+
.filter(
|
|
91
|
+
(value, index, array) =>
|
|
92
|
+
array.findIndex((item) => item.tx_hash === value.tx_hash) === index
|
|
93
|
+
)
|
|
47
94
|
.sort((a, b) =>
|
|
48
95
|
a.height <= 0 || b.height <= 0 ? a.height - b.height : b.height - a.height
|
|
49
96
|
)
|
|
50
97
|
.slice(start, start + count);
|
|
51
98
|
|
|
52
99
|
// fill transaction timestamps by requesting headers from network and parsing them
|
|
53
|
-
const
|
|
100
|
+
const uniqueHeights = history
|
|
54
101
|
.map((tx) => tx.height)
|
|
55
102
|
.filter((height) => height > 0)
|
|
56
103
|
.filter((value, index, array) => array.indexOf(value) === index);
|
|
57
104
|
const timestampMap = (
|
|
58
105
|
await Promise.all(
|
|
59
|
-
|
|
106
|
+
uniqueHeights.map(async (height) => [
|
|
60
107
|
height,
|
|
61
108
|
((await provider.getHeader(height, true)) as HeaderI).timestamp,
|
|
62
109
|
])
|
|
@@ -118,10 +165,8 @@ export const getAddressHistory = async ({
|
|
|
118
165
|
{} as { [hash: string]: TransactionCommon }
|
|
119
166
|
);
|
|
120
167
|
|
|
121
|
-
const decoded = decodeCashAddress(
|
|
122
|
-
|
|
123
|
-
throw decoded;
|
|
124
|
-
}
|
|
168
|
+
const decoded = assertSuccess(decodeCashAddress(addresses[0]));
|
|
169
|
+
const prefix = decoded.prefix as CashAddressNetworkPrefix;
|
|
125
170
|
|
|
126
171
|
const addressCache: Record<any, string> = {};
|
|
127
172
|
|
|
@@ -165,7 +210,7 @@ export const getAddressHistory = async ({
|
|
|
165
210
|
address = assertSuccess(
|
|
166
211
|
lockingBytecodeToCashAddress({
|
|
167
212
|
bytecode: prevoutOutput.lockingBytecode,
|
|
168
|
-
prefix:
|
|
213
|
+
prefix: prefix,
|
|
169
214
|
})
|
|
170
215
|
).address;
|
|
171
216
|
addressCache[prevoutOutput.lockingBytecode as any] = address;
|
|
@@ -203,7 +248,7 @@ export const getAddressHistory = async ({
|
|
|
203
248
|
address = assertSuccess(
|
|
204
249
|
lockingBytecodeToCashAddress({
|
|
205
250
|
bytecode: output.lockingBytecode,
|
|
206
|
-
prefix:
|
|
251
|
+
prefix: prefix,
|
|
207
252
|
})
|
|
208
253
|
).address;
|
|
209
254
|
addressCache[output.lockingBytecode as any] = address;
|
|
@@ -253,7 +298,7 @@ export const getAddressHistory = async ({
|
|
|
253
298
|
const nftTokenBalances: Record<string, bigint> = {};
|
|
254
299
|
|
|
255
300
|
tx.inputs.forEach((input) => {
|
|
256
|
-
if (input.address
|
|
301
|
+
if (addresses.includes(input.address)) {
|
|
257
302
|
satoshiBalance -= input.value;
|
|
258
303
|
|
|
259
304
|
if (input.token?.amount) {
|
|
@@ -269,7 +314,7 @@ export const getAddressHistory = async ({
|
|
|
269
314
|
}
|
|
270
315
|
});
|
|
271
316
|
tx.outputs.forEach((output) => {
|
|
272
|
-
if (output.address
|
|
317
|
+
if (addresses.includes(output.address)) {
|
|
273
318
|
satoshiBalance += Number(output.value);
|
|
274
319
|
|
|
275
320
|
if (output.token?.amount) {
|
|
@@ -319,7 +364,10 @@ export const getAddressHistory = async ({
|
|
|
319
364
|
);
|
|
320
365
|
|
|
321
366
|
// backfill the balances
|
|
322
|
-
let prevBalance =
|
|
367
|
+
let prevBalance = (
|
|
368
|
+
await Promise.all(addresses.map((address) => provider.getBalance(address)))
|
|
369
|
+
).reduce((a, b) => a + b, 0);
|
|
370
|
+
|
|
323
371
|
let prevValueChange = 0;
|
|
324
372
|
historyItems.forEach((tx) => {
|
|
325
373
|
tx.balance = prevBalance - prevValueChange;
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,9 @@ export * from "./network/index.js";
|
|
|
7
7
|
export { SignedMessage } from "./message/signed.js";
|
|
8
8
|
|
|
9
9
|
export * from "./wallet/Base.js";
|
|
10
|
+
export * from "./wallet/Watch.js";
|
|
10
11
|
export * from "./wallet/Wif.js";
|
|
12
|
+
export * from "./wallet/HDWallet.js";
|
|
11
13
|
export * from "./wallet/createWallet.js";
|
|
12
14
|
|
|
13
15
|
// provider
|
|
@@ -27,7 +29,7 @@ export * from "./wallet/model.js";
|
|
|
27
29
|
import * as Mainnet from "./util/index.js";
|
|
28
30
|
export { Mainnet };
|
|
29
31
|
export * from "./util/index.js";
|
|
30
|
-
export {
|
|
32
|
+
export { getHistory } from "./history/getHistory.js";
|
|
31
33
|
|
|
32
34
|
// libauth
|
|
33
35
|
export * as libauth from "./libauth.js";
|
package/src/interface.ts
CHANGED
|
@@ -15,13 +15,20 @@ export const Network = {
|
|
|
15
15
|
};
|
|
16
16
|
export type Network = typeof Network[keyof typeof Network];
|
|
17
17
|
|
|
18
|
-
export interface
|
|
18
|
+
export interface Utxo {
|
|
19
19
|
txid: string;
|
|
20
20
|
vout: number;
|
|
21
21
|
satoshis: number;
|
|
22
22
|
height?: number;
|
|
23
23
|
coinbase?: boolean;
|
|
24
24
|
token?: TokenI;
|
|
25
|
+
address: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UtxoId {
|
|
29
|
+
txid: string;
|
|
30
|
+
vout: number;
|
|
31
|
+
satoshis: number;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
export interface ElectrumBalanceI {
|
package/src/message/interface.ts
CHANGED
|
@@ -1,37 +1,11 @@
|
|
|
1
|
-
// interface EncryptedMessageFunc {
|
|
2
|
-
// (message: string, privateKey: string): string;
|
|
3
|
-
// }
|
|
4
|
-
|
|
5
|
-
// interface DecryptedMessageFunc {
|
|
6
|
-
// (message: string, publicKeyHash: string): string;
|
|
7
|
-
// }
|
|
8
|
-
|
|
9
|
-
// export interface EncryptedMessageI{
|
|
10
|
-
// encrypt: EncryptedMessageFunc
|
|
11
|
-
// decrypt: DecryptedMessageFunc
|
|
12
|
-
// }
|
|
13
|
-
|
|
14
|
-
// interface SignMessageFunc {
|
|
15
|
-
// sign(message: string, privateKey: Uint8Array): Promise<string>
|
|
16
|
-
// }
|
|
17
|
-
|
|
18
|
-
// interface VerifyMessageFunc {
|
|
19
|
-
// verify(message: string,
|
|
20
|
-
// signature: string,
|
|
21
|
-
// cashaddr: string): Promise<boolean>;
|
|
22
|
-
// }
|
|
23
|
-
|
|
24
1
|
export interface SignedMessageI {
|
|
25
|
-
sign(
|
|
26
|
-
message: string,
|
|
27
|
-
privateKey: Uint8Array
|
|
28
|
-
): Promise<SignedMessageResponseI>;
|
|
2
|
+
sign(message: string, privateKey: Uint8Array): SignedMessageResponseI;
|
|
29
3
|
verify(
|
|
30
4
|
message: string,
|
|
31
5
|
signature: string,
|
|
32
6
|
cashaddr: string,
|
|
33
7
|
publicKey?: Uint8Array
|
|
34
|
-
):
|
|
8
|
+
): VerifyMessageResponseI;
|
|
35
9
|
}
|
|
36
10
|
|
|
37
11
|
export interface SignedMessageRawI {
|