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.
Files changed (195) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/{mainnet-2.7.34.js → mainnet-3.0.0-next.1.js} +728 -708
  3. package/dist/module/cache/MemoryCache.d.ts +0 -1
  4. package/dist/module/cache/MemoryCache.d.ts.map +1 -1
  5. package/dist/module/cache/MemoryCache.js +5 -7
  6. package/dist/module/cache/MemoryCache.js.map +1 -1
  7. package/dist/module/cache/index.d.ts +1 -0
  8. package/dist/module/cache/index.d.ts.map +1 -1
  9. package/dist/module/cache/index.js +1 -0
  10. package/dist/module/cache/index.js.map +1 -1
  11. package/dist/module/cache/walletCache.d.ts +45 -0
  12. package/dist/module/cache/walletCache.d.ts.map +1 -0
  13. package/dist/module/cache/walletCache.js +140 -0
  14. package/dist/module/cache/walletCache.js.map +1 -0
  15. package/dist/module/chain.d.ts +1 -1
  16. package/dist/module/chain.js +1 -1
  17. package/dist/module/chain.js.map +1 -1
  18. package/dist/module/constant.d.ts +1 -1
  19. package/dist/module/constant.d.ts.map +1 -1
  20. package/dist/module/constant.js +1 -1
  21. package/dist/module/constant.js.map +1 -1
  22. package/dist/module/enum.d.ts +1 -7
  23. package/dist/module/enum.d.ts.map +1 -1
  24. package/dist/module/enum.js +0 -6
  25. package/dist/module/enum.js.map +1 -1
  26. package/dist/module/history/{electrumTransformer.d.ts → getHistory.d.ts} +3 -3
  27. package/dist/module/history/getHistory.d.ts.map +1 -0
  28. package/dist/module/history/{electrumTransformer.js → getHistory.js} +17 -14
  29. package/dist/module/history/getHistory.js.map +1 -0
  30. package/dist/module/index.d.ts +3 -1
  31. package/dist/module/index.d.ts.map +1 -1
  32. package/dist/module/index.js +3 -1
  33. package/dist/module/index.js.map +1 -1
  34. package/dist/module/interface.d.ts +7 -2
  35. package/dist/module/interface.d.ts.map +1 -1
  36. package/dist/module/interface.js.map +1 -1
  37. package/dist/module/message/interface.d.ts +2 -2
  38. package/dist/module/message/interface.d.ts.map +1 -1
  39. package/dist/module/message/interface.js +0 -3
  40. package/dist/module/message/interface.js.map +1 -1
  41. package/dist/module/message/signed.d.ts +5 -5
  42. package/dist/module/message/signed.d.ts.map +1 -1
  43. package/dist/module/message/signed.js +8 -8
  44. package/dist/module/message/signed.js.map +1 -1
  45. package/dist/module/network/ElectrumNetworkProvider.d.ts +2 -2
  46. package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
  47. package/dist/module/network/ElectrumNetworkProvider.js +3 -2
  48. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  49. package/dist/module/network/NetworkProvider.d.ts +2 -2
  50. package/dist/module/network/NetworkProvider.d.ts.map +1 -1
  51. package/dist/module/network/constant.js +4 -4
  52. package/dist/module/network/constant.js.map +1 -1
  53. package/dist/module/network/getRelayFeeCache.js +2 -2
  54. package/dist/module/network/getRelayFeeCache.js.map +1 -1
  55. package/dist/module/rate/ExchangeRate.d.ts +2 -1
  56. package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
  57. package/dist/module/rate/ExchangeRate.js +4 -1
  58. package/dist/module/rate/ExchangeRate.js.map +1 -1
  59. package/dist/module/transaction/Wif.d.ts +25 -23
  60. package/dist/module/transaction/Wif.d.ts.map +1 -1
  61. package/dist/module/transaction/Wif.js +26 -25
  62. package/dist/module/transaction/Wif.js.map +1 -1
  63. package/dist/module/transaction/allocateFee.d.ts +3 -3
  64. package/dist/module/transaction/allocateFee.d.ts.map +1 -1
  65. package/dist/module/transaction/allocateFee.js +5 -6
  66. package/dist/module/transaction/allocateFee.js.map +1 -1
  67. package/dist/module/util/amountInSatoshi.d.ts +1 -1
  68. package/dist/module/util/amountInSatoshi.d.ts.map +1 -1
  69. package/dist/module/util/amountInSatoshi.js +3 -9
  70. package/dist/module/util/amountInSatoshi.js.map +1 -1
  71. package/dist/module/util/asSendRequestObject.d.ts.map +1 -1
  72. package/dist/module/util/asSendRequestObject.js +10 -7
  73. package/dist/module/util/asSendRequestObject.js.map +1 -1
  74. package/dist/module/util/checkUtxos.d.ts +2 -2
  75. package/dist/module/util/checkUtxos.d.ts.map +1 -1
  76. package/dist/module/util/checkUtxos.js +11 -12
  77. package/dist/module/util/checkUtxos.js.map +1 -1
  78. package/dist/module/util/convert.d.ts +3 -0
  79. package/dist/module/util/convert.d.ts.map +1 -1
  80. package/dist/module/util/convert.js +12 -0
  81. package/dist/module/util/convert.js.map +1 -1
  82. package/dist/module/util/deriveCashaddr.d.ts.map +1 -1
  83. package/dist/module/util/deriveCashaddr.js +6 -0
  84. package/dist/module/util/deriveCashaddr.js.map +1 -1
  85. package/dist/module/util/deriveNetwork.js +1 -1
  86. package/dist/module/util/deriveNetwork.js.map +1 -1
  87. package/dist/module/util/hd.d.ts +3 -0
  88. package/dist/module/util/hd.d.ts.map +1 -0
  89. package/dist/module/util/hd.js +11 -0
  90. package/dist/module/util/hd.js.map +1 -0
  91. package/dist/module/util/index.d.ts +3 -3
  92. package/dist/module/util/index.d.ts.map +1 -1
  93. package/dist/module/util/index.js +3 -3
  94. package/dist/module/util/index.js.map +1 -1
  95. package/dist/module/util/satoshiToAmount.d.ts +1 -1
  96. package/dist/module/util/satoshiToAmount.d.ts.map +1 -1
  97. package/dist/module/util/satoshiToAmount.js +3 -9
  98. package/dist/module/util/satoshiToAmount.js.map +1 -1
  99. package/dist/module/util/sumSendRequestAmounts.d.ts.map +1 -1
  100. package/dist/module/util/sumSendRequestAmounts.js +3 -4
  101. package/dist/module/util/sumSendRequestAmounts.js.map +1 -1
  102. package/dist/module/util/sumUtxoValue.d.ts +3 -3
  103. package/dist/module/util/sumUtxoValue.d.ts.map +1 -1
  104. package/dist/module/util/sumUtxoValue.js +2 -2
  105. package/dist/module/util/sumUtxoValue.js.map +1 -1
  106. package/dist/module/wallet/Base.d.ts +45 -103
  107. package/dist/module/wallet/Base.d.ts.map +1 -1
  108. package/dist/module/wallet/Base.js +99 -298
  109. package/dist/module/wallet/Base.js.map +1 -1
  110. package/dist/module/wallet/HDWallet.d.ts +164 -0
  111. package/dist/module/wallet/HDWallet.d.ts.map +1 -0
  112. package/dist/module/wallet/HDWallet.js +486 -0
  113. package/dist/module/wallet/HDWallet.js.map +1 -0
  114. package/dist/module/wallet/Util.js +1 -1
  115. package/dist/module/wallet/Util.js.map +1 -1
  116. package/dist/module/wallet/Watch.d.ts +151 -0
  117. package/dist/module/wallet/Watch.d.ts.map +1 -0
  118. package/dist/module/wallet/Watch.js +307 -0
  119. package/dist/module/wallet/Watch.js.map +1 -0
  120. package/dist/module/wallet/Wif.d.ts +23 -29
  121. package/dist/module/wallet/Wif.d.ts.map +1 -1
  122. package/dist/module/wallet/Wif.js +204 -267
  123. package/dist/module/wallet/Wif.js.map +1 -1
  124. package/dist/module/wallet/createWallet.d.ts +7 -1
  125. package/dist/module/wallet/createWallet.d.ts.map +1 -1
  126. package/dist/module/wallet/createWallet.js +26 -17
  127. package/dist/module/wallet/createWallet.js.map +1 -1
  128. package/dist/module/wallet/interface.d.ts +5 -6
  129. package/dist/module/wallet/interface.d.ts.map +1 -1
  130. package/dist/module/wallet/model.d.ts +15 -19
  131. package/dist/module/wallet/model.d.ts.map +1 -1
  132. package/dist/module/wallet/model.js +5 -25
  133. package/dist/module/wallet/model.js.map +1 -1
  134. package/dist/tsconfig.tsbuildinfo +1 -1
  135. package/package.json +1 -1
  136. package/src/cache/MemoryCache.ts +5 -5
  137. package/src/cache/index.ts +1 -0
  138. package/src/cache/walletCache.ts +239 -0
  139. package/src/chain.ts +1 -1
  140. package/src/constant.ts +1 -1
  141. package/src/enum.ts +0 -6
  142. package/src/history/{electrumTransformer.test.ts → getHistory.test.ts} +26 -53
  143. package/src/history/{electrumTransformer.ts → getHistory.ts} +31 -15
  144. package/src/index.ts +3 -1
  145. package/src/interface.ts +8 -2
  146. package/src/message/interface.ts +2 -28
  147. package/src/message/signed.test.ts +36 -48
  148. package/src/message/signed.ts +9 -12
  149. package/src/network/Connection.test.ts +3 -3
  150. package/src/network/ElectrumNetworkProvider.ts +5 -5
  151. package/src/network/NetworkProvider.ts +2 -2
  152. package/src/network/Rpc.test.ts +3 -4
  153. package/src/network/constant.ts +4 -4
  154. package/src/network/getRelayFeeCache.ts +2 -2
  155. package/src/rate/ExchangeRate.test.ts +2 -44
  156. package/src/rate/ExchangeRate.ts +5 -2
  157. package/src/transaction/Wif.ts +59 -52
  158. package/src/transaction/allocateFee.test.ts +110 -131
  159. package/src/transaction/allocateFee.ts +14 -15
  160. package/src/util/amountInSatoshi.test.ts +1 -9
  161. package/src/util/amountInSatoshi.ts +6 -10
  162. package/src/util/asSendRequestObject.ts +12 -7
  163. package/src/util/checkUtxos.ts +21 -26
  164. package/src/util/convert.ts +18 -0
  165. package/src/util/deriveCashaddr.ts +8 -0
  166. package/src/util/deriveNetwork.ts +1 -1
  167. package/src/util/derivePublicKeyHash.test.ts +0 -13
  168. package/src/util/hd.ts +16 -0
  169. package/src/util/index.ts +3 -7
  170. package/src/util/satoshiToAmount.test.ts +1 -1
  171. package/src/util/satoshiToAmount.ts +4 -10
  172. package/src/util/sumSendRequestAmounts.ts +3 -4
  173. package/src/util/sumUtxoValue.ts +7 -7
  174. package/src/wallet/Base.ts +147 -420
  175. package/src/wallet/Cashtokens.test.headless.js +11 -11
  176. package/src/wallet/Cashtokens.test.ts +36 -37
  177. package/src/wallet/HDWallet.test.ts +515 -0
  178. package/src/wallet/HDWallet.ts +764 -0
  179. package/src/wallet/Util.ts +1 -1
  180. package/src/wallet/Watch.ts +447 -0
  181. package/src/wallet/Wif.bip39.test.ts +1 -1
  182. package/src/wallet/Wif.test.ts +108 -133
  183. package/src/wallet/Wif.ts +258 -283
  184. package/src/wallet/createWallet.ts +28 -18
  185. package/src/wallet/interface.ts +5 -6
  186. package/src/wallet/model.test.ts +4 -7
  187. package/src/wallet/model.ts +19 -51
  188. package/dist/module/history/electrumTransformer.d.ts.map +0 -1
  189. package/dist/module/history/electrumTransformer.js.map +0 -1
  190. package/dist/module/util/balanceObjectFromSatoshi.d.ts +0 -8
  191. package/dist/module/util/balanceObjectFromSatoshi.d.ts.map +0 -1
  192. package/dist/module/util/balanceObjectFromSatoshi.js +0 -35
  193. package/dist/module/util/balanceObjectFromSatoshi.js.map +0 -1
  194. package/src/util/balanceObjectFromSatoshi.test.ts +0 -58
  195. 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
@@ -1,3 +1,3 @@
1
1
  export const bchParam = {
2
- subUnits: 100000000,
2
+ subUnits: 100000000n,
3
3
  };
package/src/constant.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export const DELIMITER = ":";
2
2
 
3
3
  // Min amount utxo can be to be accepted by the network
4
- export const DUST_UTXO_THRESHOLD = 546;
4
+ export const DUST_UTXO_THRESHOLD = 546n;
5
5
 
6
6
  // Current chained tx limit
7
7
  export const MEMPOOL_CHAIN_LIMIT = 50;
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 { getAddressHistory } from "./electrumTransformer";
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 getAddressHistory({
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: 31000,
35
- unit: "satoshis",
32
+ value: 31000n,
36
33
  },
37
34
  {
38
35
  cashaddr: charlie.cashaddr!,
39
- value: 41000,
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: 2100,
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: 2100,
56
- unit: "satoshis",
50
+ value: 2100n,
57
51
  },
58
52
  ]);
59
53
  expect(sendResponse!.txId!.length).toBe(64);
60
- expect(sendResponse.balance!.bch).toBeGreaterThan(0.01);
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 getAddressHistory({
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: 31000,
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: 2100,
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: 2100,
136
- unit: "satoshis",
124
+ value: 2100n,
137
125
  },
138
126
  ]);
139
127
  expect(sendResponse!.txId!.length).toBe(64);
140
- expect(sendResponse.balance!.bch).toBeGreaterThan(0.01);
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 getAddressHistory({
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: 31000,
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: 2100,
211
- unit: "satoshis",
194
+ value: 2100n,
212
195
  },
213
196
  {
214
197
  cashaddr: alice.cashaddr!,
215
- value: 2100,
216
- unit: "satoshis",
198
+ value: 2100n,
217
199
  },
218
200
  {
219
201
  cashaddr: alice.cashaddr!,
220
- value: 2100,
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!.bch).toBeGreaterThan(0.01);
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 getAddressHistory({
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: 600,
273
- unit: "satoshis",
251
+ value: 600n,
274
252
  },
275
253
  {
276
254
  cashaddr: bob.cashaddr!,
277
- value: 600,
278
- unit: "satoshis",
255
+ value: 600n,
279
256
  },
280
257
  {
281
258
  cashaddr: bob.cashaddr!,
282
- value: 600,
283
- unit: "satoshis",
259
+ value: 600n,
284
260
  },
285
261
  {
286
262
  cashaddr: bob.cashaddr!,
287
- value: 600,
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!.bch).toBeGreaterThan(0.01);
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 getAddressHistory({
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 getAddressHistory = async ({
26
- address,
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
- address: string;
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 = (await provider.getHistory(address, fromHeight, toHeight))
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 heights = history
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
- heights.map(async (height) => [
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(address);
122
- if (typeof decoded === "string") {
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: decoded.prefix as CashAddressNetworkPrefix,
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: decoded.prefix as CashAddressNetworkPrefix,
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 === 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 === 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 = await provider.getBalance(address);
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 { getAddressHistory } from "./history/electrumTransformer.js";
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 UtxoI {
18
+ export interface Utxo {
19
19
  txid: string;
20
20
  vout: number;
21
- satoshis: number;
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 {
@@ -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
- ): Promise<VerifyMessageResponseI>;
8
+ ): VerifyMessageResponseI;
35
9
  }
36
10
 
37
11
  export interface SignedMessageRawI {