@buildonspark/spark-sdk 0.2.3 → 0.2.5

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 (91) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{chunk-3SEOTO43.js → chunk-3SPMJMUX.js} +3 -2
  3. package/dist/{chunk-CDLETEDT.js → chunk-CQY5ML2A.js} +16 -3
  4. package/dist/{chunk-PTRXJS7Q.js → chunk-LQZL2D3Y.js} +1 -1
  5. package/dist/{chunk-PLLJIZC3.js → chunk-U7LRIWTF.js} +2471 -822
  6. package/dist/{client-CcYzmpmj.d.cts → client-C88GCTPB.d.cts} +211 -104
  7. package/dist/{client-CGTRS23n.d.ts → client-Dg6vS_2I.d.ts} +211 -104
  8. package/dist/debug.cjs +2511 -831
  9. package/dist/debug.d.cts +19 -6
  10. package/dist/debug.d.ts +19 -6
  11. package/dist/debug.js +3 -3
  12. package/dist/graphql/objects/index.cjs +13 -1
  13. package/dist/graphql/objects/index.d.cts +6 -51
  14. package/dist/graphql/objects/index.d.ts +6 -51
  15. package/dist/graphql/objects/index.js +1 -1
  16. package/dist/index.cjs +2491 -797
  17. package/dist/index.d.cts +189 -9
  18. package/dist/index.d.ts +189 -9
  19. package/dist/index.js +32 -4
  20. package/dist/index.node.cjs +2596 -799
  21. package/dist/index.node.d.cts +9 -190
  22. package/dist/index.node.d.ts +9 -190
  23. package/dist/index.node.js +134 -4
  24. package/dist/native/index.cjs +2491 -797
  25. package/dist/native/index.d.cts +309 -174
  26. package/dist/native/index.d.ts +309 -174
  27. package/dist/native/index.js +2495 -814
  28. package/dist/proto/lrc20.d.cts +1 -1
  29. package/dist/proto/lrc20.d.ts +1 -1
  30. package/dist/proto/spark.d.cts +1 -1
  31. package/dist/proto/spark.d.ts +1 -1
  32. package/dist/proto/spark_token.d.cts +1 -1
  33. package/dist/proto/spark_token.d.ts +1 -1
  34. package/dist/{spark-B_7nZx6T.d.cts → spark-ESAfZARg.d.cts} +1 -1
  35. package/dist/{spark-B_7nZx6T.d.ts → spark-ESAfZARg.d.ts} +1 -1
  36. package/dist/{spark-wallet-CxcGPXRB.d.ts → spark-wallet-B2WwKN8W.d.ts} +57 -35
  37. package/dist/{spark-wallet-DJJm19BP.d.cts → spark-wallet-Di65w0Us.d.cts} +57 -35
  38. package/dist/spark-wallet.node-7R0Rxyj9.d.cts +13 -0
  39. package/dist/spark-wallet.node-CSPWOWRu.d.ts +13 -0
  40. package/dist/tests/test-utils.cjs +578 -77
  41. package/dist/tests/test-utils.d.cts +12 -13
  42. package/dist/tests/test-utils.d.ts +12 -13
  43. package/dist/tests/test-utils.js +54 -17
  44. package/dist/types/index.cjs +16 -3
  45. package/dist/types/index.d.cts +3 -4
  46. package/dist/types/index.d.ts +3 -4
  47. package/dist/types/index.js +2 -2
  48. package/dist/{xchain-address-Bh9w1SeC.d.ts → xchain-address-BsveIy5l.d.ts} +56 -8
  49. package/dist/{xchain-address-SZ7dkVUE.d.cts → xchain-address-CqRu3F21.d.cts} +56 -8
  50. package/package.json +1 -1
  51. package/src/graphql/client.ts +57 -8
  52. package/src/graphql/mutations/CompleteLeavesSwap.ts +9 -1
  53. package/src/graphql/mutations/RequestSwapLeaves.ts +4 -0
  54. package/src/graphql/objects/CompleteLeavesSwapInput.ts +34 -34
  55. package/src/graphql/objects/LeavesSwapRequest.ts +4 -0
  56. package/src/graphql/objects/RequestLeavesSwapInput.ts +48 -47
  57. package/src/graphql/objects/SparkWalletUser.ts +1 -1
  58. package/src/graphql/objects/SwapLeaf.ts +40 -32
  59. package/src/graphql/objects/UserLeafInput.ts +24 -0
  60. package/src/graphql/objects/UserRequest.ts +4 -0
  61. package/src/graphql/queries/Transfers.ts +15 -0
  62. package/src/index.node.ts +1 -1
  63. package/src/native/index.ts +4 -5
  64. package/src/services/coop-exit.ts +171 -36
  65. package/src/services/deposit.ts +471 -74
  66. package/src/services/lightning.ts +18 -5
  67. package/src/services/signing.ts +162 -50
  68. package/src/services/transfer.ts +950 -384
  69. package/src/services/tree-creation.ts +342 -121
  70. package/src/spark-wallet/spark-wallet.node.ts +71 -66
  71. package/src/spark-wallet/spark-wallet.ts +561 -192
  72. package/src/tests/integration/coop-exit.test.ts +3 -8
  73. package/src/tests/integration/deposit.test.ts +3 -3
  74. package/src/tests/integration/lightning.test.ts +521 -466
  75. package/src/tests/integration/ssp/static_deposit.test.ts +83 -1
  76. package/src/tests/integration/ssp/transfers.test.ts +97 -0
  77. package/src/tests/integration/swap.test.ts +559 -307
  78. package/src/tests/integration/transfer.test.ts +625 -623
  79. package/src/tests/integration/wallet.test.ts +2 -2
  80. package/src/tests/integration/watchtower.test.ts +211 -0
  81. package/src/tests/test-utils.ts +63 -14
  82. package/src/tests/utils/test-faucet.ts +4 -2
  83. package/src/types/sdk-types.ts +15 -0
  84. package/src/utils/adaptor-signature.ts +15 -5
  85. package/src/utils/bitcoin.ts +13 -0
  86. package/src/utils/fetch.ts +75 -0
  87. package/src/utils/mempool.ts +9 -4
  88. package/src/utils/transaction.ts +388 -26
  89. package/dist/sdk-types-CB9HrW5O.d.cts +0 -44
  90. package/dist/sdk-types-CkRNraXT.d.ts +0 -44
  91. package/src/graphql/queries/Transfer.ts +0 -10
@@ -4,7 +4,11 @@ import { sha256 } from "@noble/hashes/sha2";
4
4
  import { equalBytes } from "@scure/btc-signer/utils";
5
5
  import { uuidv7 } from "uuidv7";
6
6
  import LightningReceiveRequest from "../../graphql/objects/LightningReceiveRequest.js";
7
- import { KeyDerivation, KeyDerivationType } from "../../index.js";
7
+ import {
8
+ getTxFromRawTxBytes,
9
+ KeyDerivation,
10
+ KeyDerivationType,
11
+ } from "../../index.js";
8
12
  import { TransferStatus } from "../../proto/spark.js";
9
13
  import { WalletConfigService } from "../../services/config.js";
10
14
  import { ConnectionManager } from "../../services/connection.js";
@@ -17,11 +21,7 @@ import {
17
21
  CurrencyUnit,
18
22
  LightningReceiveRequestStatus,
19
23
  } from "../../types/index.js";
20
- import {
21
- createNewTree,
22
- getTestWalletConfig,
23
- signerTypes,
24
- } from "../test-utils.js";
24
+ import { getTestWalletConfig, walletTypes } from "../test-utils.js";
25
25
  import { SparkWalletTesting } from "../utils/spark-testing-wallet.js";
26
26
  import { BitcoinFaucet } from "../utils/test-faucet.js";
27
27
 
@@ -72,483 +72,538 @@ const fakeInvoiceCreator = async (): Promise<LightningReceiveRequest> => {
72
72
  };
73
73
  };
74
74
 
75
- describe.each(signerTypes)("LightningService", ({ name, Signer }) => {
76
- let userWallet: SparkWalletTesting;
77
- let userConfig: WalletConfigService;
78
- let lightningService: LightningService;
79
- let transferService: TransferService;
80
- let signingService: SigningService;
81
-
82
- let sspWallet: SparkWalletTesting;
83
- let sspConfig: WalletConfigService;
84
- let sspLightningService: LightningService;
85
- let sspTransferService: TransferService;
86
- let sspSigningService: SigningService;
87
-
88
- beforeAll(async () => {
89
- const { wallet: wallet1 } = await SparkWalletTesting.initialize({
90
- options: {
91
- network: "LOCAL",
92
- },
93
- signer: new Signer(),
94
- });
95
-
96
- userWallet = wallet1;
97
-
98
- userConfig = new WalletConfigService(
99
- {
100
- network: "LOCAL",
101
- },
102
- userWallet.getSigner(),
103
- );
104
- const connectionManager = new ConnectionManager(userConfig);
105
- signingService = new SigningService(userConfig);
106
- lightningService = new LightningService(
107
- userConfig,
108
- connectionManager,
109
- signingService,
110
- );
111
- transferService = new TransferService(
112
- userConfig,
113
- connectionManager,
114
- signingService,
115
- );
116
-
117
- const { wallet: wallet2 } = await SparkWalletTesting.initialize({
118
- options: {
119
- network: "LOCAL",
120
- },
121
- signer: new Signer(),
122
- });
123
-
124
- sspWallet = wallet2;
125
-
126
- sspConfig = new WalletConfigService(
127
- {
128
- network: "LOCAL",
129
- },
130
- sspWallet.getSigner(),
131
- );
132
- const sspConnectionManager = new ConnectionManager(sspConfig);
133
- sspSigningService = new SigningService(sspConfig);
134
- sspLightningService = new LightningService(
135
- sspConfig,
136
- sspConnectionManager,
137
- sspSigningService,
138
- );
139
- sspTransferService = new TransferService(
140
- sspConfig,
141
- sspConnectionManager,
142
- sspSigningService,
143
- );
144
- });
145
- afterEach(async () => {
146
- await cleanUp();
147
- });
148
-
149
- it(`${name} - should create an invoice`, async () => {
150
- const preimage = hexToBytes(
151
- "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
152
- );
153
-
154
- const invoice = await lightningService.createLightningInvoiceWithPreImage({
155
- invoiceCreator: fakeInvoiceCreator,
156
- amountSats: 100,
157
- memo: "test",
158
- preimage,
159
- });
160
-
161
- expect(invoice).toBeDefined();
162
- });
163
-
164
- it(`${name} - test receive lightning payment`, async () => {
165
- const faucet = BitcoinFaucet.getInstance();
166
-
167
- const preimage = hexToBytes(
168
- "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
169
- );
170
- const paymentHash = sha256(preimage);
171
-
172
- const invoice = await lightningService.createLightningInvoiceWithPreImage({
173
- invoiceCreator: fakeInvoiceCreator,
174
- amountSats: 100,
175
- memo: "test",
176
- preimage,
177
- });
178
-
179
- expect(invoice).toBeDefined();
180
-
181
- const leafId = uuidv7();
182
- const nodeToSend = await createNewTree(sspWallet, leafId, faucet, 12345n);
183
-
184
- const newDerivationPath: KeyDerivation = {
185
- type: KeyDerivationType.LEAF,
186
- path: uuidv7(),
187
- };
188
-
189
- const leaves: LeafKeyTweak[] = [
190
- {
191
- leaf: nodeToSend,
192
- keyDerivation: {
193
- type: KeyDerivationType.LEAF,
194
- path: leafId,
75
+ describe.each(walletTypes)(
76
+ "LightningService",
77
+ ({ name, Signer, createTree }) => {
78
+ let userWallet: SparkWalletTesting;
79
+ let userConfig: WalletConfigService;
80
+ let lightningService: LightningService;
81
+ let transferService: TransferService;
82
+ let signingService: SigningService;
83
+
84
+ let sspWallet: SparkWalletTesting;
85
+ let sspConfig: WalletConfigService;
86
+ let sspLightningService: LightningService;
87
+ let sspTransferService: TransferService;
88
+ let sspSigningService: SigningService;
89
+
90
+ beforeAll(async () => {
91
+ const { wallet: wallet1 } = await SparkWalletTesting.initialize({
92
+ options: {
93
+ network: "LOCAL",
195
94
  },
196
- newKeyDerivation: newDerivationPath,
197
- },
198
- ];
199
-
200
- const response = await sspLightningService.swapNodesForPreimage({
201
- leaves,
202
- receiverIdentityPubkey: await userConfig.signer.getIdentityPublicKey(),
203
- paymentHash,
204
- isInboundPayment: true,
205
- });
206
-
207
- expect(equalBytes(response.preimage, preimage)).toBe(true);
208
-
209
- const senderTransfer = response.transfer;
210
-
211
- expect(senderTransfer).toBeDefined();
212
-
213
- const transfer = await sspTransferService.sendTransferTweakKey(
214
- senderTransfer!,
215
- leaves,
216
- new Map(),
217
- );
218
-
219
- expect(transfer.status).toEqual(
220
- TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
221
- );
222
-
223
- const pendingTransfer = await transferService.queryPendingTransfers();
224
-
225
- expect(pendingTransfer.transfers.length).toBe(1);
226
-
227
- const receiverTransfer = pendingTransfer.transfers[0];
228
-
229
- expect(receiverTransfer!.id).toEqual(senderTransfer!.id);
230
-
231
- const leafPrivKeyMap = await transferService.verifyPendingTransfer(
232
- receiverTransfer!,
233
- );
95
+ signer: new Signer(),
96
+ });
234
97
 
235
- expect(leafPrivKeyMap.size).toBe(1);
236
- expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
237
- expect(
238
- equalBytes(
239
- leafPrivKeyMap.get(nodeToSend.id)!,
240
- await sspConfig.signer.getPublicKeyFromDerivation(newDerivationPath),
241
- ),
242
- ).toBe(true);
98
+ userWallet = wallet1;
243
99
 
244
- const leaf = receiverTransfer!.leaves[0]!.leaf;
245
- expect(leaf).toBeDefined();
246
-
247
- const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
248
- (leaf) => ({
249
- leaf: leaf.leaf!,
250
- keyDerivation: {
251
- type: KeyDerivationType.ECIES,
252
- path: leaf.secretCipher,
100
+ userConfig = new WalletConfigService(
101
+ {
102
+ network: "LOCAL",
253
103
  },
254
- newKeyDerivation: {
255
- type: KeyDerivationType.LEAF,
256
- path: leaf.leaf!.id,
104
+ userWallet.getSigner(),
105
+ );
106
+ const connectionManager = new ConnectionManager(userConfig);
107
+ signingService = new SigningService(userConfig);
108
+ lightningService = new LightningService(
109
+ userConfig,
110
+ connectionManager,
111
+ signingService,
112
+ );
113
+ transferService = new TransferService(
114
+ userConfig,
115
+ connectionManager,
116
+ signingService,
117
+ );
118
+
119
+ const { wallet: wallet2 } = await SparkWalletTesting.initialize({
120
+ options: {
121
+ network: "LOCAL",
257
122
  },
258
- }),
259
- );
260
-
261
- await transferService.claimTransfer(receiverTransfer!, claimingNodes);
262
- }, 60000);
263
-
264
- it(`${name} - test receive lightning v2 payment`, async () => {
265
- const faucet = BitcoinFaucet.getInstance();
123
+ signer: new Signer(),
124
+ });
266
125
 
267
- const preimage = hexToBytes(
268
- "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
269
- );
270
- const paymentHash = sha256(preimage);
126
+ sspWallet = wallet2;
271
127
 
272
- const invoice = await lightningService.createLightningInvoiceWithPreImage({
273
- invoiceCreator: fakeInvoiceCreator,
274
- amountSats: 100,
275
- memo: "test",
276
- preimage,
128
+ sspConfig = new WalletConfigService(
129
+ {
130
+ network: "LOCAL",
131
+ },
132
+ sspWallet.getSigner(),
133
+ );
134
+ const sspConnectionManager = new ConnectionManager(sspConfig);
135
+ sspSigningService = new SigningService(sspConfig);
136
+ sspLightningService = new LightningService(
137
+ sspConfig,
138
+ sspConnectionManager,
139
+ sspSigningService,
140
+ );
141
+ sspTransferService = new TransferService(
142
+ sspConfig,
143
+ sspConnectionManager,
144
+ sspSigningService,
145
+ );
146
+ });
147
+ afterEach(async () => {
148
+ await cleanUp();
277
149
  });
278
150
 
279
- expect(invoice).toBeDefined();
280
-
281
- const leafId = uuidv7();
282
- const nodeToSend = await createNewTree(sspWallet, leafId, faucet, 12345n);
283
-
284
- const newKeyDerivation: KeyDerivation = {
285
- type: KeyDerivationType.LEAF,
286
- path: uuidv7(),
287
- };
288
- const leaves: LeafKeyTweak[] = [
289
- {
290
- leaf: nodeToSend,
291
- keyDerivation: {
292
- type: KeyDerivationType.LEAF,
293
- path: leafId,
151
+ it(`${name} - should create an invoice`, async () => {
152
+ const preimage = hexToBytes(
153
+ "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
154
+ );
155
+
156
+ const invoice = await lightningService.createLightningInvoiceWithPreImage(
157
+ {
158
+ invoiceCreator: fakeInvoiceCreator,
159
+ amountSats: 100,
160
+ memo: "test",
161
+ preimage,
294
162
  },
295
- newKeyDerivation,
296
- },
297
- ];
163
+ );
298
164
 
299
- const response = await sspLightningService.swapNodesForPreimage({
300
- leaves,
301
- receiverIdentityPubkey: await userConfig.signer.getIdentityPublicKey(),
302
- paymentHash,
303
- isInboundPayment: true,
165
+ expect(invoice).toBeDefined();
304
166
  });
305
167
 
306
- expect(equalBytes(response.preimage, preimage)).toBe(true);
307
-
308
- const senderTransfer = response.transfer;
309
-
310
- expect(senderTransfer).toBeDefined();
311
-
312
- const transfer = await sspTransferService.deliverTransferPackage(
313
- senderTransfer!,
314
- leaves,
315
- new Map(),
316
- );
317
-
318
- expect(transfer.status).toEqual(
319
- TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
320
- );
321
-
322
- const pendingTransfer = await transferService.queryPendingTransfers();
323
-
324
- expect(pendingTransfer.transfers.length).toBe(1);
325
-
326
- const receiverTransfer = pendingTransfer.transfers[0];
327
-
328
- expect(receiverTransfer!.id).toEqual(senderTransfer!.id);
329
-
330
- const leafPrivKeyMap = await transferService.verifyPendingTransfer(
331
- receiverTransfer!,
332
- );
333
-
334
- expect(leafPrivKeyMap.size).toBe(1);
335
- expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
336
- expect(
337
- equalBytes(
338
- leafPrivKeyMap.get(nodeToSend.id)!,
339
- await sspConfig.signer.getPublicKeyFromDerivation(newKeyDerivation),
340
- ),
341
- ).toBe(true);
168
+ it(`${name} - test receive lightning payment`, async () => {
169
+ const faucet = BitcoinFaucet.getInstance();
342
170
 
343
- const leaf = receiverTransfer!.leaves[0]!.leaf;
344
- expect(leaf).toBeDefined();
345
-
346
- const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
347
- (leaf) => ({
348
- leaf: leaf.leaf!,
349
- keyDerivation: {
350
- type: KeyDerivationType.ECIES,
351
- path: leaf.secretCipher,
352
- },
353
- newKeyDerivation: {
354
- type: KeyDerivationType.LEAF,
355
- path: leaf.leaf!.id,
356
- },
357
- }),
358
- );
359
-
360
- await transferService.claimTransfer(receiverTransfer!, claimingNodes);
361
- }, 60000);
362
-
363
- it(`${name} - test send lightning payment`, async () => {
364
- const faucet = BitcoinFaucet.getInstance();
365
-
366
- const preimage = hexToBytes(
367
- "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
368
- );
369
- const paymentHash = sha256(preimage);
370
-
371
- const leafId = uuidv7();
372
- const nodeToSend = await createNewTree(userWallet, leafId, faucet, 12345n);
373
-
374
- const newKeyDerivation: KeyDerivation = {
375
- type: KeyDerivationType.LEAF,
376
- path: uuidv7(),
377
- };
378
-
379
- const leaves: LeafKeyTweak[] = [
380
- {
381
- leaf: nodeToSend,
382
- keyDerivation: {
383
- type: KeyDerivationType.LEAF,
384
- path: leafId,
171
+ const preimage = hexToBytes(
172
+ "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
173
+ );
174
+ const paymentHash = sha256(preimage);
175
+
176
+ const invoice = await lightningService.createLightningInvoiceWithPreImage(
177
+ {
178
+ invoiceCreator: fakeInvoiceCreator,
179
+ amountSats: 100,
180
+ memo: "test",
181
+ preimage,
385
182
  },
386
- newKeyDerivation,
387
- },
388
- ];
389
-
390
- const response = await lightningService.swapNodesForPreimage({
391
- leaves,
392
- receiverIdentityPubkey: await sspConfig.signer.getIdentityPublicKey(),
393
- paymentHash,
394
- isInboundPayment: false,
395
- invoiceString: (await fakeInvoiceCreator()).invoice.encodedInvoice,
396
- });
397
-
398
- expect(response.transfer).toBeDefined();
399
-
400
- const transfer = await transferService.sendTransferTweakKey(
401
- response.transfer!,
402
- leaves,
403
- new Map(),
404
- );
405
-
406
- expect(transfer.status).toEqual(
407
- TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAK_PENDING,
408
- );
409
-
410
- const refunds =
411
- await sspLightningService.queryUserSignedRefunds(paymentHash);
412
-
413
- let totalValue = 0n;
414
- for (const refund of refunds) {
415
- const value = sspLightningService.validateUserSignedRefund(refund);
416
- totalValue += value;
417
- }
418
-
419
- expect(totalValue).toBe(12345n);
420
- const receiverTransfer =
421
- await sspLightningService.providePreimage(preimage);
422
-
423
- expect(receiverTransfer.status).toEqual(
424
- TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
425
- );
426
- expect(receiverTransfer.id).toEqual(transfer.id);
427
-
428
- const leafPrivKeyMap =
429
- await sspTransferService.verifyPendingTransfer(receiverTransfer);
430
-
431
- expect(leafPrivKeyMap.size).toBe(1);
432
- expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
433
- expect(
434
- equalBytes(
435
- leafPrivKeyMap.get(nodeToSend.id)!,
436
- await userConfig.signer.getPublicKeyFromDerivation(newKeyDerivation),
437
- ),
438
- ).toBe(true);
439
-
440
- expect(receiverTransfer.leaves[0]!.leaf).toBeDefined();
441
-
442
- const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
443
- (leaf) => ({
444
- leaf: leaf.leaf!,
445
- keyDerivation: {
446
- type: KeyDerivationType.ECIES,
447
- path: leaf.secretCipher,
183
+ );
184
+
185
+ expect(invoice).toBeDefined();
186
+
187
+ const leafId = uuidv7();
188
+ const nodeToSend = await createTree(sspWallet, leafId, faucet, 12345n);
189
+
190
+ const newDerivationPath: KeyDerivation = {
191
+ type: KeyDerivationType.LEAF,
192
+ path: uuidv7(),
193
+ };
194
+
195
+ const leaves: LeafKeyTweak[] = [
196
+ {
197
+ leaf: nodeToSend,
198
+ keyDerivation: {
199
+ type: KeyDerivationType.LEAF,
200
+ path: leafId,
201
+ },
202
+ newKeyDerivation: newDerivationPath,
448
203
  },
449
- newKeyDerivation: {
450
- type: KeyDerivationType.LEAF,
451
- path: leaf.leaf!.id,
204
+ ];
205
+
206
+ const response = await sspLightningService.swapNodesForPreimage({
207
+ leaves,
208
+ receiverIdentityPubkey: await userConfig.signer.getIdentityPublicKey(),
209
+ paymentHash,
210
+ isInboundPayment: true,
211
+ });
212
+
213
+ expect(equalBytes(response.preimage, preimage)).toBe(true);
214
+
215
+ const senderTransfer = response.transfer;
216
+
217
+ expect(senderTransfer).toBeDefined();
218
+
219
+ const transfer = await sspTransferService.sendTransferTweakKey(
220
+ senderTransfer!,
221
+ leaves,
222
+ new Map(),
223
+ new Map(),
224
+ new Map(),
225
+ );
226
+
227
+ expect(transfer.status).toEqual(
228
+ TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
229
+ );
230
+
231
+ const pendingTransfer = await transferService.queryPendingTransfers();
232
+
233
+ expect(pendingTransfer.transfers.length).toBe(1);
234
+
235
+ const receiverTransfer = pendingTransfer.transfers[0];
236
+
237
+ expect(receiverTransfer!.id).toEqual(senderTransfer!.id);
238
+
239
+ const leafPrivKeyMap = await transferService.verifyPendingTransfer(
240
+ receiverTransfer!,
241
+ );
242
+
243
+ expect(leafPrivKeyMap.size).toBe(1);
244
+ expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
245
+ expect(
246
+ equalBytes(
247
+ leafPrivKeyMap.get(nodeToSend.id)!,
248
+ await sspConfig.signer.getPublicKeyFromDerivation(newDerivationPath),
249
+ ),
250
+ ).toBe(true);
251
+
252
+ const leaf = receiverTransfer!.leaves[0]!.leaf;
253
+ expect(leaf).toBeDefined();
254
+
255
+ const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
256
+ (leaf) => ({
257
+ leaf: leaf.leaf!,
258
+ keyDerivation: {
259
+ type: KeyDerivationType.ECIES,
260
+ path: leaf.secretCipher,
261
+ },
262
+ newKeyDerivation: {
263
+ type: KeyDerivationType.LEAF,
264
+ path: leaf.leaf!.id,
265
+ },
266
+ }),
267
+ );
268
+
269
+ await transferService.claimTransfer(receiverTransfer!, claimingNodes);
270
+ }, 60000);
271
+
272
+ it(`${name} - test receive lightning v2 payment`, async () => {
273
+ const faucet = BitcoinFaucet.getInstance();
274
+
275
+ const preimage = hexToBytes(
276
+ "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
277
+ );
278
+ const paymentHash = sha256(preimage);
279
+
280
+ const invoice = await lightningService.createLightningInvoiceWithPreImage(
281
+ {
282
+ invoiceCreator: fakeInvoiceCreator,
283
+ amountSats: 100,
284
+ memo: "test",
285
+ preimage,
452
286
  },
453
- }),
454
- );
455
-
456
- await sspTransferService.claimTransfer(receiverTransfer, claimingNodes);
457
- }, 60000);
458
-
459
- it(`${name} - test send lightning v2 payment`, async () => {
460
- const faucet = BitcoinFaucet.getInstance();
461
-
462
- const preimage = hexToBytes(
463
- "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
464
- );
465
- const paymentHash = sha256(preimage);
466
-
467
- const leafId = uuidv7();
468
- const nodeToSend = await createNewTree(userWallet, leafId, faucet, 12345n);
469
-
470
- const newKeyDerivation: KeyDerivation = {
471
- type: KeyDerivationType.LEAF,
472
- path: uuidv7(),
473
- };
474
-
475
- const leaves: LeafKeyTweak[] = [
476
- {
477
- leaf: nodeToSend,
478
- keyDerivation: {
479
- type: KeyDerivationType.LEAF,
480
- path: leafId,
287
+ );
288
+
289
+ expect(invoice).toBeDefined();
290
+
291
+ const leafId = uuidv7();
292
+ const nodeToSend = await createTree(sspWallet, leafId, faucet, 12345n);
293
+
294
+ const newKeyDerivation: KeyDerivation = {
295
+ type: KeyDerivationType.LEAF,
296
+ path: uuidv7(),
297
+ };
298
+ const leaves: LeafKeyTweak[] = [
299
+ {
300
+ leaf: nodeToSend,
301
+ keyDerivation: {
302
+ type: KeyDerivationType.LEAF,
303
+ path: leafId,
304
+ },
305
+ newKeyDerivation,
481
306
  },
482
- newKeyDerivation,
483
- },
484
- ];
485
-
486
- const response = await lightningService.swapNodesForPreimage({
487
- leaves,
488
- receiverIdentityPubkey: await sspConfig.signer.getIdentityPublicKey(),
489
- paymentHash,
490
- isInboundPayment: false,
491
- invoiceString: (await fakeInvoiceCreator()).invoice.encodedInvoice,
492
- });
493
-
494
- expect(response.transfer).toBeDefined();
495
-
496
- const transfer = await transferService.deliverTransferPackage(
497
- response.transfer!,
498
- leaves,
499
- new Map(),
500
- );
501
-
502
- expect(transfer.status).toEqual(
503
- TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAK_PENDING,
504
- );
505
-
506
- const refunds =
507
- await sspLightningService.queryUserSignedRefunds(paymentHash);
508
-
509
- let totalValue = 0n;
510
- for (const refund of refunds) {
511
- const value = sspLightningService.validateUserSignedRefund(refund);
512
- totalValue += value;
513
- }
514
-
515
- expect(totalValue).toBe(12345n);
516
- const receiverTransfer =
517
- await sspLightningService.providePreimage(preimage);
518
-
519
- expect(receiverTransfer.status).toEqual(
520
- TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
521
- );
522
- expect(receiverTransfer.id).toEqual(transfer.id);
523
-
524
- const leafPrivKeyMap =
525
- await sspTransferService.verifyPendingTransfer(receiverTransfer);
526
-
527
- expect(leafPrivKeyMap.size).toBe(1);
528
- expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
529
- expect(
530
- equalBytes(
531
- leafPrivKeyMap.get(nodeToSend.id)!,
532
- await userConfig.signer.getPublicKeyFromDerivation(newKeyDerivation),
533
- ),
534
- ).toBe(true);
535
-
536
- expect(receiverTransfer.leaves[0]!.leaf).toBeDefined();
537
-
538
- const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
539
- (leaf) => ({
540
- leaf: leaf.leaf!,
541
- keyDerivation: {
542
- type: KeyDerivationType.ECIES,
543
- path: leaf.secretCipher,
307
+ ];
308
+
309
+ const response = await sspLightningService.swapNodesForPreimage({
310
+ leaves,
311
+ receiverIdentityPubkey: await userConfig.signer.getIdentityPublicKey(),
312
+ paymentHash,
313
+ isInboundPayment: true,
314
+ });
315
+
316
+ expect(equalBytes(response.preimage, preimage)).toBe(true);
317
+
318
+ const senderTransfer = response.transfer;
319
+
320
+ expect(senderTransfer).toBeDefined();
321
+
322
+ const transfer = await sspTransferService.deliverTransferPackage(
323
+ senderTransfer!,
324
+ leaves,
325
+ new Map(),
326
+ new Map(),
327
+ new Map(),
328
+ );
329
+
330
+ expect(transfer.status).toEqual(
331
+ TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
332
+ );
333
+
334
+ const pendingTransfer = await transferService.queryPendingTransfers();
335
+
336
+ expect(pendingTransfer.transfers.length).toBe(1);
337
+
338
+ const receiverTransfer = pendingTransfer.transfers[0];
339
+
340
+ expect(receiverTransfer!.id).toEqual(senderTransfer!.id);
341
+
342
+ const leafPrivKeyMap = await transferService.verifyPendingTransfer(
343
+ receiverTransfer!,
344
+ );
345
+
346
+ expect(leafPrivKeyMap.size).toBe(1);
347
+ expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
348
+ expect(
349
+ equalBytes(
350
+ leafPrivKeyMap.get(nodeToSend.id)!,
351
+ await sspConfig.signer.getPublicKeyFromDerivation(newKeyDerivation),
352
+ ),
353
+ ).toBe(true);
354
+
355
+ const leaf = receiverTransfer!.leaves[0]!.leaf;
356
+ expect(leaf).toBeDefined();
357
+
358
+ const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
359
+ (leaf) => ({
360
+ leaf: leaf.leaf!,
361
+ keyDerivation: {
362
+ type: KeyDerivationType.ECIES,
363
+ path: leaf.secretCipher,
364
+ },
365
+ newKeyDerivation: {
366
+ type: KeyDerivationType.LEAF,
367
+ path: leaf.leaf!.id,
368
+ },
369
+ }),
370
+ );
371
+
372
+ await transferService.claimTransfer(receiverTransfer!, claimingNodes);
373
+ }, 60000);
374
+
375
+ it(`${name} - test send lightning payment`, async () => {
376
+ const faucet = BitcoinFaucet.getInstance();
377
+
378
+ const preimage = hexToBytes(
379
+ "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
380
+ );
381
+ const paymentHash = sha256(preimage);
382
+
383
+ const leafId = uuidv7();
384
+ const nodeToSend = await createTree(userWallet, leafId, faucet, 12345n);
385
+
386
+ const newKeyDerivation: KeyDerivation = {
387
+ type: KeyDerivationType.LEAF,
388
+ path: uuidv7(),
389
+ };
390
+
391
+ const leaves: LeafKeyTweak[] = [
392
+ {
393
+ leaf: nodeToSend,
394
+ keyDerivation: {
395
+ type: KeyDerivationType.LEAF,
396
+ path: leafId,
397
+ },
398
+ newKeyDerivation,
544
399
  },
545
- newKeyDerivation: {
546
- type: KeyDerivationType.LEAF,
547
- path: leaf.leaf!.id,
400
+ ];
401
+
402
+ const response = await lightningService.swapNodesForPreimage({
403
+ leaves,
404
+ receiverIdentityPubkey: await sspConfig.signer.getIdentityPublicKey(),
405
+ paymentHash,
406
+ isInboundPayment: false,
407
+ invoiceString: (await fakeInvoiceCreator()).invoice.encodedInvoice,
408
+ });
409
+
410
+ expect(response.transfer).toBeDefined();
411
+
412
+ const transfer = await transferService.sendTransferTweakKey(
413
+ response.transfer!,
414
+ leaves,
415
+ new Map(),
416
+ new Map(),
417
+ new Map(),
418
+ );
419
+
420
+ expect(transfer.status).toEqual(
421
+ TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAK_PENDING,
422
+ );
423
+
424
+ const refunds =
425
+ await sspLightningService.queryUserSignedRefunds(paymentHash);
426
+
427
+ let expectedValue = 0n;
428
+ for (const leaf of transfer.leaves) {
429
+ const cpfpRefund = getTxFromRawTxBytes(leaf.leaf?.refundTx!);
430
+ expectedValue += cpfpRefund.getOutput(0)?.amount || 0n;
431
+
432
+ if ((leaf.leaf?.directRefundTx.length || 0) > 0) {
433
+ const directRefund = getTxFromRawTxBytes(leaf.leaf?.directRefundTx!);
434
+ expectedValue += directRefund.getOutput(0)?.amount || 0n;
435
+ }
436
+
437
+ if ((leaf.leaf?.directFromCpfpRefundTx.length || 0) > 0) {
438
+ const directFromCpfpRefund = getTxFromRawTxBytes(
439
+ leaf.leaf?.directFromCpfpRefundTx!,
440
+ );
441
+ expectedValue += directFromCpfpRefund.getOutput(0)?.amount || 0n;
442
+ }
443
+ }
444
+
445
+ let totalValue = 0n;
446
+ for (const refund of refunds) {
447
+ const value = sspLightningService.validateUserSignedRefund(refund);
448
+ totalValue += value;
449
+ }
450
+
451
+ expect(totalValue).toBe(expectedValue);
452
+ const receiverTransfer =
453
+ await sspLightningService.providePreimage(preimage);
454
+
455
+ expect(receiverTransfer.status).toEqual(
456
+ TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
457
+ );
458
+ expect(receiverTransfer.id).toEqual(transfer.id);
459
+
460
+ const leafPrivKeyMap =
461
+ await sspTransferService.verifyPendingTransfer(receiverTransfer);
462
+
463
+ expect(leafPrivKeyMap.size).toBe(1);
464
+ expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
465
+ expect(
466
+ equalBytes(
467
+ leafPrivKeyMap.get(nodeToSend.id)!,
468
+ await userConfig.signer.getPublicKeyFromDerivation(newKeyDerivation),
469
+ ),
470
+ ).toBe(true);
471
+
472
+ expect(receiverTransfer.leaves[0]!.leaf).toBeDefined();
473
+
474
+ const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
475
+ (leaf) => ({
476
+ leaf: leaf.leaf!,
477
+ keyDerivation: {
478
+ type: KeyDerivationType.ECIES,
479
+ path: leaf.secretCipher,
480
+ },
481
+ newKeyDerivation: {
482
+ type: KeyDerivationType.LEAF,
483
+ path: leaf.leaf!.id,
484
+ },
485
+ }),
486
+ );
487
+
488
+ await sspTransferService.claimTransfer(receiverTransfer, claimingNodes);
489
+ }, 60000);
490
+
491
+ it(`${name} - test send lightning v2 payment`, async () => {
492
+ const faucet = BitcoinFaucet.getInstance();
493
+
494
+ const preimage = hexToBytes(
495
+ "2d059c3ede82a107aa1452c0bea47759be3c5c6e5342be6a310f6c3a907d9f4c",
496
+ );
497
+ const paymentHash = sha256(preimage);
498
+
499
+ const leafId = uuidv7();
500
+ const nodeToSend = await createTree(userWallet, leafId, faucet, 12345n);
501
+
502
+ const newKeyDerivation: KeyDerivation = {
503
+ type: KeyDerivationType.LEAF,
504
+ path: uuidv7(),
505
+ };
506
+
507
+ const leaves: LeafKeyTweak[] = [
508
+ {
509
+ leaf: nodeToSend,
510
+ keyDerivation: {
511
+ type: KeyDerivationType.LEAF,
512
+ path: leafId,
513
+ },
514
+ newKeyDerivation,
548
515
  },
549
- }),
550
- );
551
-
552
- await sspTransferService.claimTransfer(receiverTransfer, claimingNodes);
553
- }, 60000);
554
- });
516
+ ];
517
+
518
+ const response = await lightningService.swapNodesForPreimage({
519
+ leaves,
520
+ receiverIdentityPubkey: await sspConfig.signer.getIdentityPublicKey(),
521
+ paymentHash,
522
+ isInboundPayment: false,
523
+ invoiceString: (await fakeInvoiceCreator()).invoice.encodedInvoice,
524
+ });
525
+
526
+ expect(response.transfer).toBeDefined();
527
+
528
+ const transfer = await transferService.deliverTransferPackage(
529
+ response.transfer!,
530
+ leaves,
531
+ new Map(),
532
+ new Map(),
533
+ new Map(),
534
+ );
535
+
536
+ expect(transfer.status).toEqual(
537
+ TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAK_PENDING,
538
+ );
539
+
540
+ const refunds =
541
+ await sspLightningService.queryUserSignedRefunds(paymentHash);
542
+
543
+ let expectedValue = 0n;
544
+ for (const leaf of transfer.leaves) {
545
+ const cpfpRefund = getTxFromRawTxBytes(leaf.intermediateRefundTx);
546
+ expectedValue += cpfpRefund.getOutput(0)?.amount || 0n;
547
+
548
+ if (leaf.intermediateDirectRefundTx.length > 0) {
549
+ const directRefund = getTxFromRawTxBytes(
550
+ leaf.intermediateDirectRefundTx,
551
+ );
552
+ expectedValue += directRefund.getOutput(0)?.amount || 0n;
553
+ }
554
+
555
+ if (leaf.intermediateDirectFromCpfpRefundTx.length > 0) {
556
+ const directFromCpfpRefund = getTxFromRawTxBytes(
557
+ leaf.intermediateDirectFromCpfpRefundTx,
558
+ );
559
+ expectedValue += directFromCpfpRefund.getOutput(0)?.amount || 0n;
560
+ }
561
+ }
562
+
563
+ let totalValue = 0n;
564
+ for (const refund of refunds) {
565
+ const value = sspLightningService.validateUserSignedRefund(refund);
566
+ totalValue += value;
567
+ }
568
+
569
+ expect(totalValue).toBe(expectedValue);
570
+ const receiverTransfer =
571
+ await sspLightningService.providePreimage(preimage);
572
+
573
+ expect(receiverTransfer.status).toEqual(
574
+ TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED,
575
+ );
576
+ expect(receiverTransfer.id).toEqual(transfer.id);
577
+
578
+ const leafPrivKeyMap =
579
+ await sspTransferService.verifyPendingTransfer(receiverTransfer);
580
+
581
+ expect(leafPrivKeyMap.size).toBe(1);
582
+ expect(leafPrivKeyMap.has(nodeToSend.id)).toBe(true);
583
+ expect(
584
+ equalBytes(
585
+ leafPrivKeyMap.get(nodeToSend.id)!,
586
+ await userConfig.signer.getPublicKeyFromDerivation(newKeyDerivation),
587
+ ),
588
+ ).toBe(true);
589
+
590
+ expect(receiverTransfer.leaves[0]!.leaf).toBeDefined();
591
+
592
+ const claimingNodes: LeafKeyTweak[] = receiverTransfer!.leaves.map(
593
+ (leaf) => ({
594
+ leaf: leaf.leaf!,
595
+ keyDerivation: {
596
+ type: KeyDerivationType.ECIES,
597
+ path: leaf.secretCipher,
598
+ },
599
+ newKeyDerivation: {
600
+ type: KeyDerivationType.LEAF,
601
+ path: leaf.leaf!.id,
602
+ },
603
+ }),
604
+ );
605
+
606
+ await sspTransferService.claimTransfer(receiverTransfer, claimingNodes);
607
+ }, 60000);
608
+ },
609
+ );