@buildonspark/spark-sdk 0.2.2 → 0.2.4

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 (94) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/{chunk-TM6CHQXC.js → chunk-3SEOTO43.js} +1 -1
  3. package/dist/{chunk-2ENZX6LT.js → chunk-AAZWSPUK.js} +84 -8
  4. package/dist/{chunk-4JD4HIAN.js → chunk-G4MSZ6DE.js} +299 -1
  5. package/dist/{chunk-S2AL73MZ.js → chunk-TVUMSHWA.js} +1 -1
  6. package/dist/{chunk-2TUM3R6C.js → chunk-W4ZRBSWM.js} +2351 -797
  7. package/dist/{chunk-CDLETEDT.js → chunk-WAQKYSDI.js} +13 -1
  8. package/dist/{client-CGTRS23n.d.ts → client-BF4cn8F4.d.ts} +15 -3
  9. package/dist/{client-CcYzmpmj.d.cts → client-KhNkrXz4.d.cts} +15 -3
  10. package/dist/debug.cjs +2948 -1023
  11. package/dist/debug.d.cts +19 -6
  12. package/dist/debug.d.ts +19 -6
  13. package/dist/debug.js +5 -5
  14. package/dist/graphql/objects/index.cjs +13 -1
  15. package/dist/graphql/objects/index.d.cts +2 -2
  16. package/dist/graphql/objects/index.d.ts +2 -2
  17. package/dist/graphql/objects/index.js +1 -1
  18. package/dist/index.cjs +2794 -858
  19. package/dist/index.d.cts +190 -9
  20. package/dist/index.d.ts +190 -9
  21. package/dist/index.js +32 -6
  22. package/dist/index.node.cjs +2931 -892
  23. package/dist/index.node.d.cts +10 -188
  24. package/dist/index.node.d.ts +10 -188
  25. package/dist/index.node.js +134 -6
  26. package/dist/native/index.cjs +2794 -858
  27. package/dist/native/index.d.cts +148 -40
  28. package/dist/native/index.d.ts +148 -40
  29. package/dist/native/index.js +2799 -877
  30. package/dist/proto/lrc20.d.cts +1 -1
  31. package/dist/proto/lrc20.d.ts +1 -1
  32. package/dist/proto/lrc20.js +1 -1
  33. package/dist/proto/spark.cjs +84 -8
  34. package/dist/proto/spark.d.cts +1 -1
  35. package/dist/proto/spark.d.ts +1 -1
  36. package/dist/proto/spark.js +1 -1
  37. package/dist/proto/spark_token.cjs +301 -0
  38. package/dist/proto/spark_token.d.cts +35 -2
  39. package/dist/proto/spark_token.d.ts +35 -2
  40. package/dist/proto/spark_token.js +8 -2
  41. package/dist/{sdk-types-DJ2ve9YY.d.cts → sdk-types-CB9HrW5O.d.cts} +1 -1
  42. package/dist/{sdk-types-DCIVdKUT.d.ts → sdk-types-CkRNraXT.d.ts} +1 -1
  43. package/dist/{spark-BUOx3U7Q.d.cts → spark-B_7nZx6T.d.cts} +112 -10
  44. package/dist/{spark-BUOx3U7Q.d.ts → spark-B_7nZx6T.d.ts} +112 -10
  45. package/dist/{spark-wallet-B_96y9BS.d.ts → spark-wallet-C1Tr_VKI.d.ts} +38 -28
  46. package/dist/{spark-wallet-CHwKQYJu.d.cts → spark-wallet-DG3x2obf.d.cts} +38 -28
  47. package/dist/spark-wallet.node-CGxoeCpH.d.ts +13 -0
  48. package/dist/spark-wallet.node-CN9LoB_O.d.cts +13 -0
  49. package/dist/tests/test-utils.cjs +1086 -218
  50. package/dist/tests/test-utils.d.cts +13 -13
  51. package/dist/tests/test-utils.d.ts +13 -13
  52. package/dist/tests/test-utils.js +56 -19
  53. package/dist/types/index.cjs +97 -9
  54. package/dist/types/index.d.cts +3 -3
  55. package/dist/types/index.d.ts +3 -3
  56. package/dist/types/index.js +3 -3
  57. package/dist/{xchain-address-D5MIHCDL.d.cts → xchain-address-BHu6CpZC.d.ts} +55 -8
  58. package/dist/{xchain-address-DLbW1iDh.d.ts → xchain-address-HBr6isnc.d.cts} +55 -8
  59. package/package.json +1 -1
  60. package/src/graphql/client.ts +8 -0
  61. package/src/graphql/mutations/CompleteLeavesSwap.ts +9 -1
  62. package/src/graphql/mutations/RequestSwapLeaves.ts +4 -0
  63. package/src/graphql/objects/CompleteLeavesSwapInput.ts +34 -34
  64. package/src/graphql/objects/LeavesSwapRequest.ts +4 -0
  65. package/src/graphql/objects/RequestLeavesSwapInput.ts +48 -47
  66. package/src/graphql/objects/SwapLeaf.ts +40 -32
  67. package/src/graphql/objects/UserLeafInput.ts +24 -0
  68. package/src/graphql/objects/UserRequest.ts +4 -0
  69. package/src/index.node.ts +1 -1
  70. package/src/native/index.ts +4 -5
  71. package/src/proto/spark.ts +172 -16
  72. package/src/proto/spark_token.ts +369 -0
  73. package/src/services/coop-exit.ts +171 -36
  74. package/src/services/deposit.ts +471 -74
  75. package/src/services/lightning.ts +18 -5
  76. package/src/services/signing.ts +162 -50
  77. package/src/services/token-transactions.ts +6 -2
  78. package/src/services/transfer.ts +950 -384
  79. package/src/services/tree-creation.ts +342 -121
  80. package/src/spark-wallet/spark-wallet.node.ts +71 -66
  81. package/src/spark-wallet/spark-wallet.ts +459 -166
  82. package/src/tests/integration/coop-exit.test.ts +3 -8
  83. package/src/tests/integration/deposit.test.ts +3 -3
  84. package/src/tests/integration/lightning.test.ts +521 -466
  85. package/src/tests/integration/swap.test.ts +559 -307
  86. package/src/tests/integration/transfer.test.ts +625 -623
  87. package/src/tests/integration/wallet.test.ts +2 -2
  88. package/src/tests/integration/watchtower.test.ts +211 -0
  89. package/src/tests/test-utils.ts +63 -14
  90. package/src/tests/utils/test-faucet.ts +4 -2
  91. package/src/utils/adaptor-signature.ts +15 -5
  92. package/src/utils/fetch.ts +75 -0
  93. package/src/utils/mempool.ts +9 -4
  94. package/src/utils/transaction.ts +388 -26
@@ -12,7 +12,10 @@ import {
12
12
  getTxFromRawTxBytes,
13
13
  } from "../utils/bitcoin.js";
14
14
  import { Network } from "../utils/network.js";
15
- import { getNextTransactionSequence } from "../utils/transaction.js";
15
+ import {
16
+ getNextTransactionSequence,
17
+ maybeApplyFee,
18
+ } from "../utils/transaction.js";
16
19
  import { WalletConfigService } from "./config.js";
17
20
  import { ConnectionManager } from "./connection.js";
18
21
  import { SigningService } from "./signing.js";
@@ -43,8 +46,15 @@ export class CoopExitService extends BaseTransferService {
43
46
  }: GetConnectorRefundSignaturesParams): Promise<{
44
47
  transfer: Transfer;
45
48
  signaturesMap: Map<string, Uint8Array>;
49
+ directSignaturesMap: Map<string, Uint8Array>;
50
+ directFromCpfpSignaturesMap: Map<string, Uint8Array>;
46
51
  }> {
47
- const { transfer, signaturesMap } = await this.signCoopExitRefunds(
52
+ const {
53
+ transfer,
54
+ signaturesMap,
55
+ directSignaturesMap,
56
+ directFromCpfpSignaturesMap,
57
+ } = await this.signCoopExitRefunds(
48
58
  leaves,
49
59
  exitTxId,
50
60
  connectorOutputs,
@@ -55,51 +65,116 @@ export class CoopExitService extends BaseTransferService {
55
65
  transfer,
56
66
  leaves,
57
67
  signaturesMap,
68
+ directSignaturesMap,
69
+ directFromCpfpSignaturesMap,
58
70
  );
59
71
 
60
- return { transfer: transferTweak, signaturesMap };
72
+ return {
73
+ transfer: transferTweak,
74
+ signaturesMap,
75
+ directSignaturesMap,
76
+ directFromCpfpSignaturesMap,
77
+ };
61
78
  }
62
79
 
63
- private createConnectorRefundTransaction(
80
+ private createConnectorRefundTransactions(
64
81
  sequence: number,
65
- nodeOutPoint: TransactionInput,
82
+ directSequence: number,
83
+ cpfpNodeOutPoint: TransactionInput,
84
+ directNodeOutPoint: TransactionInput | undefined,
66
85
  connectorOutput: TransactionInput,
67
86
  amountSats: bigint,
68
87
  receiverPubKey: Uint8Array,
69
- ): Transaction {
70
- const refundTx = new Transaction();
71
- if (!nodeOutPoint.txid || nodeOutPoint.index === undefined) {
72
- throw new ValidationError("Invalid node outpoint", {
73
- field: "nodeOutPoint",
74
- value: { txid: nodeOutPoint.txid, index: nodeOutPoint.index },
88
+ ): {
89
+ cpfpRefundTx: Transaction;
90
+ directRefundTx?: Transaction;
91
+ directFromCpfpRefundTx?: Transaction;
92
+ } {
93
+ // Create CPFP refund transaction
94
+ const cpfpRefundTx = new Transaction();
95
+ if (!cpfpNodeOutPoint.txid || cpfpNodeOutPoint.index === undefined) {
96
+ throw new ValidationError("Invalid CPFP node outpoint", {
97
+ field: "cpfpNodeOutPoint",
98
+ value: { txid: cpfpNodeOutPoint.txid, index: cpfpNodeOutPoint.index },
75
99
  expected: "Both txid and index must be defined",
76
100
  });
77
101
  }
78
- refundTx.addInput({
79
- txid: nodeOutPoint.txid,
80
- index: nodeOutPoint.index,
102
+ cpfpRefundTx.addInput({
103
+ txid: cpfpNodeOutPoint.txid,
104
+ index: cpfpNodeOutPoint.index,
81
105
  sequence,
82
106
  });
83
107
 
84
- refundTx.addInput(connectorOutput);
108
+ cpfpRefundTx.addInput(connectorOutput);
85
109
  const receiverScript = getP2TRScriptFromPublicKey(
86
110
  receiverPubKey,
87
111
  this.config.getNetwork(),
88
112
  );
89
113
 
90
- refundTx.addOutput({
114
+ cpfpRefundTx.addOutput({
91
115
  script: receiverScript,
92
116
  amount: amountSats,
93
117
  });
94
118
 
95
- return refundTx;
119
+ // Create direct refund transaction
120
+ let directRefundTx: Transaction | undefined;
121
+ let directFromCpfpRefundTx: Transaction | undefined;
122
+ if (directNodeOutPoint) {
123
+ if (!directNodeOutPoint.txid || directNodeOutPoint.index === undefined) {
124
+ throw new ValidationError("Invalid direct node outpoint", {
125
+ field: "directNodeOutPoint",
126
+ value: {
127
+ txid: directNodeOutPoint.txid,
128
+ index: directNodeOutPoint.index,
129
+ },
130
+ expected: "Both txid and index must be defined",
131
+ });
132
+ }
133
+ directRefundTx = new Transaction();
134
+ directRefundTx.addInput({
135
+ txid: directNodeOutPoint.txid,
136
+ index: directNodeOutPoint.index,
137
+ sequence: directSequence,
138
+ });
139
+
140
+ directRefundTx.addInput(connectorOutput);
141
+ directRefundTx.addOutput({
142
+ script: receiverScript,
143
+ amount: maybeApplyFee(amountSats),
144
+ });
145
+
146
+ directFromCpfpRefundTx = new Transaction();
147
+ directFromCpfpRefundTx.addInput({
148
+ txid: cpfpNodeOutPoint.txid,
149
+ index: cpfpNodeOutPoint.index,
150
+ sequence: directSequence,
151
+ });
152
+
153
+ directFromCpfpRefundTx.addInput(connectorOutput);
154
+ directFromCpfpRefundTx.addOutput({
155
+ script: receiverScript,
156
+ amount: maybeApplyFee(amountSats),
157
+ });
158
+ }
159
+
160
+ return {
161
+ cpfpRefundTx,
162
+ directRefundTx,
163
+ directFromCpfpRefundTx,
164
+ };
96
165
  }
166
+
97
167
  private async signCoopExitRefunds(
98
168
  leaves: LeafKeyTweak[],
99
169
  exitTxId: Uint8Array,
100
170
  connectorOutputs: TransactionInput[],
101
171
  receiverPubKey: Uint8Array,
102
- ): Promise<{ transfer: Transfer; signaturesMap: Map<string, Uint8Array> }> {
172
+ ): Promise<{
173
+ transfer: Transfer;
174
+ signaturesMap: Map<string, Uint8Array>;
175
+ directSignaturesMap: Map<string, Uint8Array>;
176
+ directFromCpfpSignaturesMap: Map<string, Uint8Array>;
177
+ }> {
103
178
  if (leaves.length !== connectorOutputs.length) {
104
179
  throw new ValidationError(
105
180
  "Mismatch between leaves and connector outputs",
@@ -136,43 +211,88 @@ export class CoopExitService extends BaseTransferService {
136
211
  }
137
212
  const currentRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
138
213
 
139
- const { nextSequence } = getNextTransactionSequence(
140
- currentRefundTx.getInput(0).sequence,
141
- );
214
+ const sequence = currentRefundTx.getInput(0).sequence;
215
+ if (!sequence) {
216
+ throw new ValidationError("Invalid refund transaction", {
217
+ field: "sequence",
218
+ value: currentRefundTx.getInput(0),
219
+ expected: "Non-null sequence",
220
+ });
221
+ }
222
+ const { nextSequence, nextDirectSequence } =
223
+ getNextTransactionSequence(sequence);
142
224
 
143
- const refundTx = this.createConnectorRefundTransaction(
144
- nextSequence,
145
- currentRefundTx.getInput(0),
146
- connectorOutput,
147
- BigInt(leaf.leaf.value),
148
- receiverPubKey,
149
- );
225
+ let currentDirectRefundTx: Transaction | undefined;
226
+ if (leaf.leaf.directRefundTx.length > 0) {
227
+ currentDirectRefundTx = getTxFromRawTxBytes(leaf.leaf.directRefundTx);
228
+ }
229
+
230
+ const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
231
+ this.createConnectorRefundTransactions(
232
+ nextSequence,
233
+ nextDirectSequence,
234
+ currentRefundTx.getInput(0),
235
+ currentDirectRefundTx?.getInput(0),
236
+ connectorOutput,
237
+ BigInt(leaf.leaf.value),
238
+ receiverPubKey,
239
+ );
150
240
 
151
241
  const signingNonceCommitment =
152
242
  await this.config.signer.getRandomSigningCommitment();
243
+ const directSigningNonceCommitment =
244
+ await this.config.signer.getRandomSigningCommitment();
245
+ const directFromCpfpSigningNonceCommitment =
246
+ await this.config.signer.getRandomSigningCommitment();
247
+ const signingPublicKey =
248
+ await this.config.signer.getPublicKeyFromDerivation(leaf.keyDerivation);
249
+
153
250
  const signingJob: LeafRefundTxSigningJob = {
154
251
  leafId: leaf.leaf.id,
155
252
  refundTxSigningJob: {
156
253
  signingPublicKey: await this.config.signer.getPublicKeyFromDerivation(
157
254
  leaf.keyDerivation,
158
255
  ),
159
- rawTx: refundTx.toBytes(),
256
+ rawTx: cpfpRefundTx.toBytes(),
160
257
  signingNonceCommitment: signingNonceCommitment.commitment,
161
258
  },
162
- // TODO: Add direct refund signature
163
- directRefundTxSigningJob: undefined,
164
- directFromCpfpRefundTxSigningJob: undefined,
259
+ directRefundTxSigningJob: directRefundTx
260
+ ? {
261
+ signingPublicKey,
262
+ rawTx: directRefundTx.toBytes(),
263
+ signingNonceCommitment: directSigningNonceCommitment.commitment,
264
+ }
265
+ : undefined,
266
+ directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx
267
+ ? {
268
+ signingPublicKey,
269
+ rawTx: directFromCpfpRefundTx.toBytes(),
270
+ signingNonceCommitment:
271
+ directFromCpfpSigningNonceCommitment.commitment,
272
+ }
273
+ : undefined,
165
274
  };
166
275
 
167
276
  signingJobs.push(signingJob);
168
277
  const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
278
+ const directTx =
279
+ leaf.leaf.directTx.length > 0
280
+ ? getTxFromRawTxBytes(leaf.leaf.directTx)
281
+ : undefined;
282
+
169
283
  leafDataMap.set(leaf.leaf.id, {
170
284
  keyDerivation: leaf.keyDerivation,
171
- refundTx,
285
+ receivingPubkey: receiverPubKey,
172
286
  signingNonceCommitment,
287
+ directSigningNonceCommitment,
173
288
  tx,
289
+ directTx,
290
+ refundTx: cpfpRefundTx,
291
+ directRefundTx: directRefundTx,
292
+ directFromCpfpRefundTx: directFromCpfpRefundTx,
293
+ directFromCpfpRefundSigningNonceCommitment:
294
+ directFromCpfpSigningNonceCommitment,
174
295
  vout: leaf.leaf.vout,
175
- receivingPubkey: receiverPubKey,
176
296
  });
177
297
  }
178
298
 
@@ -182,7 +302,7 @@ export class CoopExitService extends BaseTransferService {
182
302
 
183
303
  let response: CooperativeExitResponse;
184
304
  try {
185
- response = await sparkClient.cooperative_exit({
305
+ response = await sparkClient.cooperative_exit_v2({
186
306
  transfer: {
187
307
  transferId: uuidv7(),
188
308
  leavesToSend: signingJobs,
@@ -222,10 +342,25 @@ export class CoopExitService extends BaseTransferService {
222
342
  );
223
343
 
224
344
  const signaturesMap: Map<string, Uint8Array> = new Map();
345
+ const directSignaturesMap: Map<string, Uint8Array> = new Map();
346
+ const directFromCpfpSignaturesMap: Map<string, Uint8Array> = new Map();
225
347
  for (const signature of signatures) {
226
348
  signaturesMap.set(signature.nodeId, signature.refundTxSignature);
349
+ directSignaturesMap.set(
350
+ signature.nodeId,
351
+ signature.directRefundTxSignature,
352
+ );
353
+ directFromCpfpSignaturesMap.set(
354
+ signature.nodeId,
355
+ signature.directFromCpfpRefundTxSignature,
356
+ );
227
357
  }
228
358
 
229
- return { transfer: response.transfer, signaturesMap };
359
+ return {
360
+ transfer: response.transfer,
361
+ signaturesMap,
362
+ directSignaturesMap,
363
+ directFromCpfpSignaturesMap,
364
+ };
230
365
  }
231
366
  }