mainnet-js 3.1.7 → 4.0.0-next.10

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 (267) hide show
  1. package/dist/module/cache/IndexedDbCache.d.ts +1 -1
  2. package/dist/module/cache/IndexedDbCache.d.ts.map +1 -1
  3. package/dist/module/cache/MemoryCache.d.ts +1 -1
  4. package/dist/module/cache/MemoryCache.d.ts.map +1 -1
  5. package/dist/module/cache/WebStorageCache.d.ts +1 -1
  6. package/dist/module/cache/WebStorageCache.d.ts.map +1 -1
  7. package/dist/module/cache/walletCache.d.ts +16 -6
  8. package/dist/module/cache/walletCache.d.ts.map +1 -1
  9. package/dist/module/cache/walletCache.js +92 -34
  10. package/dist/module/cache/walletCache.js.map +1 -1
  11. package/dist/module/cli.js +1 -2
  12. package/dist/module/cli.js.map +1 -1
  13. package/dist/module/db/index.d.ts +1 -1
  14. package/dist/module/db/index.d.ts.map +1 -1
  15. package/dist/module/db/index.js +1 -1
  16. package/dist/module/db/index.js.map +1 -1
  17. package/dist/module/enum.d.ts +1 -1
  18. package/dist/module/enum.d.ts.map +1 -1
  19. package/dist/module/history/getHistory.d.ts +1 -1
  20. package/dist/module/history/getHistory.d.ts.map +1 -1
  21. package/dist/module/history/getHistory.js +3 -3
  22. package/dist/module/history/getHistory.js.map +1 -1
  23. package/dist/module/index.d.ts +25 -22
  24. package/dist/module/index.d.ts.map +1 -1
  25. package/dist/module/index.js +33 -26
  26. package/dist/module/index.js.map +1 -1
  27. package/dist/module/interface.d.ts +12 -2
  28. package/dist/module/interface.d.ts.map +1 -1
  29. package/dist/module/interface.js.map +1 -1
  30. package/dist/module/libauth.d.ts +1 -1
  31. package/dist/module/libauth.d.ts.map +1 -1
  32. package/dist/module/libauth.js +1 -1
  33. package/dist/module/libauth.js.map +1 -1
  34. package/dist/module/mine/mine.d.ts +2 -7
  35. package/dist/module/mine/mine.d.ts.map +1 -1
  36. package/dist/module/mine/mine.js +6 -27
  37. package/dist/module/mine/mine.js.map +1 -1
  38. package/dist/module/network/Connection.d.ts +1 -12
  39. package/dist/module/network/Connection.d.ts.map +1 -1
  40. package/dist/module/network/Connection.js +24 -33
  41. package/dist/module/network/Connection.js.map +1 -1
  42. package/dist/module/network/ElectrumNetworkProvider.d.ts +16 -17
  43. package/dist/module/network/ElectrumNetworkProvider.d.ts.map +1 -1
  44. package/dist/module/network/ElectrumNetworkProvider.js +91 -93
  45. package/dist/module/network/ElectrumNetworkProvider.js.map +1 -1
  46. package/dist/module/network/MockNetworkProvider.d.ts +28 -0
  47. package/dist/module/network/MockNetworkProvider.d.ts.map +1 -0
  48. package/dist/module/network/MockNetworkProvider.js +74 -0
  49. package/dist/module/network/MockNetworkProvider.js.map +1 -0
  50. package/dist/module/network/NetworkProvider.d.ts +9 -2
  51. package/dist/module/network/NetworkProvider.d.ts.map +1 -1
  52. package/dist/module/network/configuration.d.ts +2 -4
  53. package/dist/module/network/configuration.d.ts.map +1 -1
  54. package/dist/module/network/configuration.js +25 -50
  55. package/dist/module/network/configuration.js.map +1 -1
  56. package/dist/module/network/constant.d.ts +7 -7
  57. package/dist/module/network/constant.d.ts.map +1 -1
  58. package/dist/module/network/constant.js +21 -24
  59. package/dist/module/network/constant.js.map +1 -1
  60. package/dist/module/network/default.d.ts +5 -3
  61. package/dist/module/network/default.d.ts.map +1 -1
  62. package/dist/module/network/default.js +29 -51
  63. package/dist/module/network/default.js.map +1 -1
  64. package/dist/module/network/index.d.ts +4 -4
  65. package/dist/module/network/index.d.ts.map +1 -1
  66. package/dist/module/network/index.js +2 -2
  67. package/dist/module/network/index.js.map +1 -1
  68. package/dist/module/network/interface.d.ts +0 -6
  69. package/dist/module/network/interface.d.ts.map +1 -1
  70. package/dist/module/rate/ExchangeRate.d.ts +1 -1
  71. package/dist/module/rate/ExchangeRate.d.ts.map +1 -1
  72. package/dist/module/rate/ExchangeRate.js +13 -7
  73. package/dist/module/rate/ExchangeRate.js.map +1 -1
  74. package/dist/module/transaction/Wif.d.ts +3 -3
  75. package/dist/module/transaction/Wif.d.ts.map +1 -1
  76. package/dist/module/transaction/Wif.js +4 -4
  77. package/dist/module/transaction/Wif.js.map +1 -1
  78. package/dist/module/transaction/allocateFee.d.ts +1 -1
  79. package/dist/module/transaction/allocateFee.d.ts.map +1 -1
  80. package/dist/module/transaction/allocateFee.js +2 -2
  81. package/dist/module/transaction/allocateFee.js.map +1 -1
  82. package/dist/module/util/deriveCashaddr.js.map +1 -1
  83. package/dist/module/util/deriveNetwork.js +1 -1
  84. package/dist/module/util/deriveNetwork.js.map +1 -1
  85. package/dist/module/util/getAddrsByXpubKey.js +1 -1
  86. package/dist/module/util/getAddrsByXpubKey.js.map +1 -1
  87. package/dist/module/util/getXPubKey.js +1 -1
  88. package/dist/module/util/getXPubKey.js.map +1 -1
  89. package/dist/module/util/hd.d.ts +2 -0
  90. package/dist/module/util/hd.d.ts.map +1 -1
  91. package/dist/module/util/hd.js +41 -0
  92. package/dist/module/util/hd.js.map +1 -1
  93. package/dist/module/util/index.d.ts +7 -9
  94. package/dist/module/util/index.d.ts.map +1 -1
  95. package/dist/module/util/index.js +7 -9
  96. package/dist/module/util/index.js.map +1 -1
  97. package/dist/module/util/transaction.js +1 -1
  98. package/dist/module/util/transaction.js.map +1 -1
  99. package/dist/module/wallet/Base.d.ts +13 -9
  100. package/dist/module/wallet/Base.d.ts.map +1 -1
  101. package/dist/module/wallet/Base.js +54 -58
  102. package/dist/module/wallet/Base.js.map +1 -1
  103. package/dist/module/wallet/HDWallet.d.ts.map +1 -1
  104. package/dist/module/wallet/HDWallet.js +19 -38
  105. package/dist/module/wallet/HDWallet.js.map +1 -1
  106. package/dist/module/wallet/Util.d.ts +4 -22
  107. package/dist/module/wallet/Util.d.ts.map +1 -1
  108. package/dist/module/wallet/Util.js +75 -102
  109. package/dist/module/wallet/Util.js.map +1 -1
  110. package/dist/module/wallet/Watch.d.ts +24 -5
  111. package/dist/module/wallet/Watch.d.ts.map +1 -1
  112. package/dist/module/wallet/Watch.js +141 -17
  113. package/dist/module/wallet/Watch.js.map +1 -1
  114. package/dist/module/wallet/Wif.d.ts +2 -6
  115. package/dist/module/wallet/Wif.d.ts.map +1 -1
  116. package/dist/module/wallet/Wif.js +3 -69
  117. package/dist/module/wallet/Wif.js.map +1 -1
  118. package/dist/module/wallet/createWallet.d.ts +1 -1
  119. package/dist/module/wallet/createWallet.d.ts.map +1 -1
  120. package/dist/module/wallet/createWallet.js +2 -1
  121. package/dist/module/wallet/createWallet.js.map +1 -1
  122. package/dist/module/wallet/interface.d.ts +3 -2
  123. package/dist/module/wallet/interface.d.ts.map +1 -1
  124. package/dist/module/wallet/model.d.ts +2 -1
  125. package/dist/module/wallet/model.d.ts.map +1 -1
  126. package/dist/module/wallet/model.js +1 -1
  127. package/dist/module/wallet/model.js.map +1 -1
  128. package/package.json +17 -29
  129. package/dist/index.html +0 -9
  130. package/dist/mainnet-3.1.7.js +0 -2066
  131. package/dist/module/network/util.d.ts +0 -3
  132. package/dist/module/network/util.d.ts.map +0 -1
  133. package/dist/module/network/util.js +0 -27
  134. package/dist/module/network/util.js.map +0 -1
  135. package/dist/module/test/expect.d.ts +0 -12
  136. package/dist/module/test/expect.d.ts.map +0 -1
  137. package/dist/module/test/expect.js +0 -47
  138. package/dist/module/test/expect.js.map +0 -1
  139. package/dist/module/test/fetch.d.ts +0 -3
  140. package/dist/module/test/fetch.d.ts.map +0 -1
  141. package/dist/module/test/fetch.js +0 -32
  142. package/dist/module/test/fetch.js.map +0 -1
  143. package/dist/module/util/randomBytes.d.ts +0 -2
  144. package/dist/module/util/randomBytes.d.ts.map +0 -1
  145. package/dist/module/util/randomBytes.js +0 -13
  146. package/dist/module/util/randomBytes.js.map +0 -1
  147. package/dist/tsconfig.tsbuildinfo +0 -1
  148. package/src/cache/IndexedDbCache.test.ts +0 -15
  149. package/src/cache/IndexedDbCache.ts +0 -172
  150. package/src/cache/MemoryCache.test.ts +0 -15
  151. package/src/cache/MemoryCache.ts +0 -32
  152. package/src/cache/WebStorageCache.test.ts +0 -15
  153. package/src/cache/WebStorageCache.ts +0 -38
  154. package/src/cache/index.ts +0 -2
  155. package/src/cache/interface.ts +0 -9
  156. package/src/cache/walletCache.ts +0 -254
  157. package/src/chain.ts +0 -3
  158. package/src/cli.ts +0 -32
  159. package/src/config.ts +0 -23
  160. package/src/constant.ts +0 -27
  161. package/src/db/ExchangeRateProvider.ts +0 -28
  162. package/src/db/StorageProvider.ts +0 -64
  163. package/src/db/index.ts +0 -2
  164. package/src/db/interface.ts +0 -11
  165. package/src/enum.ts +0 -34
  166. package/src/history/getHistory.test.ts +0 -290
  167. package/src/history/getHistory.ts +0 -411
  168. package/src/history/interface.ts +0 -24
  169. package/src/index.ts +0 -48
  170. package/src/interface.ts +0 -72
  171. package/src/libauth.ts +0 -11
  172. package/src/message/index.ts +0 -2
  173. package/src/message/interface.ts +0 -40
  174. package/src/message/signed.test.ts +0 -309
  175. package/src/message/signed.ts +0 -201
  176. package/src/mine/index.ts +0 -1
  177. package/src/mine/mine.test.ts +0 -10
  178. package/src/mine/mine.ts +0 -42
  179. package/src/network/Connection.test.ts +0 -51
  180. package/src/network/Connection.ts +0 -73
  181. package/src/network/ElectrumNetworkProvider.ts +0 -657
  182. package/src/network/NetworkProvider.ts +0 -180
  183. package/src/network/Rpc.test.ts +0 -130
  184. package/src/network/configuration.test.ts +0 -59
  185. package/src/network/configuration.ts +0 -72
  186. package/src/network/constant.ts +0 -43
  187. package/src/network/default.ts +0 -120
  188. package/src/network/electrum.test.ts +0 -28
  189. package/src/network/getRelayFeeCache.test.ts +0 -15
  190. package/src/network/getRelayFeeCache.ts +0 -23
  191. package/src/network/index.ts +0 -14
  192. package/src/network/interface.ts +0 -80
  193. package/src/network/util.test.ts +0 -24
  194. package/src/network/util.ts +0 -30
  195. package/src/rate/ExchangeRate.test.headless.js +0 -35
  196. package/src/rate/ExchangeRate.test.ts +0 -51
  197. package/src/rate/ExchangeRate.ts +0 -142
  198. package/src/test/expect.ts +0 -59
  199. package/src/test/fetch.ts +0 -39
  200. package/src/test/json.test.ts +0 -13
  201. package/src/transaction/Wif.ts +0 -680
  202. package/src/transaction/allocateFee.test.ts +0 -298
  203. package/src/transaction/allocateFee.ts +0 -149
  204. package/src/util/amountInSatoshi.test.ts +0 -27
  205. package/src/util/amountInSatoshi.ts +0 -33
  206. package/src/util/asSendRequestObject.ts +0 -81
  207. package/src/util/base64.test.ts +0 -39
  208. package/src/util/base64.ts +0 -12
  209. package/src/util/browserNotSupported.ts +0 -7
  210. package/src/util/checkForEmptySeed.ts +0 -9
  211. package/src/util/checkUtxos.ts +0 -29
  212. package/src/util/checkWifNetwork.ts +0 -24
  213. package/src/util/convert.test.ts +0 -46
  214. package/src/util/convert.ts +0 -50
  215. package/src/util/delay.ts +0 -3
  216. package/src/util/deriveCashaddr.test.ts +0 -164
  217. package/src/util/deriveCashaddr.ts +0 -143
  218. package/src/util/deriveLockscript.ts +0 -16
  219. package/src/util/deriveNetwork.ts +0 -19
  220. package/src/util/derivePublicKeyHash.test.ts +0 -55
  221. package/src/util/derivePublicKeyHash.ts +0 -64
  222. package/src/util/floor.test.ts +0 -21
  223. package/src/util/floor.ts +0 -4
  224. package/src/util/getAddrsByXpubKey.test.ts +0 -115
  225. package/src/util/getAddrsByXpubKey.ts +0 -86
  226. package/src/util/getRuntimePlatform.test.headless.js +0 -40
  227. package/src/util/getRuntimePlatform.test.ts +0 -5
  228. package/src/util/getRuntimePlatform.ts +0 -31
  229. package/src/util/getUsdRate.ts +0 -5
  230. package/src/util/getXPubKey.ts +0 -39
  231. package/src/util/hash160.test.ts +0 -18
  232. package/src/util/hash160.ts +0 -12
  233. package/src/util/hd.ts +0 -16
  234. package/src/util/header.test.ts +0 -34
  235. package/src/util/header.ts +0 -26
  236. package/src/util/index.ts +0 -33
  237. package/src/util/randomBytes.ts +0 -13
  238. package/src/util/randomInt.test.ts +0 -15
  239. package/src/util/randomInt.ts +0 -4
  240. package/src/util/sanitizeAddress.ts +0 -10
  241. package/src/util/sanitizeUnit.ts +0 -11
  242. package/src/util/satoshiToAmount.test.ts +0 -6
  243. package/src/util/satoshiToAmount.ts +0 -33
  244. package/src/util/sumSendRequestAmounts.ts +0 -34
  245. package/src/util/sumUtxoValue.ts +0 -27
  246. package/src/util/transaction.ts +0 -10
  247. package/src/wallet/Base.ts +0 -1563
  248. package/src/wallet/Cashtokens.test.headless.js +0 -730
  249. package/src/wallet/Cashtokens.test.ts +0 -1411
  250. package/src/wallet/HDWallet.test.ts +0 -1086
  251. package/src/wallet/HDWallet.ts +0 -992
  252. package/src/wallet/Util.test.ts +0 -134
  253. package/src/wallet/Util.ts +0 -191
  254. package/src/wallet/WalletCache.test.ts +0 -45
  255. package/src/wallet/Watch.ts +0 -441
  256. package/src/wallet/Wif.bip39.test.ts +0 -48
  257. package/src/wallet/Wif.test.ts +0 -1189
  258. package/src/wallet/Wif.ts +0 -687
  259. package/src/wallet/Wif.watchOnly.test.ts +0 -58
  260. package/src/wallet/createWallet.ts +0 -238
  261. package/src/wallet/enum.ts +0 -18
  262. package/src/wallet/interface.ts +0 -102
  263. package/src/wallet/model.test.ts +0 -24
  264. package/src/wallet/model.ts +0 -352
  265. package/tsconfig.browser.json +0 -11
  266. package/tsconfig.json +0 -33
  267. package/webpack.config.cjs +0 -132
@@ -1,1086 +0,0 @@
1
- import { assertSuccess, decodeTransaction, hexToBin } from "@bitauth/libauth";
2
- import { HDWallet, RegTestHDWallet, GAP_SIZE } from "./HDWallet";
3
- import { RegTestWallet, Wallet } from "./Wif";
4
- import { Config } from "../config";
5
- import { getNextUnusedIndex } from "../util/hd";
6
- import { NFTCapability } from "../interface";
7
- import { TokenMintRequest, TokenSendRequest } from "./model";
8
- import { stringify } from "../cache";
9
- import { mine } from "../mine";
10
- import { delay } from "../util/delay";
11
- import { CancelFn } from "./interface";
12
-
13
- const expectedXpub =
14
- "xpub6CGqRCnS5qDfyxtzV3y3tj8CY7qf3z3GiB2qnCUTdNkhpNxbLtobrU5ZXBVPG3rzPcBUpJAoj3K1u1jyDwKuduL71gLPm27Tckc85apgQRr";
15
- const expectedXprv =
16
- "xprv9yHV1hFYFTfNmUpXP2S3XbBTz61AeXKRLx7Eyp4r53DiwadSoMVMJfm5fvtxBc3NFKfozcH42LM66Kb5VaxdLvGk43JWahCegx6iaEJbkB2";
17
-
18
- describe("HDWallet", () => {
19
- it("should create a new HDWallet instance", async () => {
20
- const wallet = await Wallet.fromSeed(
21
- "divide battle bulb improve hockey favorite charge save merit fatal frog cage"
22
- );
23
- const walletSeed = await HDWallet.fromSeed(
24
- "divide battle bulb improve hockey favorite charge save merit fatal frog cage"
25
- );
26
- const walletPriv = await HDWallet.fromXPriv(expectedXprv);
27
- const walletPub = await HDWallet.fromXPub(expectedXpub);
28
-
29
- expect(walletSeed.xPub).toBe(expectedXpub);
30
- expect(walletSeed.xPriv).toBe(expectedXprv);
31
- expect(walletPriv.xPub).toBe(expectedXpub);
32
- expect(walletPriv.xPriv).toBe(expectedXprv);
33
- expect(walletPub.xPub).toBe(expectedXpub);
34
-
35
- expect(wallet.getDepositAddress()).toBe(walletSeed.getDepositAddress());
36
- expect(wallet.getDepositAddress()).toBe(walletPriv.getDepositAddress());
37
- expect(wallet.getDepositAddress()).toBe(walletPub.getDepositAddress());
38
-
39
- expect(walletSeed.getChangeAddress()).toBe(walletPriv.getChangeAddress());
40
- expect(walletSeed.getChangeAddress()).toBe(walletPub.getChangeAddress());
41
- });
42
-
43
- it("should serialize", async () => {
44
- const wallet = await HDWallet.fromSeed(
45
- "divide battle bulb improve hockey favorite charge save merit fatal frog cage"
46
- );
47
- expect(wallet.toString()).toBe(
48
- "hd:mainnet:divide battle bulb improve hockey favorite charge save merit fatal frog cage:m/44'/0'/0':0:0"
49
- );
50
- expect(wallet.toDbString()).toBe(
51
- "hd:mainnet:divide battle bulb improve hockey favorite charge save merit fatal frog cage:m/44'/0'/0':0:0"
52
- );
53
-
54
- wallet.name = "testWallet";
55
- expect(wallet.toString()).toBe("named:mainnet:testWallet");
56
- expect(wallet.toDbString()).toBe(
57
- "hd:mainnet:divide battle bulb improve hockey favorite charge save merit fatal frog cage:m/44'/0'/0':0:0"
58
- );
59
-
60
- const xPrivWallet = await HDWallet.fromXPriv(expectedXprv);
61
- expect(xPrivWallet.toString()).toBe(
62
- "hd:mainnet:xprv9yHV1hFYFTfNmUpXP2S3XbBTz61AeXKRLx7Eyp4r53DiwadSoMVMJfm5fvtxBc3NFKfozcH42LM66Kb5VaxdLvGk43JWahCegx6iaEJbkB2:0:0"
63
- );
64
-
65
- const xPubWallet = await HDWallet.fromXPub(expectedXpub);
66
- expect(xPubWallet.toString()).toBe(
67
- "hd:mainnet:xpub6CGqRCnS5qDfyxtzV3y3tj8CY7qf3z3GiB2qnCUTdNkhpNxbLtobrU5ZXBVPG3rzPcBUpJAoj3K1u1jyDwKuduL71gLPm27Tckc85apgQRr:0:0"
68
- );
69
-
70
- const uninitializedWallet = new HDWallet();
71
- expect(() => uninitializedWallet.toDbString()).toThrowError(
72
- "HDWallet has no mnemonic, xPriv or xPub to serialize"
73
- );
74
- });
75
-
76
- it("Get next index", () => {
77
- expect(getNextUnusedIndex(-1, [null, null, null])).toBe(0);
78
- expect(getNextUnusedIndex(-1, ["", null, null])).toBe(1);
79
- expect(getNextUnusedIndex(-1, ["", null, ""])).toBe(1);
80
- expect(getNextUnusedIndex(-1, ["", "", null])).toBe(2);
81
- expect(getNextUnusedIndex(-1, ["", "", ""])).toBe(3);
82
-
83
- expect(getNextUnusedIndex(0, [null, null, null])).toBe(0);
84
- expect(getNextUnusedIndex(1, [null, null, null])).toBe(1);
85
- expect(getNextUnusedIndex(2, [null, null, null])).toBe(2);
86
-
87
- expect(
88
- getNextUnusedIndex(-1, [
89
- "759933dd4c6d75f097ec75158ebc04a1f89bc484fc6df0352816328fb4f533a4",
90
- null,
91
- null,
92
- null,
93
- ])
94
- ).toBe(1);
95
- });
96
-
97
- it("promises", async () => {
98
- const result = await Promise.all([
99
- (async () => 1)(),
100
- new Promise((resolve) => resolve(2)),
101
- ]);
102
- expect(stringify(result)).toBe(stringify([1, 2]));
103
- });
104
-
105
- it("deposit indexes", async () => {
106
- const hdWallet = await RegTestHDWallet.newRandom();
107
- expect(hdWallet.depositIndex).toBe(0);
108
-
109
- const fundingWallet = await RegTestWallet.fromId(
110
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
111
- );
112
-
113
- await fundingWallet.send({
114
- cashaddr: hdWallet.getDepositAddress(0),
115
- value: 100000n,
116
- });
117
- await hdWallet.waitForUpdate({ depositIndex: 1 });
118
- expect(hdWallet.depositIndex).toBe(1);
119
-
120
- await fundingWallet.send({
121
- cashaddr: hdWallet.getDepositAddress(1),
122
- value: 100000n,
123
- });
124
- await hdWallet.waitForUpdate({ depositIndex: 2 });
125
- expect(hdWallet.depositIndex).toBe(2);
126
-
127
- await fundingWallet.send({
128
- cashaddr: hdWallet.getDepositAddress(4),
129
- value: 100000n,
130
- });
131
- await hdWallet.waitForUpdate({ depositIndex: 5 });
132
- expect(hdWallet.depositIndex).toBe(5);
133
-
134
- // beyond gap size, should not update index
135
- await fundingWallet.send({
136
- cashaddr: hdWallet.getDepositAddress(30),
137
- value: 100000n,
138
- });
139
- expect(hdWallet.depositIndex).toBe(5);
140
-
141
- await hdWallet.scanMoreAddresses(30);
142
- expect(hdWallet.depositIndex).toBe(31);
143
- });
144
-
145
- it("should scan beyond gap to find real deposit index", async () => {
146
- const fundingWallet = await RegTestWallet.fromId(
147
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
148
- );
149
-
150
- // Create a wallet and fund addresses 0 and 20
151
- // Initial scan covers 0-19, finds addr 0 used (depositIndex=1)
152
- // Gap from index 1 to end of scan (19) is 19 < 20, so scanner extends
153
- // Next batch includes addr 20, finds it used (depositIndex=21)
154
- const seedWallet = await RegTestHDWallet.newRandom();
155
- const addr0 = seedWallet.getDepositAddress(0);
156
- const addr20 = seedWallet.getDepositAddress(20);
157
-
158
- await fundingWallet.send([
159
- { cashaddr: addr0, value: 10000n },
160
- { cashaddr: addr20, value: 10000n },
161
- ]);
162
- // Wait for seedWallet to see both transactions via electrum
163
- await seedWallet.waitForUpdate({ depositIndex: 21 });
164
-
165
- // Restore wallet from same seed, starting from index 0
166
- const restoredWallet = await RegTestHDWallet.fromSeed(
167
- seedWallet.mnemonic!,
168
- seedWallet.derivation
169
- );
170
- await restoredWallet.watchPromise;
171
-
172
- expect(restoredWallet.depositIndex).toBe(21);
173
- });
174
-
175
- it("changeIndex updates when spending", async () => {
176
- const fundingWallet = await RegTestWallet.fromId(
177
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
178
- );
179
- const hdWallet = await RegTestHDWallet.newRandom();
180
- const bob = await RegTestWallet.newRandom();
181
-
182
- expect(hdWallet.depositIndex).toBe(0);
183
- expect(hdWallet.changeIndex).toBe(0);
184
-
185
- // fund deposit address 0
186
- await fundingWallet.send({
187
- cashaddr: hdWallet.getDepositAddress(0),
188
- value: 100000n,
189
- });
190
- await hdWallet.waitForUpdate({ depositIndex: 1 });
191
- expect(hdWallet.depositIndex).toBe(1);
192
- expect(hdWallet.changeIndex).toBe(0);
193
-
194
- // spend, which creates change on change address 0
195
- await hdWallet.send({
196
- cashaddr: bob.getDepositAddress(),
197
- value: 50000n,
198
- });
199
- await hdWallet.waitForUpdate({ changeIndex: 1 });
200
- expect(hdWallet.changeIndex).toBe(1);
201
-
202
- // fund and spend again, change goes to change address 1
203
- await fundingWallet.send({
204
- cashaddr: hdWallet.getDepositAddress(),
205
- value: 100000n,
206
- });
207
- await hdWallet.waitForUpdate({ depositIndex: 2 });
208
- await hdWallet.send({
209
- cashaddr: bob.getDepositAddress(),
210
- value: 50000n,
211
- });
212
- await hdWallet.waitForUpdate({ changeIndex: 2 });
213
- expect(hdWallet.changeIndex).toBe(2);
214
-
215
- // Restore wallet from same seed and verify depositIndex is correct
216
- const restoredWallet = await RegTestHDWallet.fromSeed(
217
- hdWallet.mnemonic!,
218
- hdWallet.derivation
219
- );
220
- await restoredWallet.watchPromise;
221
-
222
- expect(restoredWallet.depositIndex).toBe(hdWallet.depositIndex);
223
- expect(restoredWallet.changeIndex).toBe(hdWallet.changeIndex);
224
- });
225
-
226
- it("hasAddress should recognize wallet addresses", async () => {
227
- const hdWallet = await RegTestHDWallet.newRandom();
228
-
229
- const deposit0 = hdWallet.getDepositAddress(0);
230
- const deposit1 = hdWallet.getDepositAddress(1);
231
- const change0 = hdWallet.getChangeAddress(0);
232
-
233
- expect(hdWallet.hasAddress(deposit0)).toBe(true);
234
- expect(hdWallet.hasAddress(deposit1)).toBe(true);
235
- expect(hdWallet.hasAddress(change0)).toBe(true);
236
- expect(
237
- hdWallet.hasAddress("bchreg:qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq9d5dxv4")
238
- ).toBe(false);
239
- });
240
-
241
- it("Should send funds from an HDWallet", async () => {
242
- const fundingWallet = await RegTestWallet.fromId(
243
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
244
- );
245
-
246
- const hdWallet = await RegTestHDWallet.newRandom();
247
- expect(await hdWallet.getBalance()).toBe(0n);
248
-
249
- const depositAddress = hdWallet.getDepositAddress();
250
- await fundingWallet.send({
251
- cashaddr: depositAddress,
252
- value: 100000n,
253
- });
254
- await hdWallet.waitForUpdate({ depositIndex: 1 });
255
-
256
- expect(await hdWallet.getBalance()).toBe(100000n);
257
-
258
- const depositAddress2 = hdWallet.getDepositAddress();
259
- expect(depositAddress).not.toBe(depositAddress2);
260
-
261
- // send more funds to new deposit address
262
- await fundingWallet.send({
263
- cashaddr: depositAddress2,
264
- value: 100000n,
265
- });
266
- await hdWallet.waitForUpdate({ depositIndex: 2 });
267
-
268
- expect(await hdWallet.getBalance()).toBe(200000n);
269
-
270
- expect(
271
- await (
272
- await RegTestWallet.watchOnly(hdWallet.getDepositAddress(0))
273
- ).getBalance()
274
- ).toBe(100000n);
275
- expect(
276
- await (
277
- await RegTestWallet.watchOnly(hdWallet.getDepositAddress(1))
278
- ).getBalance()
279
- ).toBe(100000n);
280
- expect(
281
- await (
282
- await RegTestWallet.watchOnly(hdWallet.getDepositAddress(2))
283
- ).getBalance()
284
- ).toBe(0n);
285
-
286
- expect(
287
- await (
288
- await RegTestWallet.watchOnly(hdWallet.getChangeAddress(0))
289
- ).getBalance()
290
- ).toBe(0n);
291
-
292
- const bob = await RegTestWallet.newRandom();
293
-
294
- await hdWallet.send({
295
- cashaddr: bob.getDepositAddress(),
296
- value: 150000n,
297
- });
298
- await hdWallet.waitForUpdate({ changeIndex: 1 });
299
-
300
- expect(
301
- await (
302
- await RegTestWallet.watchOnly(hdWallet.getDepositAddress(0))
303
- ).getBalance()
304
- ).toBe(0n);
305
- expect(
306
- await (
307
- await RegTestWallet.watchOnly(hdWallet.getDepositAddress(1))
308
- ).getBalance()
309
- ).toBe(0n);
310
- expect(
311
- await (
312
- await RegTestWallet.watchOnly(hdWallet.getDepositAddress(2))
313
- ).getBalance()
314
- ).toBe(0n);
315
-
316
- expect(
317
- await (
318
- await RegTestWallet.watchOnly(hdWallet.getChangeAddress(0))
319
- ).getBalance()
320
- ).toBeGreaterThan(50000n - 1000n);
321
-
322
- expect(hdWallet.getChangeAddress()).not.toBe(hdWallet.getChangeAddress(0));
323
- expect(hdWallet.getChangeAddress()).toBe(hdWallet.getChangeAddress(1));
324
-
325
- expect(hdWallet.depositIndex).toBe(2);
326
- expect(hdWallet.changeIndex).toBe(1);
327
-
328
- expect(await bob.getBalance()).toBe(150000n);
329
-
330
- expect(await hdWallet.getBalance()).toBe(49639n); // minus fees
331
-
332
- expect(await hdWallet.getMaxAmountToSend()).toBe(49407n);
333
- const charlie = await RegTestWallet.newRandom();
334
- await hdWallet.sendMax(charlie.cashaddr);
335
-
336
- // Wait for HD wallet to process the spent notification
337
- while ((await hdWallet.getBalance()) > 0n)
338
- await new Promise((r) => setTimeout(r, 50));
339
-
340
- expect(await charlie.getBalance()).toBe(49407n);
341
- expect(await hdWallet.getBalance()).toBe(0n);
342
- });
343
-
344
- it("Should build unsigned transactions from an HDWallet", async () => {
345
- const fundingWallet = await RegTestWallet.fromId(
346
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
347
- );
348
-
349
- const hdWallet = await RegTestHDWallet.newRandom();
350
- expect(await hdWallet.getBalance()).toBe(0n);
351
-
352
- const depositAddress = hdWallet.getDepositAddress();
353
- await fundingWallet.send({
354
- cashaddr: depositAddress,
355
- value: 100000n,
356
- });
357
- await hdWallet.waitForUpdate({ depositIndex: 1 });
358
-
359
- expect(await hdWallet.getBalance()).toBe(100000n);
360
-
361
- const unsignedTx = await hdWallet.send(
362
- {
363
- cashaddr: (await RegTestWallet.newRandom()).getDepositAddress(),
364
- value: 50000n,
365
- },
366
- {
367
- buildUnsigned: true,
368
- }
369
- );
370
-
371
- const tx = assertSuccess(
372
- decodeTransaction(hexToBin(unsignedTx.unsignedTransaction!))
373
- );
374
- expect(tx.inputs.length).toBe(1);
375
- expect(tx.inputs[0].unlockingBytecode.length).toBe(0); // should be empty
376
- });
377
-
378
- it("WalletCache persistence, addresses", async () => {
379
- const memoryCacheValue = Config.UseMemoryCache;
380
- Config.UseMemoryCache = true;
381
-
382
- const hdWallet = await RegTestHDWallet.newRandom();
383
-
384
- // get some addresses to populate cache
385
- hdWallet.getDepositAddress(0);
386
- hdWallet.getDepositAddress(100);
387
-
388
- hdWallet.getChangeAddress(0);
389
- hdWallet.getChangeAddress(100);
390
-
391
- // persist cache
392
- await hdWallet.walletCache.persist();
393
-
394
- // check cache data is there in other instance
395
- const otherWallet = await RegTestHDWallet.fromId(hdWallet.toDbString());
396
- expect(
397
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))
398
- ?.privateKey instanceof Uint8Array
399
- ).toBe(true);
400
- expect(
401
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))
402
- ?.publicKey instanceof Uint8Array
403
- ).toBe(true);
404
- expect(
405
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))
406
- ?.publicKeyHash instanceof Uint8Array
407
- ).toBe(true);
408
-
409
- expect(
410
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))
411
- ).toBeDefined();
412
- expect(
413
- otherWallet.walletCache.get(hdWallet.getDepositAddress(99))
414
- ).not.toBeDefined();
415
- expect(
416
- otherWallet.walletCache.get(hdWallet.getDepositAddress(100))
417
- ).toBeDefined();
418
-
419
- expect(
420
- otherWallet.walletCache.get(hdWallet.getChangeAddress(0))
421
- ).toBeDefined();
422
- expect(
423
- otherWallet.walletCache.get(hdWallet.getChangeAddress(99))
424
- ).not.toBeDefined();
425
- expect(
426
- otherWallet.walletCache.get(hdWallet.getChangeAddress(100))
427
- ).toBeDefined();
428
-
429
- Config.UseMemoryCache = memoryCacheValue;
430
- });
431
-
432
- it("WalletCache persistence, status and utxo", async () => {
433
- const memoryCacheValue = Config.UseMemoryCache;
434
- Config.UseMemoryCache = true;
435
-
436
- const hdWallet = await RegTestHDWallet.newRandom();
437
-
438
- // get some addresses to populate cache
439
- hdWallet.getDepositAddress(0);
440
- expect(
441
- hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.status
442
- ).toBeNull();
443
-
444
- const fundingWallet = await RegTestWallet.fromId(
445
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
446
- );
447
- await fundingWallet.send({
448
- cashaddr: hdWallet.getDepositAddress(0),
449
- value: 100000n,
450
- });
451
- await hdWallet.waitForUpdate({ depositIndex: 1 });
452
-
453
- expect(
454
- hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.status
455
- ).not.toBeNull();
456
- expect(
457
- hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.utxos.length
458
- ).toBe(1);
459
-
460
- // persist cache
461
- await hdWallet.walletCache.persist();
462
-
463
- // check cache data is there in other instance
464
- const otherWallet = await RegTestHDWallet.fromId(hdWallet.toDbString());
465
- await otherWallet.watchPromise; // ensure any async init is done
466
- expect(
467
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))?.status
468
- ).not.toBeNull();
469
- expect(
470
- hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.utxos.length
471
- ).toBe(1);
472
- expect(
473
- stringify(hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.utxos)
474
- ).toBe(
475
- stringify(
476
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))?.utxos
477
- )
478
- );
479
-
480
- Config.UseMemoryCache = memoryCacheValue;
481
- });
482
-
483
- it("WalletCache persistence, rawHistory", async () => {
484
- const memoryCacheValue = Config.UseMemoryCache;
485
- Config.UseMemoryCache = true;
486
-
487
- const hdWallet = await RegTestHDWallet.newRandom();
488
-
489
- // get deposit address to populate cache
490
- hdWallet.getDepositAddress(0);
491
- expect(
492
- hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.rawHistory
493
- ).toEqual([]);
494
-
495
- const fundingWallet = await RegTestWallet.fromId(
496
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
497
- );
498
- await fundingWallet.send({
499
- cashaddr: hdWallet.getDepositAddress(0),
500
- value: 100000n,
501
- });
502
- await hdWallet.waitForUpdate({ depositIndex: 1 });
503
-
504
- // rawHistory should now have one entry
505
- expect(
506
- hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.rawHistory.length
507
- ).toBe(1);
508
-
509
- // persist cache
510
- await hdWallet.walletCache.persist();
511
-
512
- // check cache data is there in other instance
513
- const otherWallet = await RegTestHDWallet.fromId(hdWallet.toDbString());
514
- await otherWallet.watchPromise;
515
- expect(
516
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))?.rawHistory
517
- .length
518
- ).toBe(1);
519
- expect(
520
- stringify(
521
- hdWallet.walletCache.get(hdWallet.getDepositAddress(0))?.rawHistory
522
- )
523
- ).toBe(
524
- stringify(
525
- otherWallet.walletCache.get(hdWallet.getDepositAddress(0))?.rawHistory
526
- )
527
- );
528
-
529
- Config.UseMemoryCache = memoryCacheValue;
530
- });
531
-
532
- it("getRawHistory uses cached data", async () => {
533
- const hdWallet = await RegTestHDWallet.newRandom();
534
-
535
- const fundingWallet = await RegTestWallet.fromId(
536
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
537
- );
538
-
539
- // Send to multiple deposit addresses
540
- await fundingWallet.send({
541
- cashaddr: hdWallet.getDepositAddress(0),
542
- value: 100000n,
543
- });
544
- await hdWallet.waitForUpdate({ depositIndex: 1 });
545
-
546
- await fundingWallet.send({
547
- cashaddr: hdWallet.getDepositAddress(1),
548
- value: 100000n,
549
- });
550
- await hdWallet.waitForUpdate({ depositIndex: 2 });
551
-
552
- // Check depositRawHistory arrays are populated
553
- expect(hdWallet.depositRawHistory[0].length).toBe(1);
554
- expect(hdWallet.depositRawHistory[1].length).toBe(1);
555
-
556
- // getRawHistory should return deduplicated history from cache
557
- const rawHistory = await hdWallet.getRawHistory();
558
- expect(rawHistory.length).toBe(2);
559
-
560
- // Verify history items have expected structure
561
- expect(rawHistory[0]).toHaveProperty("tx_hash");
562
- expect(rawHistory[0]).toHaveProperty("height");
563
- });
564
-
565
- it("getHistory works with cached rawHistory", async () => {
566
- const hdWallet = await RegTestHDWallet.newRandom();
567
-
568
- const fundingWallet = await RegTestWallet.fromId(
569
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
570
- );
571
-
572
- await fundingWallet.send({
573
- cashaddr: hdWallet.getDepositAddress(0),
574
- value: 100000n,
575
- });
576
- await hdWallet.waitForUpdate({ depositIndex: 1 });
577
-
578
- const history = await hdWallet.getHistory({ unit: "sat" });
579
- expect(history.length).toBe(1);
580
- expect(history[0].valueChange).toBe(100000);
581
- });
582
-
583
- it("incremental history fetching with lastConfirmedHeight", async () => {
584
- const memoryCacheValue = Config.UseMemoryCache;
585
- Config.UseMemoryCache = true;
586
-
587
- const hdWallet = await RegTestHDWallet.newRandom();
588
-
589
- const fundingWallet = await RegTestWallet.fromId(
590
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
591
- );
592
-
593
- // First transaction
594
- await fundingWallet.send({
595
- cashaddr: hdWallet.getDepositAddress(0),
596
- value: 50000n,
597
- });
598
- await hdWallet.waitForUpdate({ depositIndex: 1 });
599
-
600
- // Check rawHistory is populated
601
- const cacheEntry1 = hdWallet.walletCache.get(hdWallet.getDepositAddress(0));
602
- expect(cacheEntry1?.rawHistory.length).toBe(1);
603
- // lastConfirmedHeight may be 0 if tx is unconfirmed
604
- expect(cacheEntry1?.lastConfirmedHeight).toBeGreaterThanOrEqual(0);
605
-
606
- // Second transaction to same address
607
- await fundingWallet.send({
608
- cashaddr: hdWallet.getDepositAddress(0),
609
- value: 60000n,
610
- });
611
- while (hdWallet.depositRawHistory[0].length < 2)
612
- await new Promise((r) => setTimeout(r, 50));
613
-
614
- // Check history accumulated correctly
615
- const cacheEntry2 = hdWallet.walletCache.get(hdWallet.getDepositAddress(0));
616
- expect(cacheEntry2?.rawHistory.length).toBe(2);
617
-
618
- // Verify getRawHistory returns both transactions
619
- const rawHistory = await hdWallet.getRawHistory();
620
- expect(rawHistory.length).toBe(2);
621
-
622
- // Persist and reload - cache should be preserved
623
- await hdWallet.walletCache.persist();
624
- const otherWallet = await RegTestHDWallet.fromId(hdWallet.toDbString());
625
- await otherWallet.watchPromise;
626
-
627
- const reloadedEntry = otherWallet.walletCache.get(
628
- hdWallet.getDepositAddress(0)
629
- );
630
- expect(reloadedEntry?.lastConfirmedHeight).toBe(
631
- cacheEntry2?.lastConfirmedHeight
632
- );
633
- expect(reloadedEntry?.rawHistory.length).toBe(2);
634
-
635
- Config.UseMemoryCache = memoryCacheValue;
636
- });
637
-
638
- it("watchWallet registers and removes callbacks", async () => {
639
- const hdWallet = await RegTestHDWallet.newRandom();
640
-
641
- const cancel = await hdWallet.watchStatus(() => {});
642
-
643
- // Verify callback was registered
644
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(1);
645
-
646
- // Cancel
647
- await cancel();
648
-
649
- // Verify callback was removed
650
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(0);
651
- });
652
-
653
- it("waitForUpdate resolves via timeout when depositIndex target is not reached", async () => {
654
- const fundingWallet = await RegTestWallet.fromId(
655
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
656
- );
657
- const hdWallet = await RegTestHDWallet.newRandom();
658
- expect(hdWallet.depositIndex).toBe(0);
659
-
660
- // No transaction sent — idle timer should resolve without hanging
661
- await hdWallet.waitForUpdate({ depositIndex: 1 });
662
-
663
- // depositIndex is still 0 because no funds arrived
664
- expect(hdWallet.depositIndex).toBe(0);
665
-
666
- // No leftover watchers
667
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(0);
668
-
669
- // Now send a real transaction — waitForUpdate should resolve once index advances
670
- await fundingWallet.send({
671
- cashaddr: hdWallet.getDepositAddress(0),
672
- value: 100000n,
673
- });
674
- await hdWallet.waitForUpdate();
675
-
676
- expect(hdWallet.depositIndex).toBe(1);
677
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(0);
678
- });
679
-
680
- it("watchWallet supports multiple watchers", async () => {
681
- const hdWallet = await RegTestHDWallet.newRandom();
682
-
683
- const cancel1 = await hdWallet.watchStatus(() => {});
684
- const cancel2 = await hdWallet.watchStatus(() => {});
685
-
686
- // Verify both callbacks registered
687
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(2);
688
-
689
- // Cancel one watcher
690
- await cancel1();
691
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(1);
692
-
693
- await cancel2();
694
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(0);
695
- });
696
-
697
- it("watchWalletBalance sets up callback correctly", async () => {
698
- const hdWallet = await RegTestHDWallet.newRandom();
699
-
700
- const cancel = await hdWallet.watchBalance(() => {});
701
-
702
- // Verify callback was registered via watchWallet
703
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(1);
704
-
705
- await cancel();
706
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(0);
707
- });
708
-
709
- it("watchWalletTransactions sets up callback correctly", async () => {
710
- const hdWallet = await RegTestHDWallet.newRandom();
711
-
712
- const cancel = await hdWallet.watchTransactions(() => {});
713
-
714
- // Verify callback was registered via watchWallet
715
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(1);
716
-
717
- await cancel();
718
- expect((hdWallet as any).walletWatchCallbacks.length).toBe(0);
719
- });
720
-
721
- it("Cashtokens integration test", async () => {
722
- const fundingWallet = await RegTestWallet.fromId(
723
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
724
- );
725
- const alice = await RegTestHDWallet.newRandom();
726
- await fundingWallet.send({
727
- cashaddr: alice.getDepositAddress(),
728
- value: 1000000n,
729
- });
730
- await alice.waitForUpdate({ depositIndex: 1 });
731
-
732
- const genesisResponse = await alice.tokenGenesis({
733
- cashaddr: alice.getDepositAddress(1),
734
- nft: {
735
- capability: NFTCapability.minting,
736
- commitment: "abcd",
737
- },
738
- amount: 1000n,
739
- });
740
-
741
- const tokenId = genesisResponse.categories![0];
742
-
743
- await new Promise((resolve) => setTimeout(resolve, 500));
744
-
745
- // mint 2 NFTs, amount reducing
746
- const response = await alice.tokenMint(tokenId, [
747
- new TokenMintRequest({
748
- cashaddr: alice.getDepositAddress(2),
749
- nft: {
750
- capability: NFTCapability.none,
751
- commitment: "",
752
- },
753
- }),
754
- new TokenMintRequest({
755
- cashaddr: alice.getDepositAddress(3),
756
- nft: {
757
- capability: NFTCapability.mutable,
758
- commitment: "00",
759
- },
760
- }),
761
- ]);
762
-
763
- await new Promise((resolve) => setTimeout(resolve, 500));
764
-
765
- const newTokenUtxos = await alice.getTokenUtxos(tokenId);
766
- expect(newTokenUtxos.length).toBe(3);
767
- expect(tokenId).toEqual(response.categories![0]);
768
-
769
- const bob = await RegTestWallet.newRandom();
770
- await alice.send([
771
- new TokenSendRequest({
772
- cashaddr: bob.cashaddr!,
773
- category: tokenId,
774
- nft: {
775
- capability: NFTCapability.minting,
776
- commitment: "abcd",
777
- },
778
- amount: 1000n,
779
- }),
780
- new TokenSendRequest({
781
- cashaddr: bob.cashaddr!,
782
- category: tokenId,
783
- nft: {
784
- capability: NFTCapability.none,
785
- commitment: "",
786
- },
787
- }),
788
- new TokenSendRequest({
789
- cashaddr: bob.cashaddr!,
790
- category: tokenId,
791
- nft: {
792
- capability: NFTCapability.mutable,
793
- commitment: "00",
794
- },
795
- }),
796
- ]);
797
-
798
- await new Promise((resolve) => setTimeout(resolve, 500));
799
-
800
- expect((await alice.getTokenUtxos(tokenId)).length).toBe(0);
801
- const bobTokenUtxos = await bob.getTokenUtxos(tokenId);
802
- expect(bobTokenUtxos.length).toBe(3);
803
- expect(tokenId).toEqual(response.categories![0]);
804
- });
805
-
806
- test("Test enforcing token addresses", async () => {
807
- const fundingWallet = await RegTestWallet.fromId(
808
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
809
- );
810
- const alice = await RegTestHDWallet.newRandom();
811
- await fundingWallet.send({
812
- cashaddr: alice.getDepositAddress(),
813
- value: 1000000n,
814
- });
815
- await alice.waitForUpdate({ depositIndex: 1 });
816
-
817
- const genesisResponse = await alice.tokenGenesis({
818
- amount: 100n,
819
- });
820
- const category = genesisResponse.categories![0];
821
-
822
- await new Promise((resolve) => setTimeout(resolve, 500));
823
-
824
- const previousValue = Config.EnforceCashTokenReceiptAddresses;
825
-
826
- const wrap = (addr) => {
827
- return new Promise((resolve) => {
828
- resolve(new TokenSendRequest({ cashaddr: addr, category: "" }));
829
- });
830
- };
831
-
832
- Config.EnforceCashTokenReceiptAddresses = false;
833
- await expect(wrap(alice.getDepositAddress())).resolves.not.toThrow();
834
- await expect(wrap(alice.getTokenDepositAddress())).resolves.not.toThrow();
835
-
836
- await expect(
837
- alice.send(
838
- new TokenSendRequest({
839
- cashaddr: alice.getDepositAddress(),
840
- category: category,
841
- amount: 1n,
842
- })
843
- )
844
- ).resolves.not.toThrow();
845
-
846
- await new Promise((resolve) => setTimeout(resolve, 500));
847
-
848
- await expect(
849
- alice.send(
850
- new TokenSendRequest({
851
- cashaddr: alice.getTokenDepositAddress(),
852
- category: category,
853
- amount: 2n,
854
- })
855
- )
856
- ).resolves.not.toThrow();
857
-
858
- await new Promise((resolve) => setTimeout(resolve, 500));
859
-
860
- Config.EnforceCashTokenReceiptAddresses = true;
861
- await expect(wrap(alice.getDepositAddress())).rejects.toThrow();
862
- await expect(wrap(alice.getTokenDepositAddress())).resolves.not.toThrow();
863
-
864
- await expect(
865
- (async () =>
866
- await alice.send(
867
- new TokenSendRequest({
868
- cashaddr: alice.getDepositAddress(),
869
- category: category,
870
- amount: 1n,
871
- })
872
- ))()
873
- ).rejects.toThrow();
874
-
875
- await new Promise((resolve) => setTimeout(resolve, 500));
876
-
877
- await expect(
878
- alice.send(
879
- new TokenSendRequest({
880
- cashaddr: alice.getTokenDepositAddress(),
881
- category: category,
882
- amount: 2n,
883
- })
884
- )
885
- ).resolves.not.toThrow();
886
-
887
- await new Promise((resolve) => setTimeout(resolve, 500));
888
-
889
- Config.EnforceCashTokenReceiptAddresses = previousValue;
890
- });
891
-
892
- it("watchTransactionHashes reports new transactions on HD wallet", async () => {
893
- const fundingWallet = await RegTestWallet.fromId(
894
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
895
- );
896
- const hdWallet = await RegTestHDWallet.newRandom();
897
-
898
- // Fund the HD wallet at deposit address 0
899
- await fundingWallet.send({
900
- cashaddr: hdWallet.getDepositAddress(0),
901
- value: 100000n,
902
- });
903
- await mine({ cashaddr: hdWallet.getDepositAddress(0), blocks: 1 });
904
- await delay(2000);
905
-
906
- // Set up watchTransactionHashes, collect reported tx hashes
907
- const reportedHashes: string[] = [];
908
- let cancelWatch: CancelFn;
909
- cancelWatch = await hdWallet.watchTransactionHashes((txHash) => {
910
- reportedHashes.push(txHash);
911
- });
912
-
913
- // Wait for initial callback to fire with existing tx
914
- await delay(2000);
915
-
916
- // Send a new transaction to the HD wallet
917
- const sendResponse = await fundingWallet.send({
918
- cashaddr: hdWallet.getDepositAddress(),
919
- value: 50000n,
920
- });
921
- await mine({ cashaddr: hdWallet.getDepositAddress(0), blocks: 1 });
922
- await delay(2000);
923
-
924
- await cancelWatch();
925
-
926
- // The new transaction's txId should appear in collected hashes
927
- expect(reportedHashes).toContain(sendResponse.txId);
928
- });
929
-
930
- it("watchTransactionHashes does not re-report old transactions", async () => {
931
- const fundingWallet = await RegTestWallet.fromId(
932
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
933
- );
934
- const hdWallet = await RegTestHDWallet.newRandom();
935
-
936
- // Start watching before any transactions so the first funding triggers a callback
937
- const reportedHashes: string[] = [];
938
- let cancelWatch: CancelFn;
939
- cancelWatch = await hdWallet.watchTransactionHashes((txHash) => {
940
- reportedHashes.push(txHash);
941
- });
942
-
943
- // Fund the HD wallet at deposit address 0
944
- const fundResponse = await fundingWallet.send({
945
- cashaddr: hdWallet.getDepositAddress(0),
946
- value: 100000n,
947
- });
948
- await mine({ cashaddr: hdWallet.getDepositAddress(0), blocks: 1 });
949
- await delay(2000);
950
-
951
- // Record how many hashes reported so far (the initial set)
952
- const initialCount = reportedHashes.length;
953
- expect(reportedHashes).toContain(fundResponse.txId);
954
- const initialHashes = [...reportedHashes];
955
-
956
- // Send a second transaction to the HD wallet
957
- const sendResponse2 = await fundingWallet.send({
958
- cashaddr: hdWallet.getDepositAddress(),
959
- value: 50000n,
960
- });
961
- await mine({ cashaddr: hdWallet.getDepositAddress(0), blocks: 1 });
962
- await delay(2000);
963
-
964
- await cancelWatch();
965
-
966
- // Hashes reported after the initial set
967
- const laterHashes = reportedHashes.slice(initialCount);
968
-
969
- // The second tx hash was reported
970
- expect(laterHashes).toContain(sendResponse2.txId);
971
-
972
- // None of the initial tx hashes were reported again after the first callback
973
- for (const hash of initialHashes) {
974
- expect(laterHashes).not.toContain(hash);
975
- }
976
- });
977
-
978
- it("watchTransactionHashes handles transactions across multiple deposit addresses", async () => {
979
- const fundingWallet = await RegTestWallet.fromId(
980
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
981
- );
982
- const hdWallet = await RegTestHDWallet.newRandom();
983
-
984
- // Fund deposit address 0
985
- const fund0Response = await fundingWallet.send({
986
- cashaddr: hdWallet.getDepositAddress(0),
987
- value: 100000n,
988
- });
989
- await mine({ cashaddr: hdWallet.getDepositAddress(0), blocks: 1 });
990
- await delay(1000);
991
-
992
- // Fund deposit address 1
993
- const fund1Response = await fundingWallet.send({
994
- cashaddr: hdWallet.getDepositAddress(1),
995
- value: 100000n,
996
- });
997
- await mine({ cashaddr: hdWallet.getDepositAddress(0), blocks: 1 });
998
- await delay(1000);
999
-
1000
- // depositIndex should be 2
1001
- expect(hdWallet.depositIndex).toBe(2);
1002
-
1003
- // Set up watchTransactionHashes, collect all reported hashes
1004
- const reportedHashes: string[] = [];
1005
- let cancelWatch: CancelFn;
1006
- cancelWatch = await hdWallet.watchTransactionHashes((txHash) => {
1007
- reportedHashes.push(txHash);
1008
- });
1009
-
1010
- // Wait for initial callback to fire
1011
- await delay(2000);
1012
-
1013
- // Send a new transaction to the wallet's next deposit address
1014
- const fund2Response = await fundingWallet.send({
1015
- cashaddr: hdWallet.getDepositAddress(),
1016
- value: 50000n,
1017
- });
1018
- await mine({ cashaddr: hdWallet.getDepositAddress(0), blocks: 1 });
1019
- await delay(2000);
1020
-
1021
- await cancelWatch();
1022
-
1023
- // All 3 tx hashes appear in the collected output
1024
- expect(reportedHashes).toContain(fund0Response.txId);
1025
- expect(reportedHashes).toContain(fund1Response.txId);
1026
- expect(reportedHashes).toContain(fund2Response.txId);
1027
-
1028
- // Each tx hash appears exactly once
1029
- const uniqueHashes = new Set(reportedHashes);
1030
- expect(uniqueHashes.size).toBe(reportedHashes.length);
1031
- });
1032
-
1033
- it("gap is maintained when addresses near the edge are used", async () => {
1034
- const fundingWallet = await RegTestWallet.fromId(
1035
- "wif:regtest:cNfsPtqN2bMRS7vH5qd8tR8GMvgXyL5BjnGAKgZ8DYEiCrCCQcP6"
1036
- );
1037
- const hdWallet = await RegTestHDWallet.newRandom();
1038
- await hdWallet.watchPromise;
1039
-
1040
- // Initially: depositIndex=0, watched addresses 0..(GAP_SIZE-1)
1041
- expect(hdWallet.depositIndex).toBe(0);
1042
- const initialWatched = (hdWallet as any).depositStatuses.length;
1043
- expect(initialWatched).toBe(GAP_SIZE);
1044
-
1045
- // Fund an address near the edge of the gap
1046
- const edgeIndex = GAP_SIZE - 2;
1047
- await fundingWallet.send({
1048
- cashaddr: hdWallet.getDepositAddress(edgeIndex),
1049
- value: 10000n,
1050
- });
1051
-
1052
- // Wait for the subscription callback to fire and gap extension to complete
1053
- await hdWallet.waitForUpdate({ depositIndex: edgeIndex + 1 });
1054
- await delay(1000);
1055
-
1056
- // depositIndex should have advanced
1057
- expect(hdWallet.depositIndex).toBe(edgeIndex + 1);
1058
-
1059
- // The watched range should have extended to maintain the gap
1060
- const newWatched = (hdWallet as any).depositStatuses.length;
1061
- expect(newWatched).toBeGreaterThanOrEqual(hdWallet.depositIndex + GAP_SIZE);
1062
-
1063
- // Verify the new addresses are actually subscribed (watchCancels populated)
1064
- const watchCancels = (hdWallet as any).depositWatchCancels;
1065
- for (let i = initialWatched; i < newWatched; i++) {
1066
- expect(watchCancels[i]).toBeDefined();
1067
- }
1068
-
1069
- // Fund an address in the newly extended range to prove it's being watched
1070
- const newEdge = newWatched - 2;
1071
- await fundingWallet.send({
1072
- cashaddr: hdWallet.getDepositAddress(newEdge),
1073
- value: 10000n,
1074
- });
1075
- await hdWallet.waitForUpdate({ depositIndex: newEdge + 1 });
1076
- await delay(1000);
1077
-
1078
- expect(hdWallet.depositIndex).toBe(newEdge + 1);
1079
-
1080
- // Gap should still be maintained after the second extension
1081
- const finalWatched = (hdWallet as any).depositStatuses.length;
1082
- expect(finalWatched).toBeGreaterThanOrEqual(
1083
- hdWallet.depositIndex + GAP_SIZE
1084
- );
1085
- });
1086
- });