mainnet-js 2.7.34 → 3.0.0-next.1
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.34.js → mainnet-3.0.0-next.1.js} +728 -708
- 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 +45 -0
- package/dist/module/cache/walletCache.d.ts.map +1 -0
- package/dist/module/cache/walletCache.js +140 -0
- package/dist/module/cache/walletCache.js.map +1 -0
- package/dist/module/chain.d.ts +1 -1
- package/dist/module/chain.js +1 -1
- package/dist/module/chain.js.map +1 -1
- package/dist/module/constant.d.ts +1 -1
- package/dist/module/constant.d.ts.map +1 -1
- package/dist/module/constant.js +1 -1
- package/dist/module/constant.js.map +1 -1
- package/dist/module/enum.d.ts +1 -7
- package/dist/module/enum.d.ts.map +1 -1
- package/dist/module/enum.js +0 -6
- package/dist/module/enum.js.map +1 -1
- 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} +17 -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 -2
- 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 +8 -8
- 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 +3 -2
- 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/network/getRelayFeeCache.js +2 -2
- package/dist/module/network/getRelayFeeCache.js.map +1 -1
- package/dist/module/rate/ExchangeRate.d.ts +2 -1
- package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
- package/dist/module/rate/ExchangeRate.js +4 -1
- package/dist/module/rate/ExchangeRate.js.map +1 -1
- package/dist/module/transaction/Wif.d.ts +25 -23
- package/dist/module/transaction/Wif.d.ts.map +1 -1
- package/dist/module/transaction/Wif.js +26 -25
- package/dist/module/transaction/Wif.js.map +1 -1
- package/dist/module/transaction/allocateFee.d.ts +3 -3
- package/dist/module/transaction/allocateFee.d.ts.map +1 -1
- package/dist/module/transaction/allocateFee.js +5 -6
- package/dist/module/transaction/allocateFee.js.map +1 -1
- package/dist/module/util/amountInSatoshi.d.ts +1 -1
- package/dist/module/util/amountInSatoshi.d.ts.map +1 -1
- package/dist/module/util/amountInSatoshi.js +3 -9
- package/dist/module/util/amountInSatoshi.js.map +1 -1
- package/dist/module/util/asSendRequestObject.d.ts.map +1 -1
- package/dist/module/util/asSendRequestObject.js +10 -7
- package/dist/module/util/asSendRequestObject.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/convert.d.ts +3 -0
- package/dist/module/util/convert.d.ts.map +1 -1
- package/dist/module/util/convert.js +12 -0
- package/dist/module/util/convert.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 +3 -3
- package/dist/module/util/index.d.ts.map +1 -1
- package/dist/module/util/index.js +3 -3
- package/dist/module/util/index.js.map +1 -1
- package/dist/module/util/satoshiToAmount.d.ts +1 -1
- package/dist/module/util/satoshiToAmount.d.ts.map +1 -1
- package/dist/module/util/satoshiToAmount.js +3 -9
- package/dist/module/util/satoshiToAmount.js.map +1 -1
- package/dist/module/util/sumSendRequestAmounts.d.ts.map +1 -1
- package/dist/module/util/sumSendRequestAmounts.js +3 -4
- package/dist/module/util/sumSendRequestAmounts.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 +2 -2
- package/dist/module/util/sumUtxoValue.js.map +1 -1
- package/dist/module/wallet/Base.d.ts +45 -103
- package/dist/module/wallet/Base.d.ts.map +1 -1
- package/dist/module/wallet/Base.js +99 -298
- 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/Util.js +1 -1
- package/dist/module/wallet/Util.js.map +1 -1
- 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 +5 -6
- package/dist/module/wallet/interface.d.ts.map +1 -1
- package/dist/module/wallet/model.d.ts +15 -19
- package/dist/module/wallet/model.d.ts.map +1 -1
- package/dist/module/wallet/model.js +5 -25
- 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 +239 -0
- package/src/chain.ts +1 -1
- package/src/constant.ts +1 -1
- package/src/enum.ts +0 -6
- package/src/history/{electrumTransformer.test.ts → getHistory.test.ts} +26 -53
- package/src/history/{electrumTransformer.ts → getHistory.ts} +31 -15
- package/src/index.ts +3 -1
- package/src/interface.ts +8 -2
- package/src/message/interface.ts +2 -28
- package/src/message/signed.test.ts +36 -48
- package/src/message/signed.ts +9 -12
- package/src/network/Connection.test.ts +3 -3
- package/src/network/ElectrumNetworkProvider.ts +5 -5
- package/src/network/NetworkProvider.ts +2 -2
- package/src/network/Rpc.test.ts +3 -4
- package/src/network/constant.ts +4 -4
- package/src/network/getRelayFeeCache.ts +2 -2
- package/src/rate/ExchangeRate.test.ts +2 -44
- package/src/rate/ExchangeRate.ts +5 -2
- package/src/transaction/Wif.ts +59 -52
- package/src/transaction/allocateFee.test.ts +110 -131
- package/src/transaction/allocateFee.ts +14 -15
- package/src/util/amountInSatoshi.test.ts +1 -9
- package/src/util/amountInSatoshi.ts +6 -10
- package/src/util/asSendRequestObject.ts +12 -7
- package/src/util/checkUtxos.ts +21 -26
- package/src/util/convert.ts +18 -0
- 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 +3 -7
- package/src/util/satoshiToAmount.test.ts +1 -1
- package/src/util/satoshiToAmount.ts +4 -10
- package/src/util/sumSendRequestAmounts.ts +3 -4
- package/src/util/sumUtxoValue.ts +7 -7
- package/src/wallet/Base.ts +147 -420
- package/src/wallet/Cashtokens.test.headless.js +11 -11
- package/src/wallet/Cashtokens.test.ts +36 -37
- package/src/wallet/HDWallet.test.ts +515 -0
- package/src/wallet/HDWallet.ts +764 -0
- package/src/wallet/Util.ts +1 -1
- package/src/wallet/Watch.ts +447 -0
- package/src/wallet/Wif.bip39.test.ts +1 -1
- package/src/wallet/Wif.test.ts +108 -133
- package/src/wallet/Wif.ts +258 -283
- package/src/wallet/createWallet.ts +28 -18
- package/src/wallet/interface.ts +5 -6
- package/src/wallet/model.test.ts +4 -7
- package/src/wallet/model.ts +19 -51
- package/dist/module/history/electrumTransformer.d.ts.map +0 -1
- package/dist/module/history/electrumTransformer.js.map +0 -1
- package/dist/module/util/balanceObjectFromSatoshi.d.ts +0 -8
- package/dist/module/util/balanceObjectFromSatoshi.d.ts.map +0 -1
- package/dist/module/util/balanceObjectFromSatoshi.js +0 -35
- package/dist/module/util/balanceObjectFromSatoshi.js.map +0 -1
- package/src/util/balanceObjectFromSatoshi.test.ts +0 -58
- package/src/util/balanceObjectFromSatoshi.ts +0 -52
|
@@ -0,0 +1,239 @@
|
|
|
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 stringify = (_: any) =>
|
|
20
|
+
JSON.stringify(_, (_, value) =>
|
|
21
|
+
typeof value === "bigint" ? value.toString() + "n" : value
|
|
22
|
+
);
|
|
23
|
+
export const parse = (data: string) =>
|
|
24
|
+
JSON.parse(data, (_, value) => {
|
|
25
|
+
if (typeof value === "string" && /^\d+n$/.test(value)) {
|
|
26
|
+
return BigInt(value.slice(0, -1));
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export interface WalletCacheEntry {
|
|
32
|
+
address: string;
|
|
33
|
+
tokenAddress: string;
|
|
34
|
+
privateKey: Uint8Array | undefined;
|
|
35
|
+
publicKey: Uint8Array;
|
|
36
|
+
publicKeyHash: Uint8Array;
|
|
37
|
+
index: number;
|
|
38
|
+
change: boolean;
|
|
39
|
+
status: string | null;
|
|
40
|
+
utxos: Utxo[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Minimal interface for use in transaction signing
|
|
44
|
+
export interface WalletCache {
|
|
45
|
+
get(address: string): { privateKey: Uint8Array | undefined } | undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Full interface for wallet cache management
|
|
49
|
+
export interface WalletCacheI extends WalletCache {
|
|
50
|
+
init(): Promise<void>;
|
|
51
|
+
persist(): Promise<void>;
|
|
52
|
+
get(address: string): WalletCacheEntry | undefined;
|
|
53
|
+
getByIndex(addressIndex: number, change: boolean): WalletCacheEntry;
|
|
54
|
+
setStatusAndUtxos(
|
|
55
|
+
address: string,
|
|
56
|
+
status: string | null,
|
|
57
|
+
utxos: Utxo[]
|
|
58
|
+
): void;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class WalletCache implements WalletCacheI {
|
|
62
|
+
private _storage: CacheProvider | undefined;
|
|
63
|
+
private walletCache: Record<string, WalletCacheEntry> = {};
|
|
64
|
+
private indexCache: Record<
|
|
65
|
+
string,
|
|
66
|
+
{
|
|
67
|
+
index: number;
|
|
68
|
+
change: boolean;
|
|
69
|
+
}
|
|
70
|
+
> = {};
|
|
71
|
+
private timeouts: NodeJS.Timeout[] = [];
|
|
72
|
+
|
|
73
|
+
get storage(): CacheProvider | undefined {
|
|
74
|
+
if (
|
|
75
|
+
!Config.UseMemoryCache &&
|
|
76
|
+
!Config.UseLocalStorageCache &&
|
|
77
|
+
!Config.UseIndexedDBCache
|
|
78
|
+
) {
|
|
79
|
+
this._storage = undefined;
|
|
80
|
+
return this._storage;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (Config.UseMemoryCache && !(this._storage instanceof MemoryCache)) {
|
|
84
|
+
this._storage = new MemoryCache();
|
|
85
|
+
return this._storage;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
Config.UseLocalStorageCache &&
|
|
90
|
+
!(this._storage instanceof WebStorageCache)
|
|
91
|
+
) {
|
|
92
|
+
this._storage = new WebStorageCache();
|
|
93
|
+
return this._storage;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (
|
|
97
|
+
Config.UseIndexedDBCache &&
|
|
98
|
+
!(this._storage instanceof IndexedDbCache)
|
|
99
|
+
) {
|
|
100
|
+
this._storage = new IndexedDbCache();
|
|
101
|
+
return this._storage;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return this._storage;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
constructor(
|
|
108
|
+
public walletId: string,
|
|
109
|
+
public hdNode: HdPublicNodeValid | HdPrivateNodeValid,
|
|
110
|
+
public networkPrefix: string,
|
|
111
|
+
public writeTimeout: number = 2000
|
|
112
|
+
) {
|
|
113
|
+
if (!this.hdNode) {
|
|
114
|
+
throw new Error("HDNode is undefined");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public async init() {
|
|
119
|
+
await this.storage?.init();
|
|
120
|
+
const data = await this.storage?.getItem(`walletCache-${this.walletId}`);
|
|
121
|
+
if (data) {
|
|
122
|
+
try {
|
|
123
|
+
const parsed = parse(data);
|
|
124
|
+
this.walletCache = parsed.walletCache || {};
|
|
125
|
+
this.indexCache = parsed.indexCache || {};
|
|
126
|
+
} catch (e) {
|
|
127
|
+
// ignore
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public async persist() {
|
|
133
|
+
this.timeouts.map(clearTimeout);
|
|
134
|
+
this.timeouts = [];
|
|
135
|
+
|
|
136
|
+
this.storage?.setItem(
|
|
137
|
+
`walletCache-${this.walletId}`,
|
|
138
|
+
stringify({
|
|
139
|
+
walletCache: this.walletCache,
|
|
140
|
+
indexCache: this.indexCache,
|
|
141
|
+
})
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public getByIndex(addressIndex: number, change: boolean) {
|
|
146
|
+
const id = `${this.walletId}-${addressIndex}-${change}`;
|
|
147
|
+
if (!this.walletCache[id]) {
|
|
148
|
+
const node = deriveHdPathRelative(
|
|
149
|
+
this.hdNode,
|
|
150
|
+
`${change ? 1 : 0}/${addressIndex}`
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
const privateKey = "privateKey" in node ? node.privateKey : undefined;
|
|
154
|
+
const publicKey =
|
|
155
|
+
"publicKey" in node
|
|
156
|
+
? node.publicKey
|
|
157
|
+
: assertSuccess(secp256k1.derivePublicKeyUncompressed(privateKey!));
|
|
158
|
+
const publicKeyCompressed = assertSuccess(
|
|
159
|
+
secp256k1.compressPublicKey(publicKey)
|
|
160
|
+
);
|
|
161
|
+
const publicKeyHash = hash160(publicKeyCompressed);
|
|
162
|
+
|
|
163
|
+
const address = encodeCashAddress({
|
|
164
|
+
throwErrors: true,
|
|
165
|
+
prefix: this.networkPrefix as CashAddressNetworkPrefix,
|
|
166
|
+
type: CashAddressType.p2pkh,
|
|
167
|
+
payload: publicKeyHash,
|
|
168
|
+
}).address;
|
|
169
|
+
|
|
170
|
+
const tokenAddress = encodeCashAddress({
|
|
171
|
+
throwErrors: true,
|
|
172
|
+
prefix: this.networkPrefix as CashAddressNetworkPrefix,
|
|
173
|
+
type: CashAddressType.p2pkhWithTokens,
|
|
174
|
+
payload: publicKeyHash,
|
|
175
|
+
}).address;
|
|
176
|
+
|
|
177
|
+
this.walletCache[id] = {
|
|
178
|
+
address,
|
|
179
|
+
tokenAddress,
|
|
180
|
+
privateKey: privateKey,
|
|
181
|
+
publicKey,
|
|
182
|
+
publicKeyHash,
|
|
183
|
+
index: addressIndex,
|
|
184
|
+
change,
|
|
185
|
+
status: null,
|
|
186
|
+
utxos: [],
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
this.indexCache[address] = {
|
|
190
|
+
index: addressIndex,
|
|
191
|
+
change,
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// batch new data into a single writeout
|
|
195
|
+
this.timeouts.push(
|
|
196
|
+
setTimeout(() => {
|
|
197
|
+
this.persist().catch(() => {});
|
|
198
|
+
}, this.writeTimeout)
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return this.walletCache[id];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
public get(address: string) {
|
|
206
|
+
const { index, change } = this.indexCache[address] || {};
|
|
207
|
+
if (index === undefined || change === undefined) {
|
|
208
|
+
return undefined;
|
|
209
|
+
}
|
|
210
|
+
return this.getByIndex(index, change);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public setStatusAndUtxos(
|
|
214
|
+
address: string,
|
|
215
|
+
status: string | null,
|
|
216
|
+
utxos: Utxo[]
|
|
217
|
+
) {
|
|
218
|
+
const entry = this.get(address);
|
|
219
|
+
if (!entry) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const { index, change } = this.indexCache[address] || {};
|
|
224
|
+
if (index === undefined || change === undefined) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const key = `${this.walletId}-${index}-${change}`;
|
|
229
|
+
this.walletCache[key].status = status;
|
|
230
|
+
this.walletCache[key].utxos = utxos;
|
|
231
|
+
|
|
232
|
+
// batch new data into a single writeout
|
|
233
|
+
this.timeouts.push(
|
|
234
|
+
setTimeout(() => {
|
|
235
|
+
this.persist().catch(() => {});
|
|
236
|
+
}, this.writeTimeout)
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
package/src/chain.ts
CHANGED
package/src/constant.ts
CHANGED
package/src/enum.ts
CHANGED
|
@@ -10,7 +10,6 @@ export enum NetworkEnum {
|
|
|
10
10
|
Mainnet = <any>"mainnet",
|
|
11
11
|
Testnet = <any>"testnet",
|
|
12
12
|
Regtest = <any>"regtest",
|
|
13
|
-
Simtest = <any>"simtest",
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
export const networkPrefixMap = {
|
|
@@ -30,11 +29,6 @@ const literal = <L extends string>(l: L): L => l;
|
|
|
30
29
|
export const UnitEnum = {
|
|
31
30
|
BCH: literal("bch"),
|
|
32
31
|
USD: literal("usd"),
|
|
33
|
-
BIT: literal("bit"),
|
|
34
|
-
BITS: literal("bits"),
|
|
35
32
|
SAT: literal("sat"),
|
|
36
|
-
SATS: literal("sats"),
|
|
37
|
-
SATOSHI: literal("satoshi"),
|
|
38
|
-
SATOSHIS: literal("satoshis"),
|
|
39
33
|
};
|
|
40
34
|
export type UnitEnum = typeof UnitEnum[keyof typeof UnitEnum];
|
|
@@ -2,14 +2,12 @@ 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
|
+
import { toBch } from "../util";
|
|
6
7
|
|
|
7
8
|
test("Should get miner history", async () => {
|
|
8
9
|
const alice = await RegTestWallet.fromWIF(process.env.PRIVATE_WIF!);
|
|
9
|
-
const history = await
|
|
10
|
-
address: alice.getDepositAddress(),
|
|
11
|
-
provider: alice.provider!,
|
|
12
|
-
});
|
|
10
|
+
const history = await alice.getHistory();
|
|
13
11
|
expect(history.length).toBeGreaterThan(0);
|
|
14
12
|
});
|
|
15
13
|
|
|
@@ -31,40 +29,33 @@ test("Should get an address history", async () => {
|
|
|
31
29
|
let sendResponse = await alice.send([
|
|
32
30
|
{
|
|
33
31
|
cashaddr: bob.cashaddr!,
|
|
34
|
-
value:
|
|
35
|
-
unit: "satoshis",
|
|
32
|
+
value: 31000n,
|
|
36
33
|
},
|
|
37
34
|
{
|
|
38
35
|
cashaddr: charlie.cashaddr!,
|
|
39
|
-
value:
|
|
40
|
-
unit: "satoshis",
|
|
36
|
+
value: 41000n,
|
|
41
37
|
},
|
|
42
38
|
]);
|
|
43
39
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
44
40
|
await bob.send([
|
|
45
41
|
{
|
|
46
42
|
cashaddr: charlie.cashaddr!,
|
|
47
|
-
value:
|
|
48
|
-
unit: "satoshis",
|
|
43
|
+
value: 2100n,
|
|
49
44
|
},
|
|
50
45
|
]);
|
|
51
46
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
52
47
|
await bob.send([
|
|
53
48
|
{
|
|
54
49
|
cashaddr: alice.cashaddr!,
|
|
55
|
-
value:
|
|
56
|
-
unit: "satoshis",
|
|
50
|
+
value: 2100n,
|
|
57
51
|
},
|
|
58
52
|
]);
|
|
59
53
|
expect(sendResponse!.txId!.length).toBe(64);
|
|
60
|
-
expect(sendResponse.balance
|
|
54
|
+
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
61
55
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
62
56
|
|
|
63
57
|
// Build Bob's wallet from a public address, check his balance.
|
|
64
|
-
const bobHistory = await
|
|
65
|
-
address: bob.getDepositAddress(),
|
|
66
|
-
provider: bob.provider!,
|
|
67
|
-
});
|
|
58
|
+
const bobHistory = await bob.getHistory();
|
|
68
59
|
expect(bobHistory[0].valueChange).toBe(-2320);
|
|
69
60
|
expect(
|
|
70
61
|
bobHistory[0].outputs.some(
|
|
@@ -116,35 +107,29 @@ test("Should get a history with multi-party sends", async () => {
|
|
|
116
107
|
let sendResponse = await alice.send([
|
|
117
108
|
{
|
|
118
109
|
cashaddr: bob.cashaddr!,
|
|
119
|
-
value:
|
|
120
|
-
unit: "satoshis",
|
|
110
|
+
value: 31000n,
|
|
121
111
|
},
|
|
122
112
|
]);
|
|
123
113
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
124
114
|
await bob.send([
|
|
125
115
|
{
|
|
126
116
|
cashaddr: charlie.cashaddr!,
|
|
127
|
-
value:
|
|
128
|
-
unit: "satoshis",
|
|
117
|
+
value: 2100n,
|
|
129
118
|
},
|
|
130
119
|
]);
|
|
131
120
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
132
121
|
await bob.send([
|
|
133
122
|
{
|
|
134
123
|
cashaddr: alice.cashaddr!,
|
|
135
|
-
value:
|
|
136
|
-
unit: "satoshis",
|
|
124
|
+
value: 2100n,
|
|
137
125
|
},
|
|
138
126
|
]);
|
|
139
127
|
expect(sendResponse!.txId!.length).toBe(64);
|
|
140
|
-
expect(sendResponse.balance
|
|
128
|
+
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
141
129
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
142
130
|
|
|
143
131
|
// Build Bob's wallet from a public address, check his balance.
|
|
144
|
-
const bobHistory = await
|
|
145
|
-
address: bob.getDepositAddress(),
|
|
146
|
-
provider: bob.provider!,
|
|
147
|
-
});
|
|
132
|
+
const bobHistory = await bob.getHistory();
|
|
148
133
|
|
|
149
134
|
expect(bobHistory[1].fee).toBeGreaterThan(120);
|
|
150
135
|
expect(bobHistory[1].fee).toBe(220);
|
|
@@ -199,37 +184,31 @@ test("Should cut results with a longer history to given count", async () => {
|
|
|
199
184
|
let sendResponse = await alice.send([
|
|
200
185
|
{
|
|
201
186
|
cashaddr: bob.cashaddr!,
|
|
202
|
-
value:
|
|
203
|
-
unit: "satoshis",
|
|
187
|
+
value: 31000n,
|
|
204
188
|
},
|
|
205
189
|
]);
|
|
206
190
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
207
191
|
await bob.send([
|
|
208
192
|
{
|
|
209
193
|
cashaddr: charlie.cashaddr!,
|
|
210
|
-
value:
|
|
211
|
-
unit: "satoshis",
|
|
194
|
+
value: 2100n,
|
|
212
195
|
},
|
|
213
196
|
{
|
|
214
197
|
cashaddr: alice.cashaddr!,
|
|
215
|
-
value:
|
|
216
|
-
unit: "satoshis",
|
|
198
|
+
value: 2100n,
|
|
217
199
|
},
|
|
218
200
|
{
|
|
219
201
|
cashaddr: alice.cashaddr!,
|
|
220
|
-
value:
|
|
221
|
-
unit: "satoshis",
|
|
202
|
+
value: 2100n,
|
|
222
203
|
},
|
|
223
204
|
]);
|
|
224
205
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
225
206
|
expect(sendResponse!.txId!.length).toBe(64);
|
|
226
|
-
expect(sendResponse.balance
|
|
207
|
+
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
227
208
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
228
209
|
|
|
229
210
|
// Build Bob's wallet from a public address, check his balance.
|
|
230
|
-
const bobHistory = await
|
|
231
|
-
address: bob.getDepositAddress(),
|
|
232
|
-
provider: bob.provider!,
|
|
211
|
+
const bobHistory = await bob.getHistory({
|
|
233
212
|
unit: "sat",
|
|
234
213
|
start: 0,
|
|
235
214
|
count: 2,
|
|
@@ -269,36 +248,30 @@ test("Should handle input and fee from many utxos", async () => {
|
|
|
269
248
|
let sendResponse = await alice.send([
|
|
270
249
|
{
|
|
271
250
|
cashaddr: bob.cashaddr!,
|
|
272
|
-
value:
|
|
273
|
-
unit: "satoshis",
|
|
251
|
+
value: 600n,
|
|
274
252
|
},
|
|
275
253
|
{
|
|
276
254
|
cashaddr: bob.cashaddr!,
|
|
277
|
-
value:
|
|
278
|
-
unit: "satoshis",
|
|
255
|
+
value: 600n,
|
|
279
256
|
},
|
|
280
257
|
{
|
|
281
258
|
cashaddr: bob.cashaddr!,
|
|
282
|
-
value:
|
|
283
|
-
unit: "satoshis",
|
|
259
|
+
value: 600n,
|
|
284
260
|
},
|
|
285
261
|
{
|
|
286
262
|
cashaddr: bob.cashaddr!,
|
|
287
|
-
value:
|
|
288
|
-
unit: "satoshis",
|
|
263
|
+
value: 600n,
|
|
289
264
|
},
|
|
290
265
|
]);
|
|
291
266
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
292
267
|
await bob.sendMax(charlie.cashaddr!);
|
|
293
268
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 1 });
|
|
294
269
|
expect(sendResponse!.txId!.length).toBe(64);
|
|
295
|
-
expect(sendResponse.balance
|
|
270
|
+
expect(toBch(sendResponse.balance!)).toBeGreaterThan(0.01);
|
|
296
271
|
await mine({ cashaddr: alice.getDepositAddress(), blocks: 10 });
|
|
297
272
|
|
|
298
273
|
// Build Bob's wallet from a public address, check his balance.
|
|
299
|
-
const bobHistory = await
|
|
300
|
-
address: bob.getDepositAddress(),
|
|
301
|
-
provider: bob.provider!,
|
|
274
|
+
const bobHistory = await bob.getHistory({
|
|
302
275
|
unit: "sat",
|
|
303
276
|
});
|
|
304
277
|
|
|
@@ -22,8 +22,8 @@ type Transaction = TransactionCommon & {
|
|
|
22
22
|
hash: string;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export const
|
|
26
|
-
|
|
25
|
+
export const getHistory = async ({
|
|
26
|
+
addresses,
|
|
27
27
|
provider,
|
|
28
28
|
unit = "sat",
|
|
29
29
|
fromHeight = 0,
|
|
@@ -31,7 +31,7 @@ export const getAddressHistory = async ({
|
|
|
31
31
|
start = 0,
|
|
32
32
|
count = -1,
|
|
33
33
|
}: {
|
|
34
|
-
|
|
34
|
+
addresses: string[];
|
|
35
35
|
provider: NetworkProvider;
|
|
36
36
|
unit?: UnitEnum;
|
|
37
37
|
fromHeight?: number;
|
|
@@ -39,24 +39,39 @@ export const getAddressHistory = async ({
|
|
|
39
39
|
start?: number;
|
|
40
40
|
count?: number;
|
|
41
41
|
}): Promise<TransactionHistoryItem[]> => {
|
|
42
|
+
if (!addresses.length) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
|
|
42
46
|
if (count === -1) {
|
|
43
47
|
count = 1e10;
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
const history = (
|
|
50
|
+
const history = (
|
|
51
|
+
await Promise.all(
|
|
52
|
+
addresses.map(async (address) =>
|
|
53
|
+
provider.getHistory(address, fromHeight, toHeight)
|
|
54
|
+
)
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
.flat()
|
|
58
|
+
.filter(
|
|
59
|
+
(value, index, array) =>
|
|
60
|
+
array.findIndex((item) => item.tx_hash === value.tx_hash) === index
|
|
61
|
+
)
|
|
47
62
|
.sort((a, b) =>
|
|
48
63
|
a.height <= 0 || b.height <= 0 ? a.height - b.height : b.height - a.height
|
|
49
64
|
)
|
|
50
65
|
.slice(start, start + count);
|
|
51
66
|
|
|
52
67
|
// fill transaction timestamps by requesting headers from network and parsing them
|
|
53
|
-
const
|
|
68
|
+
const uniqueHeights = history
|
|
54
69
|
.map((tx) => tx.height)
|
|
55
70
|
.filter((height) => height > 0)
|
|
56
71
|
.filter((value, index, array) => array.indexOf(value) === index);
|
|
57
72
|
const timestampMap = (
|
|
58
73
|
await Promise.all(
|
|
59
|
-
|
|
74
|
+
uniqueHeights.map(async (height) => [
|
|
60
75
|
height,
|
|
61
76
|
((await provider.getHeader(height, true)) as HeaderI).timestamp,
|
|
62
77
|
])
|
|
@@ -118,10 +133,8 @@ export const getAddressHistory = async ({
|
|
|
118
133
|
{} as { [hash: string]: TransactionCommon }
|
|
119
134
|
);
|
|
120
135
|
|
|
121
|
-
const decoded = decodeCashAddress(
|
|
122
|
-
|
|
123
|
-
throw decoded;
|
|
124
|
-
}
|
|
136
|
+
const decoded = assertSuccess(decodeCashAddress(addresses[0]));
|
|
137
|
+
const prefix = decoded.prefix as CashAddressNetworkPrefix;
|
|
125
138
|
|
|
126
139
|
const addressCache: Record<any, string> = {};
|
|
127
140
|
|
|
@@ -165,7 +178,7 @@ export const getAddressHistory = async ({
|
|
|
165
178
|
address = assertSuccess(
|
|
166
179
|
lockingBytecodeToCashAddress({
|
|
167
180
|
bytecode: prevoutOutput.lockingBytecode,
|
|
168
|
-
prefix:
|
|
181
|
+
prefix: prefix,
|
|
169
182
|
})
|
|
170
183
|
).address;
|
|
171
184
|
addressCache[prevoutOutput.lockingBytecode as any] = address;
|
|
@@ -203,7 +216,7 @@ export const getAddressHistory = async ({
|
|
|
203
216
|
address = assertSuccess(
|
|
204
217
|
lockingBytecodeToCashAddress({
|
|
205
218
|
bytecode: output.lockingBytecode,
|
|
206
|
-
prefix:
|
|
219
|
+
prefix: prefix,
|
|
207
220
|
})
|
|
208
221
|
).address;
|
|
209
222
|
addressCache[output.lockingBytecode as any] = address;
|
|
@@ -253,7 +266,7 @@ export const getAddressHistory = async ({
|
|
|
253
266
|
const nftTokenBalances: Record<string, bigint> = {};
|
|
254
267
|
|
|
255
268
|
tx.inputs.forEach((input) => {
|
|
256
|
-
if (input.address
|
|
269
|
+
if (addresses.includes(input.address)) {
|
|
257
270
|
satoshiBalance -= input.value;
|
|
258
271
|
|
|
259
272
|
if (input.token?.amount) {
|
|
@@ -269,7 +282,7 @@ export const getAddressHistory = async ({
|
|
|
269
282
|
}
|
|
270
283
|
});
|
|
271
284
|
tx.outputs.forEach((output) => {
|
|
272
|
-
if (output.address
|
|
285
|
+
if (addresses.includes(output.address)) {
|
|
273
286
|
satoshiBalance += Number(output.value);
|
|
274
287
|
|
|
275
288
|
if (output.token?.amount) {
|
|
@@ -319,7 +332,10 @@ export const getAddressHistory = async ({
|
|
|
319
332
|
);
|
|
320
333
|
|
|
321
334
|
// backfill the balances
|
|
322
|
-
let prevBalance =
|
|
335
|
+
let prevBalance = (
|
|
336
|
+
await Promise.all(addresses.map((address) => provider.getBalance(address)))
|
|
337
|
+
).reduce((a, b) => a + b, 0);
|
|
338
|
+
|
|
323
339
|
let prevValueChange = 0;
|
|
324
340
|
historyItems.forEach((tx) => {
|
|
325
341
|
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,19 @@ 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
|
-
satoshis:
|
|
21
|
+
satoshis: bigint;
|
|
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;
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
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 {
|