@buildonspark/spark-sdk 0.0.15 → 0.0.16

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 (131) hide show
  1. package/dist/services/wallet-config.d.ts +1 -0
  2. package/dist/services/wallet-config.js +1 -0
  3. package/dist/services/wallet-config.js.map +1 -1
  4. package/dist/spark-sdk.d.ts +1 -1
  5. package/dist/spark-sdk.js +3 -3
  6. package/dist/spark-sdk.js.map +1 -1
  7. package/package.json +4 -3
  8. package/src/examples/example.js +247 -0
  9. package/src/examples/example.ts +207 -0
  10. package/src/graphql/client.ts +282 -0
  11. package/src/graphql/mutations/CompleteCoopExit.ts +19 -0
  12. package/src/graphql/mutations/CompleteLeavesSwap.ts +17 -0
  13. package/src/graphql/mutations/RequestCoopExit.ts +20 -0
  14. package/src/graphql/mutations/RequestLightningReceive.ts +26 -0
  15. package/src/graphql/mutations/RequestLightningSend.ts +17 -0
  16. package/src/graphql/mutations/RequestSwapLeaves.ts +24 -0
  17. package/src/graphql/objects/BitcoinNetwork.ts +22 -0
  18. package/src/graphql/objects/CompleteCoopExitInput.ts +41 -0
  19. package/src/graphql/objects/CompleteCoopExitOutput.ts +45 -0
  20. package/src/graphql/objects/CompleteLeavesSwapInput.ts +45 -0
  21. package/src/graphql/objects/CompleteLeavesSwapOutput.ts +45 -0
  22. package/src/graphql/objects/CompleteSeedReleaseInput.ts +41 -0
  23. package/src/graphql/objects/CompleteSeedReleaseOutput.ts +43 -0
  24. package/src/graphql/objects/Connection.ts +90 -0
  25. package/src/graphql/objects/CoopExitFeeEstimateInput.ts +41 -0
  26. package/src/graphql/objects/CoopExitFeeEstimateOutput.ts +52 -0
  27. package/src/graphql/objects/CoopExitRequest.ts +118 -0
  28. package/src/graphql/objects/CurrencyAmount.ts +74 -0
  29. package/src/graphql/objects/CurrencyUnit.ts +32 -0
  30. package/src/graphql/objects/Entity.ts +202 -0
  31. package/src/graphql/objects/GetChallengeInput.ts +37 -0
  32. package/src/graphql/objects/GetChallengeOutput.ts +43 -0
  33. package/src/graphql/objects/Invoice.ts +83 -0
  34. package/src/graphql/objects/Leaf.ts +59 -0
  35. package/src/graphql/objects/LeavesSwapFeeEstimateInput.ts +37 -0
  36. package/src/graphql/objects/LeavesSwapFeeEstimateOutput.ts +52 -0
  37. package/src/graphql/objects/LeavesSwapRequest.ts +192 -0
  38. package/src/graphql/objects/LightningReceiveFeeEstimateInput.ts +41 -0
  39. package/src/graphql/objects/LightningReceiveFeeEstimateOutput.ts +52 -0
  40. package/src/graphql/objects/LightningReceiveRequest.ts +147 -0
  41. package/src/graphql/objects/LightningReceiveRequestStatus.ts +34 -0
  42. package/src/graphql/objects/LightningSendFeeEstimateInput.ts +37 -0
  43. package/src/graphql/objects/LightningSendFeeEstimateOutput.ts +52 -0
  44. package/src/graphql/objects/LightningSendRequest.ts +134 -0
  45. package/src/graphql/objects/LightningSendRequestStatus.ts +28 -0
  46. package/src/graphql/objects/NotifyReceiverTransferInput.ts +41 -0
  47. package/src/graphql/objects/PageInfo.ts +58 -0
  48. package/src/graphql/objects/Provider.ts +41 -0
  49. package/src/graphql/objects/RequestCoopExitInput.ts +41 -0
  50. package/src/graphql/objects/RequestCoopExitOutput.ts +45 -0
  51. package/src/graphql/objects/RequestLeavesSwapInput.ts +55 -0
  52. package/src/graphql/objects/RequestLeavesSwapOutput.ts +45 -0
  53. package/src/graphql/objects/RequestLightningReceiveInput.ts +58 -0
  54. package/src/graphql/objects/RequestLightningReceiveOutput.ts +45 -0
  55. package/src/graphql/objects/RequestLightningSendInput.ts +41 -0
  56. package/src/graphql/objects/RequestLightningSendOutput.ts +45 -0
  57. package/src/graphql/objects/SparkCoopExitRequestStatus.ts +20 -0
  58. package/src/graphql/objects/SparkLeavesSwapRequestStatus.ts +20 -0
  59. package/src/graphql/objects/SparkTransferToLeavesConnection.ts +79 -0
  60. package/src/graphql/objects/SparkWalletUser.ts +86 -0
  61. package/src/graphql/objects/StartSeedReleaseInput.ts +37 -0
  62. package/src/graphql/objects/SwapLeaf.ts +53 -0
  63. package/src/graphql/objects/Transfer.ts +98 -0
  64. package/src/graphql/objects/UserLeafInput.ts +28 -0
  65. package/src/graphql/objects/VerifyChallengeInput.ts +51 -0
  66. package/src/graphql/objects/VerifyChallengeOutput.ts +43 -0
  67. package/src/graphql/objects/WalletUserIdentityPublicKeyInput.ts +37 -0
  68. package/src/graphql/objects/WalletUserIdentityPublicKeyOutput.ts +43 -0
  69. package/src/graphql/objects/index.ts +67 -0
  70. package/src/graphql/queries/CoopExitFeeEstimate.ts +18 -0
  71. package/src/graphql/queries/CurrentUser.ts +10 -0
  72. package/src/graphql/queries/LightningReceiveFeeEstimate.ts +18 -0
  73. package/src/graphql/queries/LightningSendFeeEstimate.ts +16 -0
  74. package/src/proto/common.ts +431 -0
  75. package/src/proto/google/protobuf/descriptor.ts +6625 -0
  76. package/src/proto/google/protobuf/duration.ts +197 -0
  77. package/src/proto/google/protobuf/empty.ts +83 -0
  78. package/src/proto/google/protobuf/timestamp.ts +226 -0
  79. package/src/proto/mock.ts +151 -0
  80. package/src/proto/spark.ts +12727 -0
  81. package/src/proto/spark_authn.ts +673 -0
  82. package/src/proto/validate/validate.ts +6047 -0
  83. package/src/services/config.ts +71 -0
  84. package/src/services/connection.ts +264 -0
  85. package/src/services/coop-exit.ts +190 -0
  86. package/src/services/deposit.ts +327 -0
  87. package/src/services/lightning.ts +341 -0
  88. package/src/services/lrc20.ts +42 -0
  89. package/src/services/token-transactions.ts +499 -0
  90. package/src/services/transfer.ts +1188 -0
  91. package/src/services/tree-creation.ts +618 -0
  92. package/src/services/wallet-config.ts +141 -0
  93. package/src/signer/signer.ts +531 -0
  94. package/src/spark-sdk.ts +1644 -0
  95. package/src/tests/adaptor-signature.test.ts +64 -0
  96. package/src/tests/bitcoin.test.ts +122 -0
  97. package/src/tests/coop-exit.test.ts +233 -0
  98. package/src/tests/deposit.test.ts +98 -0
  99. package/src/tests/keys.test.ts +82 -0
  100. package/src/tests/lightning.test.ts +307 -0
  101. package/src/tests/secret-sharing.test.ts +63 -0
  102. package/src/tests/swap.test.ts +252 -0
  103. package/src/tests/test-util.ts +92 -0
  104. package/src/tests/tokens.test.ts +47 -0
  105. package/src/tests/transfer.test.ts +371 -0
  106. package/src/tests/tree-creation.test.ts +56 -0
  107. package/src/tests/utils/spark-testing-wallet.ts +37 -0
  108. package/src/tests/utils/test-faucet.ts +257 -0
  109. package/src/types/grpc.ts +8 -0
  110. package/src/types/index.ts +3 -0
  111. package/src/utils/adaptor-signature.ts +189 -0
  112. package/src/utils/bitcoin.ts +138 -0
  113. package/src/utils/crypto.ts +14 -0
  114. package/src/utils/index.ts +12 -0
  115. package/src/utils/keys.ts +92 -0
  116. package/src/utils/mempool.ts +42 -0
  117. package/src/utils/network.ts +70 -0
  118. package/src/utils/proof.ts +17 -0
  119. package/src/utils/response-validation.ts +26 -0
  120. package/src/utils/secret-sharing.ts +263 -0
  121. package/src/utils/signing.ts +96 -0
  122. package/src/utils/token-hashing.ts +163 -0
  123. package/src/utils/token-keyshares.ts +31 -0
  124. package/src/utils/token-transactions.ts +71 -0
  125. package/src/utils/transaction.ts +45 -0
  126. package/src/utils/wasm-wrapper.ts +57 -0
  127. package/src/utils/wasm.ts +154 -0
  128. package/src/wasm/spark_bindings.d.ts +208 -0
  129. package/src/wasm/spark_bindings.js +1161 -0
  130. package/src/wasm/spark_bindings_bg.wasm +0 -0
  131. package/src/wasm/spark_bindings_bg.wasm.d.ts +136 -0
@@ -0,0 +1,47 @@
1
+ import { numberToBytesBE } from "@noble/curves/abstract/utils";
2
+ import { hashTokenTransaction } from "../utils/token-hashing.js";
3
+
4
+ describe("hash token transaction", () => {
5
+ it("should produce the exact same hash", () => {
6
+ const tokenAmount: bigint = 1000n;
7
+
8
+ const tokenPublicKey = new Uint8Array([
9
+ 242, 155, 208, 90, 72, 211, 120, 244, 69, 99, 28, 101, 149, 222, 123, 50,
10
+ 252, 63, 99, 54, 137, 226, 7, 224, 163, 122, 93, 248, 42, 159, 173, 45,
11
+ ]);
12
+
13
+ const identityPubKey = new Uint8Array([
14
+ 25, 155, 208, 90, 72, 211, 120, 244, 69, 99, 28, 101, 149, 222, 123, 50,
15
+ 252, 63, 99, 54, 137, 226, 7, 224, 163, 122, 93, 248, 42, 159, 173, 46,
16
+ ]);
17
+
18
+ const tokenTransaction = {
19
+ tokenInput: {
20
+ $case: "mintInput" as const,
21
+ mintInput: {
22
+ issuerPublicKey: tokenPublicKey,
23
+ issuerProvidedTimestamp: 100,
24
+ },
25
+ },
26
+ outputLeaves: [
27
+ {
28
+ id: "db1a4e48-0fc5-4f6c-8a80-d9d6c561a436",
29
+ ownerPublicKey: identityPubKey,
30
+ withdrawBondSats: 10000,
31
+ withdrawLocktime: 100,
32
+ tokenPublicKey: tokenPublicKey,
33
+ tokenAmount: numberToBytesBE(tokenAmount, 16),
34
+ revocationPublicKey: new Uint8Array(0),
35
+ },
36
+ ],
37
+ sparkOperatorIdentityPublicKeys: [],
38
+ };
39
+
40
+ const hash = hashTokenTransaction(tokenTransaction, false);
41
+
42
+ expect(Array.from(hash)).toEqual([
43
+ 169, 30, 146, 172, 90, 113, 89, 157, 142, 5, 138, 251, 237, 122, 65, 135,
44
+ 47, 178, 192, 116, 107, 24, 176, 162, 78, 238, 80, 166, 38, 129, 151, 167,
45
+ ]);
46
+ });
47
+ });
@@ -0,0 +1,371 @@
1
+ import { describe, expect, it } from "@jest/globals";
2
+ import {
3
+ bytesToHex,
4
+ equalBytes,
5
+ hexToBytes,
6
+ } from "@noble/curves/abstract/utils";
7
+ import { generateMnemonic } from "@scure/bip39";
8
+ import { wordlist } from "@scure/bip39/wordlists/english";
9
+ import { sha256 } from "@scure/btc-signer/utils";
10
+ import { WalletConfigService } from "../services/config.js";
11
+ import { ConnectionManager } from "../services/connection.js";
12
+ import { LeafKeyTweak, TransferService } from "../services/transfer.js";
13
+ import { ConfigOptions } from "../services/wallet-config.js";
14
+ import { createNewTree } from "./test-util.js";
15
+ import { SparkWalletTesting } from "./utils/spark-testing-wallet.js";
16
+ import { BitcoinFaucet } from "./utils/test-faucet.js";
17
+ describe("Transfer", () => {
18
+ // Skip all tests if running in GitHub Actions
19
+ const testFn = process.env.GITHUB_ACTIONS ? it.skip : it;
20
+
21
+ testFn(
22
+ "test transfer",
23
+ async () => {
24
+ const faucet = new BitcoinFaucet(
25
+ "http://127.0.0.1:18443",
26
+ "admin1",
27
+ "123",
28
+ );
29
+
30
+ const options: ConfigOptions = {
31
+ network: "LOCAL",
32
+ };
33
+
34
+ const { wallet: senderWallet } = await SparkWalletTesting.create({
35
+ options,
36
+ });
37
+
38
+ const senderConfigService = new WalletConfigService(
39
+ options,
40
+ senderWallet.getSigner(),
41
+ );
42
+ const senderConnectionManager = new ConnectionManager(
43
+ senderConfigService,
44
+ );
45
+ const senderTransferService = new TransferService(
46
+ senderConfigService,
47
+ senderConnectionManager,
48
+ );
49
+
50
+ const leafPubKey = await senderWallet.getSigner().generatePublicKey();
51
+ const rootNode = await createNewTree(
52
+ senderWallet,
53
+ leafPubKey,
54
+ faucet,
55
+ 1000n,
56
+ );
57
+
58
+ const newLeafPubKey = await senderWallet.getSigner().generatePublicKey();
59
+
60
+ const { wallet: receiverWallet } = await SparkWalletTesting.create({
61
+ options,
62
+ });
63
+ const receiverPubkey = await receiverWallet.getIdentityPublicKey();
64
+
65
+ const receiverConfigService = new WalletConfigService(
66
+ options,
67
+ receiverWallet.getSigner(),
68
+ );
69
+ const receiverConnectionManager = new ConnectionManager(
70
+ receiverConfigService,
71
+ );
72
+
73
+ const receiverTransferService = new TransferService(
74
+ receiverConfigService,
75
+ receiverConnectionManager,
76
+ );
77
+
78
+ const transferNode = {
79
+ leaf: rootNode,
80
+ signingPubKey: leafPubKey,
81
+ newSigningPubKey: newLeafPubKey,
82
+ };
83
+
84
+ const senderTransfer = await senderTransferService.sendTransfer(
85
+ [transferNode],
86
+ hexToBytes(receiverPubkey),
87
+ );
88
+
89
+ const pendingTransfer = await receiverWallet.queryPendingTransfers();
90
+
91
+ expect(pendingTransfer.transfers.length).toBe(1);
92
+
93
+ const receiverTransfer = pendingTransfer.transfers[0];
94
+
95
+ expect(receiverTransfer!.id).toBe(senderTransfer.id);
96
+
97
+ const leafPrivKeyMap = await receiverWallet.verifyPendingTransfer(
98
+ receiverTransfer!,
99
+ );
100
+
101
+ expect(leafPrivKeyMap.size).toBe(1);
102
+
103
+ const leafPrivKeyMapBytes = leafPrivKeyMap.get(rootNode.id);
104
+ expect(leafPrivKeyMapBytes).toBeDefined();
105
+ expect(bytesToHex(leafPrivKeyMapBytes!)).toBe(bytesToHex(newLeafPubKey));
106
+
107
+ const finalLeafPubKey = await receiverWallet
108
+ .getSigner()
109
+ .generatePublicKey(sha256(rootNode.id));
110
+
111
+ const claimingNode = {
112
+ leaf: rootNode,
113
+ signingPubKey: newLeafPubKey,
114
+ newSigningPubKey: finalLeafPubKey,
115
+ };
116
+
117
+ await receiverTransferService.claimTransfer(receiverTransfer!, [
118
+ claimingNode,
119
+ ]);
120
+
121
+ const { wallet: newReceiverWallet } = await SparkWalletTesting.create({
122
+ options: {
123
+ network: "LOCAL",
124
+ },
125
+ });
126
+ const newReceiverPubkey = await newReceiverWallet.getIdentityPublicKey();
127
+
128
+ await receiverWallet.transfer({
129
+ amountSats: 1000,
130
+ receiverSparkAddress: newReceiverPubkey,
131
+ });
132
+
133
+ const newPendingTransfer =
134
+ await newReceiverWallet.queryPendingTransfers();
135
+
136
+ expect(newPendingTransfer.transfers.length).toBe(1);
137
+ await newReceiverWallet.getBalance();
138
+ },
139
+ 30000,
140
+ );
141
+
142
+ testFn("test transfer with separate", async () => {
143
+ const faucet = new BitcoinFaucet("http://127.0.0.1:18443", "admin1", "123");
144
+
145
+ const options: ConfigOptions = {
146
+ network: "LOCAL",
147
+ };
148
+ const { wallet: senderWallet } = await SparkWalletTesting.create({
149
+ options,
150
+ });
151
+
152
+ const senderConfigService = new WalletConfigService(
153
+ options,
154
+ senderWallet.getSigner(),
155
+ );
156
+ const senderConnectionManager = new ConnectionManager(senderConfigService);
157
+ const senderTransferService = new TransferService(
158
+ senderConfigService,
159
+ senderConnectionManager,
160
+ );
161
+
162
+ const { wallet: receiverWallet } = await SparkWalletTesting.create({
163
+ options,
164
+ });
165
+ const receiverPubkey = await receiverWallet.getIdentityPublicKey();
166
+
167
+ const receiverConfigService = new WalletConfigService(
168
+ options,
169
+ receiverWallet.getSigner(),
170
+ );
171
+ const receiverConnectionManager = new ConnectionManager(
172
+ receiverConfigService,
173
+ );
174
+ const receiverTransferService = new TransferService(
175
+ receiverConfigService,
176
+ receiverConnectionManager,
177
+ );
178
+
179
+ const leafPubKey = await senderWallet.getSigner().generatePublicKey();
180
+
181
+ const rootNode = await createNewTree(
182
+ senderWallet,
183
+ leafPubKey,
184
+ faucet,
185
+ 100_000n,
186
+ );
187
+
188
+ const newLeafPubKey = await senderWallet.getSigner().generatePublicKey();
189
+
190
+ const transferNode: LeafKeyTweak = {
191
+ leaf: rootNode,
192
+ signingPubKey: leafPubKey,
193
+ newSigningPubKey: newLeafPubKey,
194
+ };
195
+
196
+ const leavesToTransfer = [transferNode];
197
+
198
+ const senderTransfer = await senderTransferService.sendTransfer(
199
+ leavesToTransfer,
200
+ hexToBytes(receiverPubkey),
201
+ );
202
+
203
+ // Receiver queries pending transfer
204
+ const pendingTransfer = await receiverWallet.queryPendingTransfers();
205
+
206
+ expect(pendingTransfer.transfers.length).toBe(1);
207
+
208
+ const receiverTransfer = pendingTransfer.transfers[0];
209
+
210
+ expect(receiverTransfer!.id).toBe(senderTransfer.id);
211
+
212
+ const leafPrivKeyMap = await receiverWallet.verifyPendingTransfer(
213
+ receiverTransfer!,
214
+ );
215
+
216
+ expect(leafPrivKeyMap.size).toBe(1);
217
+
218
+ const leafPrivKeyMapBytes = leafPrivKeyMap.get(rootNode.id);
219
+ expect(leafPrivKeyMapBytes).toBeDefined();
220
+ expect(equalBytes(leafPrivKeyMapBytes!, newLeafPubKey)).toBe(true);
221
+
222
+ const finalLeafPubKey = await receiverWallet
223
+ .getSigner()
224
+ .generatePublicKey(sha256(rootNode.id));
225
+
226
+ const claimingNode: LeafKeyTweak = {
227
+ leaf: receiverTransfer!.leaves[0]!.leaf!,
228
+ signingPubKey: newLeafPubKey,
229
+ newSigningPubKey: finalLeafPubKey,
230
+ };
231
+
232
+ const transferService = new TransferService(
233
+ receiverConfigService,
234
+ new ConnectionManager(receiverConfigService),
235
+ );
236
+
237
+ await transferService.claimTransferTweakKeys(receiverTransfer!, [
238
+ claimingNode,
239
+ ]);
240
+
241
+ const newPendingTransfer = await receiverWallet.queryPendingTransfers();
242
+
243
+ expect(newPendingTransfer.transfers.length).toBe(1);
244
+
245
+ const newReceiverTransfer = newPendingTransfer.transfers[0];
246
+ expect(newReceiverTransfer!.id).toBe(receiverTransfer!.id);
247
+
248
+ const newLeafPubKeyMap = await receiverWallet.verifyPendingTransfer(
249
+ newReceiverTransfer!,
250
+ );
251
+
252
+ expect(newLeafPubKeyMap.size).toBe(1);
253
+
254
+ const newLeafPubKeyMapBytes = newLeafPubKeyMap.get(rootNode.id);
255
+ expect(newLeafPubKeyMapBytes).toBeDefined();
256
+ expect(bytesToHex(newLeafPubKeyMapBytes!)).toBe(bytesToHex(newLeafPubKey));
257
+
258
+ await transferService.claimTransferSignRefunds(newReceiverTransfer!, [
259
+ claimingNode,
260
+ ]);
261
+
262
+ const newNewPendingTransfer = await receiverWallet.queryPendingTransfers();
263
+ expect(newNewPendingTransfer.transfers.length).toBe(1);
264
+
265
+ await receiverTransferService.claimTransfer(
266
+ newNewPendingTransfer.transfers[0]!,
267
+ [claimingNode],
268
+ );
269
+ });
270
+
271
+ testFn("cancel transfer", async () => {
272
+ const faucet = new BitcoinFaucet("http://127.0.0.1:18443", "admin1", "123");
273
+
274
+ const options: ConfigOptions = {
275
+ network: "LOCAL",
276
+ };
277
+ const { wallet: senderWallet } = await SparkWalletTesting.create({
278
+ options,
279
+ });
280
+ const mnemonic = generateMnemonic(wordlist);
281
+
282
+ const { wallet: receiverWallet } = await SparkWalletTesting.create({
283
+ options,
284
+ });
285
+ const receiverPubkey = await receiverWallet.getIdentityPublicKey();
286
+
287
+ const receiverConfigService = new WalletConfigService(
288
+ options,
289
+ receiverWallet.getSigner(),
290
+ );
291
+ const receiverConnectionManager = new ConnectionManager(
292
+ receiverConfigService,
293
+ );
294
+ const receiverTransferService = new TransferService(
295
+ receiverConfigService,
296
+ receiverConnectionManager,
297
+ );
298
+
299
+ const leafPubKey = await senderWallet.getSigner().generatePublicKey();
300
+ const rootNode = await createNewTree(
301
+ senderWallet,
302
+ leafPubKey,
303
+ faucet,
304
+ 100_000n,
305
+ );
306
+
307
+ const newLeafPubKey = await senderWallet.getSigner().generatePublicKey();
308
+
309
+ const transferNode: LeafKeyTweak = {
310
+ leaf: rootNode,
311
+ signingPubKey: leafPubKey,
312
+ newSigningPubKey: newLeafPubKey,
313
+ };
314
+
315
+ const senderConfigService = new WalletConfigService(
316
+ options,
317
+ senderWallet.getSigner(),
318
+ );
319
+ const senderConnectionManager = new ConnectionManager(senderConfigService);
320
+ const senderTransferService = new TransferService(
321
+ senderConfigService,
322
+ senderConnectionManager,
323
+ );
324
+
325
+ const senderTransfer = await senderTransferService.sendTransferSignRefund(
326
+ [transferNode],
327
+ hexToBytes(receiverPubkey),
328
+ new Date(Date.now() + 10 * 60 * 1000),
329
+ );
330
+
331
+ await senderTransferService.cancelSendTransfer(
332
+ senderTransfer.transfer,
333
+ senderConfigService.getCoordinatorAddress(),
334
+ );
335
+
336
+ const newSenderTransfer = await senderTransferService.sendTransfer(
337
+ [transferNode],
338
+ hexToBytes(receiverPubkey),
339
+ );
340
+
341
+ const pendingTransfer = await receiverWallet.queryPendingTransfers();
342
+ expect(pendingTransfer.transfers.length).toBe(1);
343
+
344
+ const receiverTransfer = pendingTransfer.transfers[0];
345
+ expect(receiverTransfer!.id).toBe(newSenderTransfer.id);
346
+
347
+ const leafPubKeyMap = await receiverWallet.verifyPendingTransfer(
348
+ receiverTransfer!,
349
+ );
350
+
351
+ expect(leafPubKeyMap.size).toBe(1);
352
+
353
+ const leafPubKeyMapBytes = leafPubKeyMap.get(rootNode.id);
354
+ expect(leafPubKeyMapBytes).toBeDefined();
355
+ expect(equalBytes(leafPubKeyMapBytes!, newLeafPubKey)).toBe(true);
356
+
357
+ const finalLeafPubKey = await receiverWallet
358
+ .getSigner()
359
+ .generatePublicKey(sha256(rootNode.id));
360
+
361
+ const claimingNode: LeafKeyTweak = {
362
+ leaf: receiverTransfer!.leaves[0]!.leaf!,
363
+ signingPubKey: newLeafPubKey,
364
+ newSigningPubKey: finalLeafPubKey,
365
+ };
366
+
367
+ await receiverTransferService.claimTransfer(receiverTransfer!, [
368
+ claimingNode,
369
+ ]);
370
+ });
371
+ });
@@ -0,0 +1,56 @@
1
+ // @ts-nocheck
2
+ import { describe, expect, it } from "@jest/globals";
3
+ import { bytesToHex } from "@noble/curves/abstract/utils";
4
+ import { getTxFromRawTxBytes, getTxId } from "../utils/bitcoin.js";
5
+ import { Network } from "../utils/network.js";
6
+ import { createDummyTx } from "../utils/wasm.js";
7
+ import { SparkWalletTesting } from "./utils/spark-testing-wallet.js";
8
+
9
+ describe("Tree Creation", () => {
10
+ // Skip all tests if running in GitHub Actions
11
+ const testFn = process.env.GITHUB_ACTIONS ? it.skip : xit;
12
+
13
+ testFn(
14
+ "test tree creation address generation",
15
+ async () => {
16
+ const wallet = new SparkWalletTesting(Network.LOCAL);
17
+ await wallet.initWallet();
18
+
19
+ const pubKey = await wallet.getSigner().generatePublicKey();
20
+
21
+ const depositResp = await wallet.generateDepositAddress();
22
+
23
+ expect(depositResp.depositAddress).toBeDefined();
24
+
25
+ const dummyTx = createDummyTx({
26
+ address: depositResp.depositAddress!.address,
27
+ amountSats: 65536n,
28
+ });
29
+
30
+ const depositTxHex = bytesToHex(dummyTx.tx);
31
+ const depositTx = getTxFromRawTxBytes(dummyTx.tx);
32
+
33
+ const vout = 0;
34
+ const txid = getTxId(depositTx);
35
+ if (!txid) {
36
+ throw new Error("txid not found");
37
+ }
38
+
39
+ const treeResp = await wallet.generateDepositAddressForTree(
40
+ vout,
41
+ pubKey,
42
+ depositTx,
43
+ );
44
+
45
+ const treeNodes = await wallet.createTree(
46
+ vout,
47
+ treeResp,
48
+ true,
49
+ depositTx,
50
+ );
51
+
52
+ console.log("tree nodes:", treeNodes);
53
+ },
54
+ 30000,
55
+ );
56
+ });
@@ -0,0 +1,37 @@
1
+ import { QueryPendingTransfersResponse, Transfer } from "../../proto/spark.js";
2
+ import { SparkSigner } from "../../signer/signer.js";
3
+ import { SparkWallet, SparkWalletProps } from "../../spark-sdk.js";
4
+
5
+ interface ISparkWalletTesting extends SparkWallet {
6
+ getSigner(): SparkSigner;
7
+ queryPendingTransfers(): Promise<QueryPendingTransfersResponse>;
8
+ verifyPendingTransfer(transfer: Transfer): Promise<Map<string, Uint8Array>>;
9
+ }
10
+
11
+ export class SparkWalletTesting
12
+ extends SparkWallet
13
+ implements ISparkWalletTesting
14
+ {
15
+ static async create(props: SparkWalletProps) {
16
+ const wallet = new SparkWalletTesting(props.options, props.signer);
17
+ const initResponse = await wallet.initWallet(props.mnemonicOrSeed);
18
+ return {
19
+ wallet,
20
+ mnemonic: initResponse?.mnemonic,
21
+ };
22
+ }
23
+
24
+ public getSigner(): SparkSigner {
25
+ return this.config.signer;
26
+ }
27
+
28
+ public async queryPendingTransfers(): Promise<QueryPendingTransfersResponse> {
29
+ return await this.transferService.queryPendingTransfers();
30
+ }
31
+
32
+ public async verifyPendingTransfer(
33
+ transfer: Transfer,
34
+ ): Promise<Map<string, Uint8Array>> {
35
+ return await this.transferService.verifyPendingTransfer(transfer);
36
+ }
37
+ }