@buildonspark/spark-sdk 0.1.43 → 0.1.45

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 (153) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/{RequestLightningSendInput-D7fZdT4A.d.ts → RequestLightningSendInput-DEPd_fPO.d.ts} +43 -4
  3. package/dist/{RequestLightningSendInput-Na1mHdWg.d.cts → RequestLightningSendInput-Du0z7Om7.d.cts} +43 -4
  4. package/dist/address/index.cjs +2 -2
  5. package/dist/address/index.d.cts +2 -2
  6. package/dist/address/index.d.ts +2 -2
  7. package/dist/address/index.js +2 -2
  8. package/dist/{chunk-IRW5TWMH.js → chunk-5FUB65LX.js} +7 -9
  9. package/dist/{chunk-BUTZWYBW.js → chunk-6264CGDM.js} +4 -4
  10. package/dist/{chunk-VFJQNBFX.js → chunk-7V6N75CC.js} +5 -2
  11. package/dist/{chunk-M6A4KFIG.js → chunk-BGGEVUJK.js} +1505 -445
  12. package/dist/{chunk-DQYKQJRZ.js → chunk-C2S227QR.js} +675 -52
  13. package/dist/{chunk-GYQR4B4P.js → chunk-GZ5IPPJ2.js} +2 -2
  14. package/dist/{chunk-6AFUC5M2.js → chunk-HWJWKEIU.js} +8 -2
  15. package/dist/{chunk-TOSP3INR.js → chunk-I54FARY2.js} +4 -2
  16. package/dist/{chunk-WWOTVNPP.js → chunk-J2IE4Z7Y.js} +544 -431
  17. package/dist/{chunk-O4RYNJNB.js → chunk-KMUMFYFX.js} +3 -3
  18. package/dist/chunk-LHRD2WT6.js +2374 -0
  19. package/dist/{chunk-ABZA6R5S.js → chunk-NTFKFRQ2.js} +1 -1
  20. package/dist/{chunk-MIVX3GHD.js → chunk-OBFKIEMP.js} +1 -1
  21. package/dist/{chunk-HRQRRDSS.js → chunk-PQN3C2MF.js} +15 -15
  22. package/dist/{chunk-DOA6QXYQ.js → chunk-R5PXJZQS.js} +3 -1
  23. package/dist/{chunk-TIUBYNN5.js → chunk-YUPMXTCJ.js} +4 -4
  24. package/dist/graphql/objects/index.d.cts +6 -43
  25. package/dist/graphql/objects/index.d.ts +6 -43
  26. package/dist/graphql/objects/index.js +1 -1
  27. package/dist/index-B2AwKW5J.d.cts +214 -0
  28. package/dist/index-CJDi1HWc.d.ts +214 -0
  29. package/dist/index.cjs +4150 -1026
  30. package/dist/index.d.cts +764 -19
  31. package/dist/index.d.ts +764 -19
  32. package/dist/index.js +17 -21
  33. package/dist/index.node.cjs +4153 -1033
  34. package/dist/index.node.d.cts +10 -8
  35. package/dist/index.node.d.ts +10 -8
  36. package/dist/index.node.js +20 -28
  37. package/dist/native/index.cjs +4166 -1042
  38. package/dist/native/index.d.cts +369 -108
  39. package/dist/native/index.d.ts +369 -108
  40. package/dist/native/index.js +4138 -1015
  41. package/dist/{network-xkBSpaTn.d.ts → network-BTJl-Sul.d.ts} +1 -1
  42. package/dist/{network-D5lKssVl.d.cts → network-CqgsdUF2.d.cts} +1 -1
  43. package/dist/proto/lrc20.cjs +222 -19
  44. package/dist/proto/lrc20.d.cts +1 -1
  45. package/dist/proto/lrc20.d.ts +1 -1
  46. package/dist/proto/lrc20.js +2 -2
  47. package/dist/proto/spark.cjs +1502 -442
  48. package/dist/proto/spark.d.cts +1 -1
  49. package/dist/proto/spark.d.ts +1 -1
  50. package/dist/proto/spark.js +5 -5
  51. package/dist/proto/spark_token.cjs +1515 -56
  52. package/dist/proto/spark_token.d.cts +153 -15
  53. package/dist/proto/spark_token.d.ts +153 -15
  54. package/dist/proto/spark_token.js +40 -4
  55. package/dist/{sdk-types-B-q9py_P.d.cts → sdk-types-B0SwjolI.d.cts} +1 -1
  56. package/dist/{sdk-types-BPoPgzda.d.ts → sdk-types-Cc4l4kb1.d.ts} +1 -1
  57. package/dist/services/config.cjs +7 -3
  58. package/dist/services/config.d.cts +5 -4
  59. package/dist/services/config.d.ts +5 -4
  60. package/dist/services/config.js +6 -6
  61. package/dist/services/connection.cjs +2938 -646
  62. package/dist/services/connection.d.cts +5 -4
  63. package/dist/services/connection.d.ts +5 -4
  64. package/dist/services/connection.js +4 -4
  65. package/dist/services/index.cjs +6381 -3461
  66. package/dist/services/index.d.cts +7 -6
  67. package/dist/services/index.d.ts +7 -6
  68. package/dist/services/index.js +15 -13
  69. package/dist/services/lrc-connection.cjs +227 -21
  70. package/dist/services/lrc-connection.d.cts +5 -4
  71. package/dist/services/lrc-connection.d.ts +5 -4
  72. package/dist/services/lrc-connection.js +4 -4
  73. package/dist/services/token-transactions.cjs +868 -244
  74. package/dist/services/token-transactions.d.cts +25 -7
  75. package/dist/services/token-transactions.d.ts +25 -7
  76. package/dist/services/token-transactions.js +5 -4
  77. package/dist/services/wallet-config.cjs +4 -1
  78. package/dist/services/wallet-config.d.cts +7 -5
  79. package/dist/services/wallet-config.d.ts +7 -5
  80. package/dist/services/wallet-config.js +3 -1
  81. package/dist/signer/signer.cjs +5 -2
  82. package/dist/signer/signer.d.cts +3 -2
  83. package/dist/signer/signer.d.ts +3 -2
  84. package/dist/signer/signer.js +2 -2
  85. package/dist/{signer-wqesWifN.d.ts → signer-BocS_J6B.d.ts} +2 -6
  86. package/dist/{signer-IO3oMRNj.d.cts → signer-DKS0AJkw.d.cts} +2 -6
  87. package/dist/{spark-CDm4gqS6.d.cts → spark-dM7EYXYQ.d.cts} +138 -42
  88. package/dist/{spark-CDm4gqS6.d.ts → spark-dM7EYXYQ.d.ts} +138 -42
  89. package/dist/spark_bindings/native/index.cjs +183 -0
  90. package/dist/spark_bindings/native/index.d.cts +14 -0
  91. package/dist/spark_bindings/native/index.d.ts +14 -0
  92. package/dist/spark_bindings/native/index.js +141 -0
  93. package/dist/spark_bindings/wasm/index.cjs +1093 -0
  94. package/dist/spark_bindings/wasm/index.d.cts +47 -0
  95. package/dist/spark_bindings/wasm/index.d.ts +47 -0
  96. package/dist/{chunk-K4C4W5FC.js → spark_bindings/wasm/index.js} +7 -6
  97. package/dist/types/index.cjs +1503 -443
  98. package/dist/types/index.d.cts +6 -5
  99. package/dist/types/index.d.ts +6 -5
  100. package/dist/types/index.js +3 -3
  101. package/dist/types-C-Rp0Oo7.d.cts +46 -0
  102. package/dist/types-C-Rp0Oo7.d.ts +46 -0
  103. package/dist/utils/index.cjs +358 -36
  104. package/dist/utils/index.d.cts +14 -134
  105. package/dist/utils/index.d.ts +14 -134
  106. package/dist/utils/index.js +8 -8
  107. package/package.json +21 -1
  108. package/src/constants.ts +5 -1
  109. package/src/graphql/client.ts +28 -0
  110. package/src/graphql/mutations/RequestCoopExit.ts +6 -0
  111. package/src/graphql/mutations/RequestSwapLeaves.ts +2 -0
  112. package/src/graphql/queries/GetCoopExitFeeQuote.ts +20 -0
  113. package/src/index.node.ts +0 -1
  114. package/src/index.ts +0 -1
  115. package/src/native/index.ts +1 -2
  116. package/src/proto/common.ts +5 -5
  117. package/src/proto/google/protobuf/descriptor.ts +34 -34
  118. package/src/proto/google/protobuf/duration.ts +2 -2
  119. package/src/proto/google/protobuf/empty.ts +2 -2
  120. package/src/proto/google/protobuf/timestamp.ts +2 -2
  121. package/src/proto/mock.ts +4 -4
  122. package/src/proto/spark.ts +1924 -525
  123. package/src/proto/spark_authn.ts +7 -7
  124. package/src/proto/spark_token.ts +1668 -105
  125. package/src/proto/validate/validate.ts +24 -24
  126. package/src/services/bolt11-spark.ts +62 -187
  127. package/src/services/coop-exit.ts +3 -0
  128. package/src/services/lrc20.ts +1 -1
  129. package/src/services/token-transactions.ts +209 -9
  130. package/src/services/transfer.ts +22 -3
  131. package/src/services/tree-creation.ts +13 -0
  132. package/src/services/wallet-config.ts +2 -1
  133. package/src/spark-wallet/spark-wallet.node.ts +3 -7
  134. package/src/spark-wallet/spark-wallet.ts +376 -232
  135. package/src/spark-wallet/types.ts +39 -3
  136. package/src/tests/bolt11-spark.test.ts +7 -15
  137. package/src/tests/integration/deposit.test.ts +16 -0
  138. package/src/tests/integration/ssp/coop-exit.test.ts +85 -21
  139. package/src/tests/integration/ssp/swap.test.ts +47 -0
  140. package/src/tests/integration/swap.test.ts +453 -433
  141. package/src/tests/integration/transfer.test.ts +261 -248
  142. package/src/tests/token-identifier.test.ts +54 -0
  143. package/src/tests/tokens.test.ts +218 -22
  144. package/src/utils/token-hashing.ts +346 -52
  145. package/src/utils/token-identifier.ts +88 -0
  146. package/src/utils/token-transaction-validation.ts +350 -5
  147. package/src/utils/token-transactions.ts +12 -8
  148. package/src/utils/transaction.ts +2 -8
  149. package/dist/chunk-VA7MV4MZ.js +0 -1073
  150. package/dist/index-7RYRH5wc.d.ts +0 -815
  151. package/dist/index-BJOc8Ur-.d.cts +0 -815
  152. package/dist/wasm-7OWFHDMS.js +0 -21
  153. package/src/logger.ts +0 -3
@@ -1,12 +1,9 @@
1
- import {
2
- ConnectionManager
3
- } from "./chunk-HRQRRDSS.js";
4
1
  import {
5
2
  Lrc20ConnectionManager
6
- } from "./chunk-GYQR4B4P.js";
3
+ } from "./chunk-GZ5IPPJ2.js";
7
4
  import {
8
5
  TokenTransactionService
9
- } from "./chunk-DQYKQJRZ.js";
6
+ } from "./chunk-C2S227QR.js";
10
7
  import {
11
8
  DEFAULT_FEE_SATS,
12
9
  computeTaprootKeyNoScript,
@@ -23,16 +20,17 @@ import {
23
20
  getTxFromRawTxHex,
24
21
  getTxId,
25
22
  proofOfPossessionMessageHashForDepositAddress
26
- } from "./chunk-IRW5TWMH.js";
23
+ } from "./chunk-5FUB65LX.js";
27
24
  import {
28
25
  calculateAvailableTokenAmount
29
- } from "./chunk-6AFUC5M2.js";
26
+ } from "./chunk-HWJWKEIU.js";
30
27
  import {
31
28
  mapTransferToWalletTransfer,
32
29
  mapTreeNodeToWalletLeaf
33
- } from "./chunk-MIVX3GHD.js";
30
+ } from "./chunk-OBFKIEMP.js";
34
31
  import {
35
32
  ClaimStaticDepositRequestType_default,
33
+ CoopExitFeeQuoteFromJson,
36
34
  CurrencyAmountFromJson,
37
35
  ExitSpeed_default,
38
36
  FRAGMENT,
@@ -40,20 +38,21 @@ import {
40
38
  FRAGMENT3,
41
39
  FRAGMENT4,
42
40
  FRAGMENT5,
41
+ FRAGMENT6,
43
42
  LeavesSwapRequestFromJson,
44
43
  LightningReceiveRequestFromJson,
45
44
  LightningSendRequestFromJson,
46
45
  SparkCoopExitRequestStatus_default,
47
46
  TransferFromJson
48
- } from "./chunk-TOSP3INR.js";
47
+ } from "./chunk-I54FARY2.js";
49
48
  import {
50
49
  decodeSparkAddress,
51
50
  encodeSparkAddress,
52
51
  isValidPublicKey
53
- } from "./chunk-O4RYNJNB.js";
52
+ } from "./chunk-KMUMFYFX.js";
54
53
  import {
55
54
  WalletConfigService
56
- } from "./chunk-BUTZWYBW.js";
55
+ } from "./chunk-6264CGDM.js";
57
56
  import {
58
57
  LRC_WALLET_NETWORK,
59
58
  LRC_WALLET_NETWORK_TYPE,
@@ -63,17 +62,7 @@ import {
63
62
  } from "./chunk-Z5HIAYFT.js";
64
63
  import {
65
64
  ELECTRS_CREDENTIALS
66
- } from "./chunk-DOA6QXYQ.js";
67
- import {
68
- BitcoinNetwork_default
69
- } from "./chunk-HMLOC6TE.js";
70
- import {
71
- SendLeafKeyTweaks,
72
- networkToJSON
73
- } from "./chunk-M6A4KFIG.js";
74
- import {
75
- isReactNative
76
- } from "./chunk-VFJQNBFX.js";
65
+ } from "./chunk-R5PXJZQS.js";
77
66
  import {
78
67
  addPublicKeys,
79
68
  applyAdaptorToSignature,
@@ -84,6 +73,15 @@ import {
84
73
  import {
85
74
  getCrypto
86
75
  } from "./chunk-QNNSEJ4P.js";
76
+ import {
77
+ BitcoinNetwork_default
78
+ } from "./chunk-HMLOC6TE.js";
79
+ import {
80
+ ConnectionManager
81
+ } from "./chunk-PQN3C2MF.js";
82
+ import {
83
+ isReactNative
84
+ } from "./chunk-7V6N75CC.js";
87
85
  import {
88
86
  AuthenticationError,
89
87
  ConfigurationError,
@@ -91,6 +89,10 @@ import {
91
89
  RPCError,
92
90
  ValidationError
93
91
  } from "./chunk-GSI4OLXZ.js";
92
+ import {
93
+ SendLeafKeyTweaks,
94
+ networkToJSON
95
+ } from "./chunk-BGGEVUJK.js";
94
96
  import {
95
97
  Buffer
96
98
  } from "./chunk-MVRQ5US7.js";
@@ -104,7 +106,7 @@ import {
104
106
  hexToBytes as hexToBytes7,
105
107
  numberToVarBytesBE
106
108
  } from "@noble/curves/abstract/utils";
107
- import { secp256k1 as secp256k16 } from "@noble/curves/secp256k1";
109
+ import { secp256k1 as secp256k15 } from "@noble/curves/secp256k1";
108
110
  import { validateMnemonic } from "@scure/bip39";
109
111
  import { wordlist } from "@scure/bip39/wordlists/english";
110
112
  import { Address as Address4, OutScript as OutScript4, Transaction as Transaction6 } from "@scure/btc-signer";
@@ -126,7 +128,7 @@ var ClaimStaticDepositOutputFromJson = (obj) => {
126
128
  transferId: obj["claim_static_deposit_output_transfer_id"]
127
129
  };
128
130
  };
129
- var FRAGMENT6 = `
131
+ var FRAGMENT7 = `
130
132
  fragment ClaimStaticDepositOutputFragment on ClaimStaticDepositOutput {
131
133
  __typename
132
134
  claim_static_deposit_output_transfer_id: transfer_id
@@ -159,7 +161,7 @@ var ClaimStaticDeposit = `
159
161
  }
160
162
  }
161
163
 
162
- ${FRAGMENT6}
164
+ ${FRAGMENT7}
163
165
  `;
164
166
 
165
167
  // src/graphql/objects/CoopExitRequest.ts
@@ -185,7 +187,7 @@ var CoopExitRequestFromJson = (obj) => {
185
187
  transfer: !!obj["coop_exit_request_transfer"] ? TransferFromJson(obj["coop_exit_request_transfer"]) : void 0
186
188
  };
187
189
  };
188
- var FRAGMENT7 = `
190
+ var FRAGMENT8 = `
189
191
  fragment CoopExitRequestFragment on CoopExitRequest {
190
192
  __typename
191
193
  coop_exit_request_id: id
@@ -250,7 +252,7 @@ var CompleteCoopExit = `
250
252
  }
251
253
  }
252
254
 
253
- ${FRAGMENT7}
255
+ ${FRAGMENT8}
254
256
  `;
255
257
 
256
258
  // src/graphql/mutations/CompleteLeavesSwap.ts
@@ -276,7 +278,7 @@ var GetChallengeOutputFromJson = (obj) => {
276
278
  protectedChallenge: obj["get_challenge_output_protected_challenge"]
277
279
  };
278
280
  };
279
- var FRAGMENT8 = `
281
+ var FRAGMENT9 = `
280
282
  fragment GetChallengeOutputFragment on GetChallengeOutput {
281
283
  __typename
282
284
  get_challenge_output_protected_challenge: protected_challenge
@@ -294,7 +296,7 @@ var GetChallenge = `
294
296
  }
295
297
  }
296
298
 
297
- ${FRAGMENT8}
299
+ ${FRAGMENT9}
298
300
  `;
299
301
 
300
302
  // src/graphql/mutations/RequestCoopExit.ts
@@ -304,6 +306,9 @@ var RequestCoopExit = `
304
306
  $withdrawal_address: String!
305
307
  $idempotency_key: String!
306
308
  $exit_speed: ExitSpeed!
309
+ $withdraw_all: Boolean
310
+ $fee_leaf_external_ids: [UUID!]
311
+ $fee_quote_id: ID
307
312
  ) {
308
313
  request_coop_exit(
309
314
  input: {
@@ -311,6 +316,9 @@ var RequestCoopExit = `
311
316
  withdrawal_address: $withdrawal_address
312
317
  idempotency_key: $idempotency_key
313
318
  exit_speed: $exit_speed
319
+ withdraw_all: $withdraw_all
320
+ fee_leaf_external_ids: $fee_leaf_external_ids
321
+ fee_quote_id: $fee_quote_id
314
322
  }
315
323
  ) {
316
324
  request {
@@ -318,7 +326,7 @@ var RequestCoopExit = `
318
326
  }
319
327
  }
320
328
  }
321
- ${FRAGMENT7}
329
+ ${FRAGMENT8}
322
330
  `;
323
331
 
324
332
  // src/graphql/mutations/RequestLightningReceive.ts
@@ -382,6 +390,7 @@ var RequestSwapLeaves = `
382
390
  $fee_sats: Long!
383
391
  $user_leaves: [UserLeafInput!]!
384
392
  $idempotency_key: String!
393
+ $target_amount_sats_list: [Long!]
385
394
  ) {
386
395
  request_leaves_swap(input: {
387
396
  adaptor_pubkey: $adaptor_pubkey
@@ -390,6 +399,7 @@ var RequestSwapLeaves = `
390
399
  fee_sats: $fee_sats
391
400
  user_leaves: $user_leaves
392
401
  idempotency_key: $idempotency_key
402
+ target_amount_sats_list: $target_amount_sats_list
393
403
  }) {
394
404
  request {
395
405
  ...LeavesSwapRequestFragment
@@ -406,7 +416,7 @@ var VerifyChallengeOutputFromJson = (obj) => {
406
416
  sessionToken: obj["verify_challenge_output_session_token"]
407
417
  };
408
418
  };
409
- var FRAGMENT9 = `
419
+ var FRAGMENT10 = `
410
420
  fragment VerifyChallengeOutputFragment on VerifyChallengeOutput {
411
421
  __typename
412
422
  verify_challenge_output_valid_until: valid_until
@@ -431,7 +441,7 @@ var VerifyChallenge = `
431
441
  }
432
442
  }
433
443
 
434
- ${FRAGMENT9}
444
+ ${FRAGMENT10}
435
445
  `;
436
446
 
437
447
  // src/graphql/objects/CoopExitFeeEstimate.ts
@@ -450,7 +460,7 @@ var CoopExitFeeEstimatesOutputFromJson = (obj) => {
450
460
  speedSlow: !!obj["coop_exit_fee_estimates_output_speed_slow"] ? CoopExitFeeEstimateFromJson(obj["coop_exit_fee_estimates_output_speed_slow"]) : void 0
451
461
  };
452
462
  };
453
- var FRAGMENT10 = `
463
+ var FRAGMENT11 = `
454
464
  fragment CoopExitFeeEstimatesOutputFragment on CoopExitFeeEstimatesOutput {
455
465
  __typename
456
466
  coop_exit_fee_estimates_output_speed_fast: speed_fast {
@@ -518,7 +528,7 @@ var LeavesSwapFeeEstimateOutputFromJson = (obj) => {
518
528
  feeEstimate: CurrencyAmountFromJson(obj["leaves_swap_fee_estimate_output_fee_estimate"])
519
529
  };
520
530
  };
521
- var FRAGMENT11 = `
531
+ var FRAGMENT12 = `
522
532
  fragment LeavesSwapFeeEstimateOutputFragment on LeavesSwapFeeEstimateOutput {
523
533
  __typename
524
534
  leaves_swap_fee_estimate_output_fee_estimate: fee_estimate {
@@ -537,7 +547,7 @@ var LightningSendFeeEstimateOutputFromJson = (obj) => {
537
547
  feeEstimate: CurrencyAmountFromJson(obj["lightning_send_fee_estimate_output_fee_estimate"])
538
548
  };
539
549
  };
540
- var FRAGMENT12 = `
550
+ var FRAGMENT13 = `
541
551
  fragment LightningSendFeeEstimateOutputFragment on LightningSendFeeEstimateOutput {
542
552
  __typename
543
553
  lightning_send_fee_estimate_output_fee_estimate: fee_estimate {
@@ -560,7 +570,7 @@ var StaticDepositQuoteOutputFromJson = (obj) => {
560
570
  signature: obj["static_deposit_quote_output_signature"]
561
571
  };
562
572
  };
563
- var FRAGMENT13 = `
573
+ var FRAGMENT14 = `
564
574
  fragment StaticDepositQuoteOutputFragment on StaticDepositQuoteOutput {
565
575
  __typename
566
576
  static_deposit_quote_output_transaction_id: transaction_id
@@ -585,7 +595,7 @@ var CoopExitFeeEstimate2 = `
585
595
  ...CoopExitFeeEstimatesOutputFragment
586
596
  }
587
597
  }
588
- ${FRAGMENT10}
598
+ ${FRAGMENT11}
589
599
  `;
590
600
 
591
601
  // src/graphql/queries/GetClaimDepositQuote.ts
@@ -605,7 +615,27 @@ var GetClaimDepositQuote = `
605
615
  ...StaticDepositQuoteOutputFragment
606
616
  }
607
617
  }
608
- ${FRAGMENT13}
618
+ ${FRAGMENT14}
619
+ `;
620
+
621
+ // src/graphql/queries/GetCoopExitFeeQuote.ts
622
+ var GetCoopExitFeeQuote = `
623
+ query CoopExitFeeQuote(
624
+ $leaf_external_ids: [UUID!]!
625
+ $withdrawal_address: String!
626
+ ) {
627
+ coop_exit_fee_quote(
628
+ input: {
629
+ leaf_external_ids: $leaf_external_ids,
630
+ withdrawal_address: $withdrawal_address
631
+ }
632
+ ) {
633
+ quote {
634
+ ...CoopExitFeeQuoteFragment
635
+ }
636
+ }
637
+ }
638
+ ${FRAGMENT5}
609
639
  `;
610
640
 
611
641
  // src/graphql/queries/LeavesSwapFeeEstimate.ts
@@ -621,7 +651,7 @@ var LeavesSwapFeeEstimate = `
621
651
  ...LeavesSwapFeeEstimateOutputFragment
622
652
  }
623
653
  }
624
- ${FRAGMENT11}
654
+ ${FRAGMENT12}
625
655
  `;
626
656
 
627
657
  // src/graphql/queries/LightningSendFeeEstimate.ts
@@ -639,7 +669,7 @@ var LightningSendFeeEstimate = `
639
669
  ...LightningSendFeeEstimateOutputFragment
640
670
  }
641
671
  }
642
- ${FRAGMENT12}
672
+ ${FRAGMENT13}
643
673
  `;
644
674
 
645
675
  // src/graphql/queries/Transfer.ts
@@ -659,7 +689,7 @@ var UserRequest = `
659
689
  ...UserRequestFragment
660
690
  }
661
691
  }
662
- ${FRAGMENT5}
692
+ ${FRAGMENT6}
663
693
  `;
664
694
 
665
695
  // src/graphql/client.ts
@@ -781,7 +811,10 @@ var SspClient = class {
781
811
  leafExternalIds,
782
812
  withdrawalAddress,
783
813
  idempotencyKey,
784
- exitSpeed
814
+ exitSpeed,
815
+ feeLeafExternalIds,
816
+ feeQuoteId,
817
+ withdrawAll
785
818
  }) {
786
819
  return await this.executeRawQuery({
787
820
  queryPayload: RequestCoopExit,
@@ -789,7 +822,10 @@ var SspClient = class {
789
822
  leaf_external_ids: leafExternalIds,
790
823
  withdrawal_address: withdrawalAddress,
791
824
  idempotency_key: idempotencyKey,
792
- exit_speed: exitSpeed
825
+ exit_speed: exitSpeed,
826
+ fee_leaf_external_ids: feeLeafExternalIds,
827
+ fee_quote_id: feeQuoteId,
828
+ withdraw_all: withdrawAll
793
829
  },
794
830
  constructObject: (response) => {
795
831
  return CoopExitRequestFromJson(response.request_coop_exit.request);
@@ -851,7 +887,8 @@ var SspClient = class {
851
887
  targetAmountSats,
852
888
  feeSats,
853
889
  userLeaves,
854
- idempotencyKey
890
+ idempotencyKey,
891
+ targetAmountSatsList
855
892
  }) {
856
893
  const query = {
857
894
  queryPayload: RequestSwapLeaves,
@@ -861,7 +898,8 @@ var SspClient = class {
861
898
  target_amount_sats: targetAmountSats,
862
899
  fee_sats: feeSats,
863
900
  user_leaves: userLeaves,
864
- idempotency_key: idempotencyKey
901
+ idempotency_key: idempotencyKey,
902
+ target_amount_sats_list: targetAmountSatsList
865
903
  },
866
904
  constructObject: (response) => {
867
905
  if (!response.request_leaves_swap) {
@@ -1053,6 +1091,21 @@ var SspClient = class {
1053
1091
  new Date(verifyChallenge.validUntil)
1054
1092
  );
1055
1093
  }
1094
+ async getCoopExitFeeQuote({
1095
+ leafExternalIds,
1096
+ withdrawalAddress
1097
+ }) {
1098
+ return await this.executeRawQuery({
1099
+ queryPayload: GetCoopExitFeeQuote,
1100
+ variables: {
1101
+ leaf_external_ids: leafExternalIds,
1102
+ withdrawal_address: withdrawalAddress
1103
+ },
1104
+ constructObject: (response) => {
1105
+ return CoopExitFeeQuoteFromJson(response.coop_exit_fee_quote.quote);
1106
+ }
1107
+ });
1108
+ }
1056
1109
  };
1057
1110
  var SparkAuthProvider = class {
1058
1111
  sessionToken;
@@ -1263,7 +1316,10 @@ var BaseTransferService = class {
1263
1316
  const transferPackage = {
1264
1317
  leavesToSend: leafSigningJobs,
1265
1318
  keyTweakPackage: encryptedKeyTweaks,
1266
- userSignature: new Uint8Array()
1319
+ userSignature: new Uint8Array(),
1320
+ // TODO: Add direct refund signature
1321
+ directLeavesToSend: [],
1322
+ directFromCpfpLeavesToSend: []
1267
1323
  };
1268
1324
  const transferPackageSigningPayload = getTransferPackageSigningPayload(
1269
1325
  transferID,
@@ -1362,7 +1418,11 @@ var BaseTransferService = class {
1362
1418
  nodeSignatures.push({
1363
1419
  nodeId: operatorSigningResult.leafId,
1364
1420
  refundTxSignature: refundAggregate,
1365
- nodeTxSignature: new Uint8Array()
1421
+ nodeTxSignature: new Uint8Array(),
1422
+ // TODO: Add direct refund signature
1423
+ directNodeTxSignature: new Uint8Array(),
1424
+ directRefundTxSignature: new Uint8Array(),
1425
+ directFromCpfpRefundTxSignature: new Uint8Array()
1366
1426
  });
1367
1427
  }
1368
1428
  return nodeSignatures;
@@ -1444,7 +1504,10 @@ var BaseTransferService = class {
1444
1504
  pubkeySharesTweak: Object.fromEntries(pubkeySharesTweak),
1445
1505
  secretCipher,
1446
1506
  signature,
1447
- refundSignature: refundSignature ?? new Uint8Array()
1507
+ refundSignature: refundSignature ?? new Uint8Array(),
1508
+ // TODO: Add direct refund signature
1509
+ directRefundSignature: new Uint8Array(),
1510
+ directFromCpfpRefundSignature: new Uint8Array()
1448
1511
  });
1449
1512
  }
1450
1513
  return leafTweaksMap;
@@ -1726,7 +1789,11 @@ var TransferService = class extends BaseTransferService {
1726
1789
  signingPublicKey: refundSigningData.signingPubKey,
1727
1790
  rawTx: refundTx.toBytes(),
1728
1791
  signingNonceCommitment: refundNonceCommitmentProto
1729
- }
1792
+ },
1793
+ // TODO: Add direct refund signature
1794
+ directRefundTxSigningJob: void 0,
1795
+ // TODO: Add direct refund signature
1796
+ directFromCpfpRefundTxSigningJob: void 0
1730
1797
  });
1731
1798
  }
1732
1799
  return signingJobs;
@@ -2093,7 +2160,11 @@ var TransferService = class extends BaseTransferService {
2093
2160
  nodeSignatures.push({
2094
2161
  nodeId,
2095
2162
  nodeTxSignature: signature,
2096
- refundTxSignature: new Uint8Array()
2163
+ refundTxSignature: new Uint8Array(),
2164
+ // TODO: Add direct refund signature
2165
+ directNodeTxSignature: new Uint8Array(),
2166
+ directRefundTxSignature: new Uint8Array(),
2167
+ directFromCpfpRefundTxSignature: new Uint8Array()
2097
2168
  });
2098
2169
  } else if (i === nodes.length) {
2099
2170
  refundSignature = signature;
@@ -2108,7 +2179,11 @@ var TransferService = class extends BaseTransferService {
2108
2179
  nodeSignatures.push({
2109
2180
  nodeId: leafNodeId,
2110
2181
  nodeTxSignature: leafSignature,
2111
- refundTxSignature: refundSignature
2182
+ refundTxSignature: refundSignature,
2183
+ // TODO: Add direct refund signature
2184
+ directNodeTxSignature: new Uint8Array(),
2185
+ directRefundTxSignature: new Uint8Array(),
2186
+ directFromCpfpRefundTxSignature: new Uint8Array()
2112
2187
  });
2113
2188
  const result = await sparkClient.finalize_node_signatures({
2114
2189
  intent: 3 /* REFRESH */,
@@ -2425,7 +2500,10 @@ var CoopExitService = class extends BaseTransferService {
2425
2500
  signingPublicKey: leaf.signingPubKey,
2426
2501
  rawTx: refundTx.toBytes(),
2427
2502
  signingNonceCommitment
2428
- }
2503
+ },
2504
+ // TODO: Add direct refund signature
2505
+ directRefundTxSigningJob: void 0,
2506
+ directFromCpfpRefundTxSigningJob: void 0
2429
2507
  };
2430
2508
  signingJobs.push(signingJob);
2431
2509
  const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
@@ -2798,98 +2876,58 @@ import {
2798
2876
  hexToBytes as hexToBytes3,
2799
2877
  numberToBytesBE as numberToBytesBE2
2800
2878
  } from "@noble/curves/abstract/utils";
2801
- import { secp256k1 as secp256k14 } from "@noble/curves/secp256k1";
2802
- import { sha256 as sha2565 } from "@noble/hashes/sha2";
2879
+ import { secp256k1 as secp256k13 } from "@noble/curves/secp256k1";
2880
+ import { sha256 as sha2564 } from "@noble/hashes/sha2";
2803
2881
  import { uuidv7 as uuidv73 } from "uuidv7";
2804
2882
 
2805
2883
  // src/services/bolt11-spark.ts
2806
- import { bech32 } from "@scure/base";
2807
- import { sha256 as sha2564 } from "@noble/hashes/sha2";
2808
- import { secp256k1 as secp256k13 } from "@noble/curves/secp256k1";
2884
+ import { decode } from "light-bolt11-decoder";
2885
+ var RECEIVER_IDENTITY_PUBLIC_KEY_SHORT_CHANNEL_ID = "f42400f424000001";
2886
+ var PAYMENT_HASH_NAME = "payment_hash";
2887
+ var AMOUNT_MSATS_NAME = "amount";
2888
+ var PAYMENT_SECRET_NAME = "payment_secret";
2809
2889
  function decodeInvoice(invoice) {
2810
- const { words, prefix } = bech32.decode(
2811
- invoice,
2812
- 1e3
2813
- );
2814
- verifySignature(words, prefix);
2815
- const amountMSats = extractMillisatoshiAmountFromInvoice(invoice);
2816
- let fallbackAddress = void 0;
2817
- let paymentHash = void 0;
2818
- let paymentSecret = void 0;
2819
- let i = 7;
2820
- const tlvEnd = words.length - 105;
2821
- while (i + 2 < tlvEnd) {
2822
- const tag = words[i];
2823
- const len1 = words[i + 1];
2824
- const len2 = words[i + 2];
2825
- if (len1 === void 0 || len2 === void 0) {
2826
- console.log("No length word");
2827
- break;
2828
- }
2829
- const len = (len1 << 5) + len2;
2830
- const start = i + 3;
2831
- const end = start + len;
2832
- if (tag === 1) {
2833
- const hashWords = words.slice(start, end);
2834
- const hashBytes = bech32WordsToBytes(hashWords);
2835
- if (hashBytes.length === 32) {
2836
- paymentHash = Buffer.from(hashBytes).toString("hex");
2837
- }
2838
- } else if (tag === 9) {
2839
- const verWord = words[start];
2840
- if (verWord !== 31) {
2841
- console.warn("Not our custom version-31");
2842
- i = end;
2843
- continue;
2844
- }
2845
- const payloadWords = words.slice(start + 1, end);
2846
- const payloadBytes = bech32WordsToBytes(payloadWords);
2847
- fallbackAddress = Buffer.from(payloadBytes).toString("hex");
2848
- } else if (tag === 16) {
2849
- if (len !== 52) {
2850
- throw new ValidationError("Invalid payment secret length", {
2851
- field: "paymentSecret",
2852
- value: len,
2853
- expected: "52 words (32 bytes for 256-bit secret)"
2854
- });
2855
- }
2856
- const secretWords = words.slice(start, end);
2857
- const secretBytes = bech32WordsToBytes(secretWords);
2858
- if (secretBytes.length !== 32) {
2859
- throw new ValidationError("Invalid payment secret size", {
2860
- field: "paymentSecret",
2861
- value: secretBytes.length,
2862
- expected: "32 bytes (256 bits)"
2863
- });
2890
+ const decodedInvoice = decode(invoice);
2891
+ const network = getNetworkFromInvoice(invoice);
2892
+ if (network === null) {
2893
+ throw new ValidationError("Invalid network found in invoice: " + invoice);
2894
+ }
2895
+ let paymentSection;
2896
+ let routeHints = [];
2897
+ let amountSection;
2898
+ let paymentSecretSection;
2899
+ let fallbackAddress;
2900
+ for (const section of decodedInvoice.sections) {
2901
+ if (section.name === PAYMENT_HASH_NAME) {
2902
+ paymentSection = section;
2903
+ }
2904
+ if (section.name === AMOUNT_MSATS_NAME) {
2905
+ amountSection = section;
2906
+ }
2907
+ if (section.name === PAYMENT_SECRET_NAME) {
2908
+ paymentSecretSection = section;
2909
+ }
2910
+ }
2911
+ routeHints = decodedInvoice.route_hints;
2912
+ const amountMSats = amountSection?.value ? BigInt(amountSection.value) : null;
2913
+ const paymentHash = paymentSection?.value;
2914
+ for (const routeHintArray of routeHints) {
2915
+ for (const routeHint of routeHintArray) {
2916
+ if (routeHint.short_channel_id === RECEIVER_IDENTITY_PUBLIC_KEY_SHORT_CHANNEL_ID) {
2917
+ fallbackAddress = routeHint.pubkey;
2864
2918
  }
2865
- paymentSecret = Buffer.from(secretBytes).toString("hex");
2866
2919
  }
2867
- i = end;
2868
2920
  }
2869
2921
  if (paymentHash === void 0) {
2870
2922
  throw new ValidationError("No payment hash found in invoice: " + invoice);
2871
2923
  }
2872
- if (paymentSecret === void 0) {
2924
+ if (paymentSecretSection?.value === void 0) {
2873
2925
  throw new ValidationError(
2874
2926
  "Invalid payment secret found in invoice: " + invoice
2875
2927
  );
2876
2928
  }
2877
2929
  return { amountMSats, fallbackAddress, paymentHash };
2878
2930
  }
2879
- function bech32WordsToBytes(words) {
2880
- let acc = 0, bits = 0;
2881
- const out = [];
2882
- for (const w of words) {
2883
- if (w < 0 || w > 31) throw new Error(`bad word ${w}`);
2884
- acc = acc << 5 | w;
2885
- bits += 5;
2886
- while (bits >= 8) {
2887
- bits -= 8;
2888
- out.push(acc >> bits & 255);
2889
- }
2890
- }
2891
- return new Uint8Array(out);
2892
- }
2893
2931
  function getNetworkFromInvoice(invoice) {
2894
2932
  if (invoice.startsWith("lnbcrt")) return 3 /* REGTEST */;
2895
2933
  if (invoice.startsWith("lnbc")) return 0 /* MAINNET */;
@@ -2897,85 +2935,11 @@ function getNetworkFromInvoice(invoice) {
2897
2935
  if (invoice.startsWith("lnsb")) return 2 /* SIGNET */;
2898
2936
  return null;
2899
2937
  }
2900
- function extractMillisatoshiAmountFromInvoice(invoice) {
2901
- const match = invoice.match(/^ln[a-z]+(\d+)([a-z]?)1/);
2902
- if (!match) return null;
2903
- const [, amount, multiplier] = match;
2904
- if (!amount) return null;
2905
- const value = BigInt(amount);
2906
- const MILLISATS_PER_BTC = 100000000000n;
2907
- const divisors = {
2908
- m: 1000n,
2909
- u: 1000000n,
2910
- n: 1000000000n,
2911
- p: 10000000000000n
2912
- };
2913
- if (multiplier) {
2914
- if (!(multiplier in divisors)) {
2915
- throw new ValidationError(`Invalid multiplier: ${multiplier}`, {
2916
- field: "multiplier",
2917
- value: multiplier,
2918
- expected: "valid bolt11 multiplier: m, u, n, p"
2919
- });
2920
- }
2921
- const divisor = divisors[multiplier];
2922
- if (value * MILLISATS_PER_BTC % divisor !== 0n) {
2923
- throw new ValidationError("Invalid submillisatoshi precision", {
2924
- field: "amount",
2925
- value: `${amount}${multiplier}`,
2926
- expected: "amount must result in whole millisatoshis"
2927
- });
2928
- }
2929
- return value * MILLISATS_PER_BTC / divisor;
2930
- } else {
2931
- return value * MILLISATS_PER_BTC;
2932
- }
2933
- }
2934
- function hasSparkHeader(bytes) {
2935
- if (bytes.length < 3) {
2936
- return false;
2937
- }
2938
- return bytes[0] === 83 && // 'S'
2939
- bytes[1] === 80 && // 'P'
2940
- bytes[2] === 75;
2941
- }
2942
2938
  function isValidSparkFallback(bytes) {
2943
- if (bytes.length !== 36) {
2939
+ if (bytes.length !== 33) {
2944
2940
  return false;
2945
2941
  }
2946
- return hasSparkHeader(bytes);
2947
- }
2948
- function verifySignature(words, prefix) {
2949
- if (words.length < 104) {
2950
- throw new ValidationError("Invoice too short for signature");
2951
- }
2952
- const signatureStart = words.length - 104;
2953
- const signatureEnd = words.length - 1;
2954
- const hrp = prefix;
2955
- const hrpBytes = new TextEncoder().encode(hrp);
2956
- const dataWords = words.slice(0, signatureStart);
2957
- const dataBytes = bech32WordsToBytes(dataWords);
2958
- const sigWords = words.slice(signatureStart, signatureEnd);
2959
- const sigBytes = bech32WordsToBytes(sigWords);
2960
- if (sigBytes.length !== 64) {
2961
- throw new ValidationError("Invalid signature length");
2962
- }
2963
- const recoveryId = words[words.length - 1];
2964
- if (recoveryId === void 0) {
2965
- throw new ValidationError("Missing recovery ID in signature");
2966
- }
2967
- const messageBytes = new Uint8Array(hrpBytes.length + dataBytes.length);
2968
- messageBytes.set(hrpBytes, 0);
2969
- messageBytes.set(dataBytes, hrpBytes.length);
2970
- const messageHash = sha2564(messageBytes);
2971
- try {
2972
- const signature = secp256k13.Signature.fromCompact(sigBytes).addRecoveryBit(recoveryId);
2973
- signature.recoverPublicKey(messageHash);
2974
- } catch (error) {
2975
- throw new ValidationError(
2976
- `Invalid BOLT11 signature: ${error.message}`
2977
- );
2978
- }
2942
+ return true;
2979
2943
  }
2980
2944
 
2981
2945
  // src/services/lightning.ts
@@ -2998,7 +2962,7 @@ var LightningService = class {
2998
2962
  }) {
2999
2963
  const randBytes = crypto.getRandomValues(new Uint8Array(32));
3000
2964
  const preimage = numberToBytesBE2(
3001
- bytesToNumberBE(randBytes) % secp256k14.CURVE.n,
2965
+ bytesToNumberBE(randBytes) % secp256k13.CURVE.n,
3002
2966
  32
3003
2967
  );
3004
2968
  return await this.createLightningInvoiceWithPreImage({
@@ -3018,7 +2982,7 @@ var LightningService = class {
3018
2982
  receiverIdentityPubkey,
3019
2983
  descriptionHash
3020
2984
  }) {
3021
- const paymentHash = sha2565(preimage);
2985
+ const paymentHash = sha2564(preimage);
3022
2986
  const invoice = await invoiceCreator(
3023
2987
  amountSats,
3024
2988
  paymentHash,
@@ -3035,7 +2999,7 @@ var LightningService = class {
3035
2999
  }
3036
3000
  const shares = await this.config.signer.splitSecretWithProofs({
3037
3001
  secret: preimage,
3038
- curveOrder: secp256k14.CURVE.n,
3002
+ curveOrder: secp256k13.CURVE.n,
3039
3003
  threshold: this.config.getThreshold(),
3040
3004
  numShares: Object.keys(this.config.getSigningOperators()).length
3041
3005
  });
@@ -3215,7 +3179,7 @@ var LightningService = class {
3215
3179
  const sparkClient = await this.connectionManager.createSparkClient(
3216
3180
  this.config.getCoordinatorAddress()
3217
3181
  );
3218
- const paymentHash = sha2565(preimage);
3182
+ const paymentHash = sha2564(preimage);
3219
3183
  let response;
3220
3184
  try {
3221
3185
  response = await sparkClient.provide_preimage({
@@ -3247,10 +3211,10 @@ var LightningService = class {
3247
3211
 
3248
3212
  // src/services/tree-creation.ts
3249
3213
  import { hexToBytes as hexToBytes4 } from "@noble/curves/abstract/utils";
3250
- import { sha256 as sha2566 } from "@noble/hashes/sha2";
3214
+ import { sha256 as sha2565 } from "@noble/hashes/sha2";
3251
3215
  import { Address as Address2, OutScript as OutScript2, Transaction as Transaction4 } from "@scure/btc-signer";
3252
3216
  var INITIAL_TIME_LOCK3 = 2e3;
3253
- function maybeApplyFee2(amount) {
3217
+ function maybeApplyFee(amount) {
3254
3218
  if (amount > BigInt(DEFAULT_FEE_SATS)) {
3255
3219
  return amount - BigInt(DEFAULT_FEE_SATS);
3256
3220
  }
@@ -3403,7 +3367,7 @@ var TreeCreationService = class {
3403
3367
  return finalizeResp;
3404
3368
  }
3405
3369
  async createDepositAddressTree(targetSigningPublicKey, nodeId) {
3406
- const leftKey = await this.config.signer.generatePublicKey(sha2566(nodeId));
3370
+ const leftKey = await this.config.signer.generatePublicKey(sha2565(nodeId));
3407
3371
  const leftNode = {
3408
3372
  signingPublicKey: leftKey,
3409
3373
  children: []
@@ -3452,7 +3416,10 @@ var TreeCreationService = class {
3452
3416
  const internalCreationNode = {
3453
3417
  nodeTxSigningJob: void 0,
3454
3418
  refundTxSigningJob: void 0,
3455
- children: []
3419
+ children: [],
3420
+ directNodeTxSigningJob: void 0,
3421
+ directRefundTxSigningJob: void 0,
3422
+ directFromCpfpRefundTxSigningJob: void 0
3456
3423
  };
3457
3424
  const tx = new Transaction4({ version: 3 });
3458
3425
  tx.addInput({
@@ -3481,7 +3448,10 @@ var TreeCreationService = class {
3481
3448
  const childCreationNode = {
3482
3449
  nodeTxSigningJob: void 0,
3483
3450
  refundTxSigningJob: void 0,
3484
- children: []
3451
+ children: [],
3452
+ directNodeTxSigningJob: void 0,
3453
+ directRefundTxSigningJob: void 0,
3454
+ directFromCpfpRefundTxSigningJob: void 0
3485
3455
  };
3486
3456
  const childTx = new Transaction4({ version: 3 });
3487
3457
  childTx.addInput({
@@ -3519,7 +3489,7 @@ var TreeCreationService = class {
3519
3489
  const refundPkScript = OutScript2.encode(refundAddress);
3520
3490
  refundTx.addOutput({
3521
3491
  script: refundPkScript,
3522
- amount: maybeApplyFee2(parentTxOut.amount)
3492
+ amount: maybeApplyFee(parentTxOut.amount)
3523
3493
  });
3524
3494
  refundTx.addOutput(getEphemeralAnchorOutput());
3525
3495
  const refundSigningNonceCommitment = await this.config.signer.getRandomSigningCommitment();
@@ -3566,7 +3536,10 @@ var TreeCreationService = class {
3566
3536
  const rootCreationNode = {
3567
3537
  nodeTxSigningJob: rootNodeSigningJob,
3568
3538
  refundTxSigningJob: void 0,
3569
- children: []
3539
+ children: [],
3540
+ directNodeTxSigningJob: void 0,
3541
+ directRefundTxSigningJob: void 0,
3542
+ directFromCpfpRefundTxSigningJob: void 0
3570
3543
  };
3571
3544
  rootCreationNode.nodeTxSigningCommitment = rootNodeSigningCommitment;
3572
3545
  const leftChild = root.children[0];
@@ -3656,7 +3629,11 @@ var TreeCreationService = class {
3656
3629
  signature: {
3657
3630
  nodeId: creationResponseNode.nodeId,
3658
3631
  nodeTxSignature,
3659
- refundTxSignature
3632
+ refundTxSignature,
3633
+ // TODO: Add direct refund signature
3634
+ directNodeTxSignature: new Uint8Array(),
3635
+ directRefundTxSignature: new Uint8Array(),
3636
+ directFromCpfpRefundTxSignature: new Uint8Array()
3660
3637
  }
3661
3638
  };
3662
3639
  }
@@ -3708,7 +3685,7 @@ var TreeCreationService = class {
3708
3685
 
3709
3686
  // src/spark-wallet/spark-wallet.ts
3710
3687
  import { LRCWallet } from "@buildonspark/lrc20-sdk";
3711
- import { sha256 as sha2567 } from "@noble/hashes/sha2";
3688
+ import { sha256 as sha2566 } from "@noble/hashes/sha2";
3712
3689
  import { EventEmitter } from "eventemitter3";
3713
3690
 
3714
3691
  // src/services/signing.ts
@@ -3789,7 +3766,7 @@ var SigningService = class {
3789
3766
 
3790
3767
  // src/tests/utils/test-faucet.ts
3791
3768
  import { bytesToHex as bytesToHex3, hexToBytes as hexToBytes6 } from "@noble/curves/abstract/utils";
3792
- import { schnorr as schnorr2, secp256k1 as secp256k15 } from "@noble/curves/secp256k1";
3769
+ import { schnorr as schnorr2, secp256k1 as secp256k14 } from "@noble/curves/secp256k1";
3793
3770
  import * as btc2 from "@scure/btc-signer";
3794
3771
  import { Address as Address3, OutScript as OutScript3, SigHash, Transaction as Transaction5 } from "@scure/btc-signer";
3795
3772
  import { taprootTweakPrivKey } from "@scure/btc-signer/utils";
@@ -3809,7 +3786,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
3809
3786
  this.username = username;
3810
3787
  this.password = password;
3811
3788
  this.miningAddress = getP2TRAddressFromPublicKey(
3812
- secp256k15.getPublicKey(STATIC_MINING_KEY),
3789
+ secp256k14.getPublicKey(STATIC_MINING_KEY),
3813
3790
  4 /* LOCAL */
3814
3791
  );
3815
3792
  }
@@ -3848,7 +3825,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
3848
3825
  });
3849
3826
  }
3850
3827
  async refill() {
3851
- const minerPubKey = secp256k15.getPublicKey(STATIC_MINING_KEY);
3828
+ const minerPubKey = secp256k14.getPublicKey(STATIC_MINING_KEY);
3852
3829
  const address = getP2TRAddressFromPublicKey(minerPubKey, 4 /* LOCAL */);
3853
3830
  const scanResult = await this.call("scantxoutset", [
3854
3831
  "start",
@@ -3897,7 +3874,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
3897
3874
  txid: selectedUtxo.txid,
3898
3875
  index: selectedUtxo.vout
3899
3876
  });
3900
- const faucetPubKey = secp256k15.getPublicKey(STATIC_FAUCET_KEY);
3877
+ const faucetPubKey = secp256k14.getPublicKey(STATIC_FAUCET_KEY);
3901
3878
  const script = getP2TRScriptFromPublicKey(faucetPubKey, 4 /* LOCAL */);
3902
3879
  for (let i = 0; i < numCoinsToCreate; i++) {
3903
3880
  splitTx.addOutput({
@@ -3958,7 +3935,7 @@ var BitcoinFaucet = class _BitcoinFaucet {
3958
3935
  await this.broadcastTx(bytesToHex3(signedTx.extract()));
3959
3936
  }
3960
3937
  async signFaucetCoin(unsignedTx, fundingTxOut, key) {
3961
- const pubKey = secp256k15.getPublicKey(key);
3938
+ const pubKey = secp256k14.getPublicKey(key);
3962
3939
  const internalKey = pubKey.slice(1);
3963
3940
  const script = getP2TRScriptFromPublicKey(pubKey, 4 /* LOCAL */);
3964
3941
  unsignedTx.updateInput(0, {
@@ -4040,8 +4017,8 @@ var BitcoinFaucet = class _BitcoinFaucet {
4040
4017
  return response;
4041
4018
  }
4042
4019
  async getNewAddress() {
4043
- const key = secp256k15.utils.randomPrivateKey();
4044
- const pubKey = secp256k15.getPublicKey(key);
4020
+ const key = secp256k14.utils.randomPrivateKey();
4021
+ const pubKey = secp256k14.getPublicKey(key);
4045
4022
  return getP2TRAddressFromPublicKey(pubKey, 4 /* LOCAL */);
4046
4023
  }
4047
4024
  async sendToAddress(address, amount) {
@@ -4062,8 +4039,8 @@ var BitcoinFaucet = class _BitcoinFaucet {
4062
4039
  });
4063
4040
  const changeAmount = availableAmount - amount;
4064
4041
  if (changeAmount > 0) {
4065
- const changeKey = secp256k15.utils.randomPrivateKey();
4066
- const changePubKey = secp256k15.getPublicKey(changeKey);
4042
+ const changeKey = secp256k14.utils.randomPrivateKey();
4043
+ const changePubKey = secp256k14.getPublicKey(changeKey);
4067
4044
  const changeScript = getP2TRScriptFromPublicKey(
4068
4045
  changePubKey,
4069
4046
  4 /* LOCAL */
@@ -4076,8 +4053,8 @@ var BitcoinFaucet = class _BitcoinFaucet {
4076
4053
  const signedTx = await this.signFaucetCoin(tx, coin.txout, coin.key);
4077
4054
  const txHex = bytesToHex3(signedTx.extract());
4078
4055
  await this.broadcastTx(txHex);
4079
- const randomKey = secp256k15.utils.randomPrivateKey();
4080
- const randomPubKey = secp256k15.getPublicKey(randomKey);
4056
+ const randomKey = secp256k14.utils.randomPrivateKey();
4057
+ const randomPubKey = secp256k14.getPublicKey(randomKey);
4081
4058
  const randomAddress = getP2TRAddressFromPublicKey(
4082
4059
  randomPubKey,
4083
4060
  4 /* LOCAL */
@@ -4099,6 +4076,35 @@ function chunkArray(arr, size) {
4099
4076
  return chunks;
4100
4077
  }
4101
4078
 
4079
+ // src/utils/token-identifier.ts
4080
+ import { bech32m } from "@scure/base";
4081
+ var HumanReadableTokenIdentifierNetworkPrefix = {
4082
+ MAINNET: "btk",
4083
+ REGTEST: "btkrt",
4084
+ TESTNET: "btkt",
4085
+ SIGNET: "btks",
4086
+ LOCAL: "btkl"
4087
+ };
4088
+ function encodeHumanReadableTokenIdentifier(payload) {
4089
+ try {
4090
+ const words = bech32m.toWords(payload.tokenIdentifier);
4091
+ return bech32m.encode(
4092
+ HumanReadableTokenIdentifierNetworkPrefix[payload.network],
4093
+ words,
4094
+ 500
4095
+ );
4096
+ } catch (error) {
4097
+ throw new ValidationError(
4098
+ "Failed to encode human readable token identifier",
4099
+ {
4100
+ field: "tokenIdentifier",
4101
+ value: payload.tokenIdentifier
4102
+ },
4103
+ error
4104
+ );
4105
+ }
4106
+ }
4107
+
4102
4108
  // src/spark-wallet/spark-wallet.ts
4103
4109
  var SparkWallet = class _SparkWallet extends EventEmitter {
4104
4110
  config;
@@ -4209,7 +4215,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4209
4215
  } else if (event?.$case === "deposit" && event.deposit.deposit) {
4210
4216
  const deposit = event.deposit.deposit;
4211
4217
  const signingKey = await this.config.signer.generatePublicKey(
4212
- sha2567(deposit.id)
4218
+ sha2566(deposit.id)
4213
4219
  );
4214
4220
  const newLeaf = await this.transferService.extendTimelock(
4215
4221
  deposit,
@@ -4364,7 +4370,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4364
4370
  if (leaf.status !== operatorLeaf.status || !leaf.signingKeyshare || !operatorLeaf.signingKeyshare || !equalBytes3(
4365
4371
  leaf.signingKeyshare.publicKey,
4366
4372
  operatorLeaf.signingKeyshare.publicKey
4367
- ) || !equalBytes3(leaf.nodeTx, operatorLeaf.nodeTx) || !equalBytes3(leaf.refundTx, operatorLeaf.refundTx)) {
4373
+ ) || !equalBytes3(leaf.nodeTx, operatorLeaf.nodeTx)) {
4368
4374
  leavesToIgnore.add(nodeId);
4369
4375
  }
4370
4376
  }
@@ -4376,7 +4382,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4376
4382
  };
4377
4383
  for (const [id, leaf] of Object.entries(leaves.nodes)) {
4378
4384
  if (!verifyKey(
4379
- await this.config.signer.generatePublicKey(sha2567(leaf.id)),
4385
+ await this.config.signer.generatePublicKey(sha2566(leaf.id)),
4380
4386
  leaf.signingKeyshare?.publicKey ?? new Uint8Array(),
4381
4387
  leaf.verifyingPublicKey
4382
4388
  )) {
@@ -4387,13 +4393,34 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4387
4393
  ([_, node]) => node.status === "AVAILABLE" && !leavesToIgnore.has(node.id)
4388
4394
  ).map(([_, node]) => node);
4389
4395
  }
4390
- async selectLeaves(targetAmount) {
4391
- if (targetAmount <= 0) {
4396
+ async selectLeaves(targetAmounts) {
4397
+ if (targetAmounts.length === 0) {
4398
+ throw new ValidationError("Target amounts must be non-empty", {
4399
+ field: "targetAmounts",
4400
+ value: targetAmounts
4401
+ });
4402
+ }
4403
+ if (targetAmounts.some((amount) => amount <= 0)) {
4392
4404
  throw new ValidationError("Target amount must be positive", {
4393
- field: "targetAmount",
4394
- value: targetAmount
4405
+ field: "targetAmounts",
4406
+ value: targetAmounts
4395
4407
  });
4396
4408
  }
4409
+ const totalTargetAmount = targetAmounts.reduce(
4410
+ (acc, amount) => acc + amount,
4411
+ 0
4412
+ );
4413
+ const totalBalance = this.getInternalBalance();
4414
+ if (totalTargetAmount > totalBalance) {
4415
+ throw new ValidationError(
4416
+ "Total target amount exceeds available balance",
4417
+ {
4418
+ field: "targetAmounts",
4419
+ value: totalTargetAmount,
4420
+ expected: `less than or equal to ${totalBalance}`
4421
+ }
4422
+ );
4423
+ }
4397
4424
  const leaves = await this.getLeaves();
4398
4425
  if (leaves.length === 0) {
4399
4426
  throw new ValidationError("No owned leaves found", {
@@ -4401,33 +4428,49 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4401
4428
  });
4402
4429
  }
4403
4430
  leaves.sort((a, b) => b.value - a.value);
4404
- let amount = 0;
4405
- let nodes = [];
4406
- for (const leaf of leaves) {
4407
- if (targetAmount - amount >= leaf.value) {
4408
- amount += leaf.value;
4409
- nodes.push(leaf);
4410
- }
4411
- }
4412
- if (amount !== targetAmount) {
4413
- await this.requestLeavesSwap({ targetAmount });
4414
- amount = 0;
4415
- nodes = [];
4416
- const newLeaves = await this.getLeaves();
4417
- newLeaves.sort((a, b) => b.value - a.value);
4418
- for (const leaf of newLeaves) {
4419
- if (targetAmount - amount >= leaf.value) {
4420
- amount += leaf.value;
4421
- nodes.push(leaf);
4431
+ const selectLeavesForTargets = (targetAmounts2, leaves2) => {
4432
+ const usedLeaves = /* @__PURE__ */ new Set();
4433
+ const results2 = /* @__PURE__ */ new Map();
4434
+ let totalAmount = 0;
4435
+ for (const targetAmount of targetAmounts2) {
4436
+ const nodes = [];
4437
+ let amount = 0;
4438
+ for (const leaf of leaves2) {
4439
+ if (usedLeaves.has(leaf.id)) {
4440
+ continue;
4441
+ }
4442
+ if (targetAmount - amount >= leaf.value) {
4443
+ amount += leaf.value;
4444
+ nodes.push(leaf);
4445
+ usedLeaves.add(leaf.id);
4446
+ }
4422
4447
  }
4448
+ totalAmount += amount;
4449
+ results2.set(targetAmount, nodes);
4423
4450
  }
4451
+ return {
4452
+ results: results2,
4453
+ foundSelections: totalAmount === totalTargetAmount
4454
+ };
4455
+ };
4456
+ let { results, foundSelections } = selectLeavesForTargets(
4457
+ targetAmounts,
4458
+ leaves
4459
+ );
4460
+ if (!foundSelections) {
4461
+ const newLeaves = await this.requestLeavesSwap({ targetAmounts });
4462
+ newLeaves.sort((a, b) => b.value - a.value);
4463
+ ({ results, foundSelections } = selectLeavesForTargets(
4464
+ targetAmounts,
4465
+ newLeaves
4466
+ ));
4424
4467
  }
4425
- if (nodes.reduce((acc, leaf) => acc + leaf.value, 0) !== targetAmount) {
4468
+ if (!foundSelections) {
4426
4469
  throw new Error(
4427
- `Failed to select leaves for target amount ${targetAmount}`
4470
+ `Failed to select leaves for target amount ${totalTargetAmount}`
4428
4471
  );
4429
4472
  }
4430
- return nodes;
4473
+ return results;
4431
4474
  }
4432
4475
  async selectLeavesForSwap(targetAmount) {
4433
4476
  if (targetAmount == 0) {
@@ -4660,27 +4703,44 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4660
4703
  * @private
4661
4704
  */
4662
4705
  async requestLeavesSwap({
4663
- targetAmount,
4706
+ targetAmounts,
4664
4707
  leaves
4665
4708
  }) {
4666
- if (targetAmount && targetAmount <= 0) {
4667
- throw new Error("targetAmount must be positive");
4709
+ if (targetAmounts && targetAmounts.some((amount) => amount <= 0)) {
4710
+ throw new Error("specified targetAmount must be positive");
4668
4711
  }
4669
- if (targetAmount && !Number.isSafeInteger(targetAmount)) {
4712
+ if (targetAmounts && targetAmounts.some((amount) => !Number.isSafeInteger(amount))) {
4670
4713
  throw new ValidationError("targetAmount must be less than 2^53", {
4671
- field: "targetAmount",
4672
- value: targetAmount,
4714
+ field: "targetAmounts",
4715
+ value: targetAmounts,
4673
4716
  expected: "smaller or equal to " + Number.MAX_SAFE_INTEGER
4674
4717
  });
4675
4718
  }
4676
4719
  let leavesToSwap;
4677
- if (targetAmount && leaves && leaves.length > 0) {
4678
- if (targetAmount < leaves.reduce((acc, leaf) => acc + leaf.value, 0)) {
4720
+ const totalTargetAmount = targetAmounts?.reduce(
4721
+ (acc, amount) => acc + amount,
4722
+ 0
4723
+ );
4724
+ if (totalTargetAmount) {
4725
+ const totalBalance = this.getInternalBalance();
4726
+ if (totalTargetAmount > totalBalance) {
4727
+ throw new ValidationError(
4728
+ "Total target amount exceeds available balance",
4729
+ {
4730
+ field: "targetAmounts",
4731
+ value: totalTargetAmount,
4732
+ expected: `less than or equal to ${totalBalance}`
4733
+ }
4734
+ );
4735
+ }
4736
+ }
4737
+ if (totalTargetAmount && leaves && leaves.length > 0) {
4738
+ if (totalTargetAmount < leaves.reduce((acc, leaf) => acc + leaf.value, 0)) {
4679
4739
  throw new Error("targetAmount is less than the sum of leaves");
4680
4740
  }
4681
4741
  leavesToSwap = leaves;
4682
- } else if (targetAmount) {
4683
- leavesToSwap = await this.selectLeavesForSwap(targetAmount);
4742
+ } else if (totalTargetAmount) {
4743
+ leavesToSwap = await this.selectLeavesForSwap(totalTargetAmount);
4684
4744
  } else if (leaves && leaves.length > 0) {
4685
4745
  leavesToSwap = leaves;
4686
4746
  } else {
@@ -4690,20 +4750,20 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4690
4750
  const batches = chunkArray(leavesToSwap, 100);
4691
4751
  const results = [];
4692
4752
  for (const batch of batches) {
4693
- const result = await this.processSwapBatch(batch, targetAmount);
4694
- results.push(...result.swapLeaves);
4753
+ const result = await this.processSwapBatch(batch, targetAmounts);
4754
+ results.push(...result);
4695
4755
  }
4696
4756
  return results;
4697
4757
  }
4698
4758
  /**
4699
4759
  * Processes a single batch of leaves for swapping.
4700
4760
  */
4701
- async processSwapBatch(leavesBatch, targetAmount) {
4761
+ async processSwapBatch(leavesBatch, targetAmounts) {
4702
4762
  const leafKeyTweaks = await Promise.all(
4703
4763
  leavesBatch.map(async (leaf) => ({
4704
4764
  leaf,
4705
4765
  signingPubKey: await this.config.signer.generatePublicKey(
4706
- sha2567(leaf.id)
4766
+ sha2566(leaf.id)
4707
4767
  ),
4708
4768
  newSigningPubKey: await this.config.signer.generatePublicKey()
4709
4769
  }))
@@ -4756,14 +4816,15 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4756
4816
  }
4757
4817
  const sspClient = this.getSspClient();
4758
4818
  const adaptorPubkey = bytesToHex4(
4759
- secp256k16.getPublicKey(adaptorPrivateKey)
4819
+ secp256k15.getPublicKey(adaptorPrivateKey)
4760
4820
  );
4761
4821
  let request = null;
4762
4822
  request = await sspClient.requestLeaveSwap({
4763
4823
  userLeaves,
4764
4824
  adaptorPubkey,
4765
- targetAmountSats: targetAmount || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
4825
+ targetAmountSats: targetAmounts?.reduce((acc, amount) => acc + amount, 0) || leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
4766
4826
  totalAmountSats: leavesBatch.reduce((acc, leaf) => acc + leaf.value, 0),
4827
+ targetAmountSatsList: targetAmounts,
4767
4828
  // TODO: Request fee from SSP
4768
4829
  feeSats: 0,
4769
4830
  idempotencyKey: uuidv74()
@@ -4819,11 +4880,21 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4819
4880
  userOutboundTransferExternalId: transfer.id,
4820
4881
  leavesSwapRequestId: request.id
4821
4882
  });
4822
- if (!completeResponse) {
4883
+ if (!completeResponse || !completeResponse.inboundTransfer?.sparkId) {
4823
4884
  throw new Error("Failed to complete leaves swap");
4824
4885
  }
4825
- await this.claimTransfers(40 /* COUNTER_SWAP */);
4826
- return completeResponse;
4886
+ const incomingTransfer = await this.transferService.queryTransfer(
4887
+ completeResponse.inboundTransfer.sparkId
4888
+ );
4889
+ if (!incomingTransfer) {
4890
+ throw new Error("Failed to get incoming transfer");
4891
+ }
4892
+ return await this.claimTransfer({
4893
+ transfer: incomingTransfer,
4894
+ emit: false,
4895
+ retryCount: 0,
4896
+ optimize: false
4897
+ });
4827
4898
  } catch (e) {
4828
4899
  await this.cancelAllSenderInitiatedTransfers();
4829
4900
  throw new Error(`Failed to request leaves swap: ${e}`);
@@ -4851,27 +4922,6 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4851
4922
  offset: transfers.offset
4852
4923
  };
4853
4924
  }
4854
- /**
4855
- * Gets the held token info for the wallet.
4856
- *
4857
- * @deprecated The information is returned in getBalance
4858
- */
4859
- async getTokenInfo() {
4860
- console.warn("getTokenInfo is deprecated. Use getBalance instead.");
4861
- await this.syncTokenOutputs();
4862
- const lrc20Client = await this.lrc20ConnectionManager.createLrc20Client();
4863
- const { balance, tokenBalances } = await this.getBalance();
4864
- const tokenInfo = await lrc20Client.getTokenPubkeyInfo({
4865
- publicKeys: Array.from(tokenBalances.keys()).map(hexToBytes7)
4866
- });
4867
- return tokenInfo.tokenPubkeyInfos.map((info) => ({
4868
- tokenPublicKey: bytesToHex4(info.announcement.publicKey.publicKey),
4869
- tokenName: info.announcement.name,
4870
- tokenSymbol: info.announcement.symbol,
4871
- tokenDecimals: Number(bytesToNumberBE2(info.announcement.decimal)),
4872
- maxSupply: bytesToNumberBE2(info.announcement.maxSupply)
4873
- }));
4874
- }
4875
4925
  /**
4876
4926
  * Gets the current balance of the wallet.
4877
4927
  * You can use the forceRefetch option to synchronize your wallet and claim any
@@ -4879,7 +4929,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4879
4929
  *
4880
4930
  * @returns {Promise<Object>} Object containing:
4881
4931
  * - balance: The wallet's current balance in satoshis
4882
- * - tokenBalances: Map of token public keys to token balances and token info
4932
+ * - tokenBalances: Map of the human readable token identifier to token balances and token info
4883
4933
  */
4884
4934
  async getBalance() {
4885
4935
  const leaves = await this.getLeaves(true);
@@ -4896,24 +4946,29 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4896
4946
  };
4897
4947
  }
4898
4948
  async getTokenBalance() {
4899
- const lrc20Client = await this.lrc20ConnectionManager.createLrc20Client();
4900
- const tokenInfo = await lrc20Client.getTokenPubkeyInfo({
4901
- publicKeys: Array.from(this.tokenOutputs.keys()).map(hexToBytes7)
4949
+ const sparkTokenClient = await this.connectionManager.createSparkTokenClient(
4950
+ this.config.getCoordinatorAddress()
4951
+ );
4952
+ const tokenMetadata = await sparkTokenClient.query_token_metadata({
4953
+ issuerPublicKeys: Array.from(this.tokenOutputs.keys()).map(hexToBytes7)
4902
4954
  });
4903
4955
  const result = /* @__PURE__ */ new Map();
4904
- for (const info of tokenInfo.tokenPubkeyInfos) {
4905
- const tokenPublicKey = bytesToHex4(
4906
- info.announcement.publicKey.publicKey
4907
- );
4956
+ for (const metadata of tokenMetadata.tokenMetadata) {
4957
+ const tokenPublicKey = bytesToHex4(metadata.issuerPublicKey);
4908
4958
  const leaves = this.tokenOutputs.get(tokenPublicKey);
4909
- result.set(tokenPublicKey, {
4959
+ const humanReadableTokenIdentifier = encodeHumanReadableTokenIdentifier({
4960
+ tokenIdentifier: metadata.tokenIdentifier,
4961
+ network: this.config.getNetworkType()
4962
+ });
4963
+ result.set(humanReadableTokenIdentifier, {
4910
4964
  balance: leaves ? calculateAvailableTokenAmount(leaves) : BigInt(0),
4911
- tokenInfo: {
4965
+ tokenMetadata: {
4912
4966
  tokenPublicKey,
4913
- tokenName: info.announcement.name,
4914
- tokenSymbol: info.announcement.symbol,
4915
- tokenDecimals: Number(bytesToNumberBE2(info.announcement.decimal)),
4916
- maxSupply: bytesToNumberBE2(info.announcement.maxSupply)
4967
+ rawTokenIdentifier: metadata.tokenIdentifier,
4968
+ tokenName: metadata.tokenName,
4969
+ tokenTicker: metadata.tokenTicker,
4970
+ decimals: metadata.decimals,
4971
+ maxSupply: bytesToNumberBE2(metadata.maxSupply)
4917
4972
  }
4918
4973
  });
4919
4974
  }
@@ -4971,7 +5026,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
4971
5026
  signingPubkey = await this.config.signer.generateStaticDepositKey(0);
4972
5027
  } else {
4973
5028
  signingPubkey = await this.config.signer.generatePublicKey(
4974
- sha2567(leafId)
5029
+ sha2566(leafId)
4975
5030
  );
4976
5031
  }
4977
5032
  const address = await this.depositService.generateDepositAddress({
@@ -5058,7 +5113,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5058
5113
  creditAmountSats,
5059
5114
  sspSignature
5060
5115
  );
5061
- const hashBuffer = sha2567(message);
5116
+ const hashBuffer = sha2566(message);
5062
5117
  const signatureBytes = await this.config.signer.signMessageWithIdentityKey(hashBuffer);
5063
5118
  const signature = bytesToHex4(signatureBytes);
5064
5119
  const response = await this.sspClient.claimStaticDeposit({
@@ -5147,7 +5202,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5147
5202
  creditAmountSats,
5148
5203
  bytesToHex4(spendTxSighash)
5149
5204
  );
5150
- const hashBuffer = sha2567(message);
5205
+ const hashBuffer = sha2566(message);
5151
5206
  const swapResponseUserSignature = await this.config.signer.signMessageWithIdentityKey(hashBuffer);
5152
5207
  const sparkClient = await this.connectionManager.createSparkClient(
5153
5208
  this.config.getCoordinatorAddress()
@@ -5360,13 +5415,45 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5360
5415
  * @returns {Promise<string[]>} The unused deposit addresses
5361
5416
  */
5362
5417
  async getUnusedDepositAddresses() {
5418
+ return (await this.queryAllUnusedDepositAddresses({})).map(
5419
+ (addr) => addr.depositAddress
5420
+ );
5421
+ }
5422
+ /**
5423
+ * Gets all unused deposit addresses for the wallet.
5424
+ *
5425
+ * @param {Object} params - Parameters for querying unused deposit addresses
5426
+ * @param {Uint8Array<ArrayBufferLike>} [params.identityPublicKey] - The identity public key
5427
+ * @param {NetworkProto} [params.network] - The network
5428
+ * @returns {Promise<DepositAddressQueryResult[]>} The unused deposit addresses
5429
+ */
5430
+ async queryAllUnusedDepositAddresses({
5431
+ identityPublicKey,
5432
+ network
5433
+ }) {
5363
5434
  const sparkClient = await this.connectionManager.createSparkClient(
5364
5435
  this.config.getCoordinatorAddress()
5365
5436
  );
5366
- return (await sparkClient.query_unused_deposit_addresses({
5367
- identityPublicKey: await this.config.signer.getIdentityPublicKey(),
5368
- network: NetworkToProto[this.config.getNetwork()]
5369
- })).depositAddresses.map((addr) => addr.depositAddress);
5437
+ let limit = 100;
5438
+ let offset = 0;
5439
+ const pastOffsets = /* @__PURE__ */ new Set();
5440
+ const depositAddresses = [];
5441
+ while (offset >= 0) {
5442
+ if (pastOffsets.has(offset)) {
5443
+ console.warn("Offset has already been seen, stopping");
5444
+ break;
5445
+ }
5446
+ const response = await sparkClient.query_unused_deposit_addresses({
5447
+ identityPublicKey: identityPublicKey ?? await this.config.signer.getIdentityPublicKey(),
5448
+ network: network ?? NetworkToProto[this.config.getNetwork()],
5449
+ limit,
5450
+ offset
5451
+ });
5452
+ depositAddresses.push(...response.depositAddresses);
5453
+ pastOffsets.add(offset);
5454
+ offset = response.offset;
5455
+ }
5456
+ return depositAddresses;
5370
5457
  }
5371
5458
  /**
5372
5459
  * Claims a deposit to the wallet.
@@ -5415,14 +5502,11 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5415
5502
  });
5416
5503
  }
5417
5504
  const depositTx = getTxFromRawTxHex(txHex);
5418
- const sparkClient = await this.connectionManager.createSparkClient(
5419
- this.config.getCoordinatorAddress()
5420
- );
5421
5505
  const unusedDepositAddresses = new Map(
5422
- (await sparkClient.query_unused_deposit_addresses({
5506
+ (await this.queryAllUnusedDepositAddresses({
5423
5507
  identityPublicKey: await this.config.signer.getIdentityPublicKey(),
5424
5508
  network: NetworkToProto[this.config.getNetwork()]
5425
- })).depositAddresses.map((addr) => [addr.depositAddress, addr])
5509
+ })).map((addr) => [addr.depositAddress, addr])
5426
5510
  );
5427
5511
  let depositAddress;
5428
5512
  let vout = 0;
@@ -5452,7 +5536,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5452
5536
  signingPubKey = depositAddress.userSigningPublicKey;
5453
5537
  } else {
5454
5538
  signingPubKey = await this.config.signer.generatePublicKey(
5455
- sha2567(depositAddress.leafId)
5539
+ sha2566(depositAddress.leafId)
5456
5540
  );
5457
5541
  }
5458
5542
  const nodes2 = await this.finalizeDeposit({
@@ -5476,14 +5560,11 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5476
5560
  */
5477
5561
  async advancedDeposit(txHex) {
5478
5562
  const depositTx = getTxFromRawTxHex(txHex);
5479
- const sparkClient = await this.connectionManager.createSparkClient(
5480
- this.config.getCoordinatorAddress()
5481
- );
5482
5563
  const unusedDepositAddresses = new Map(
5483
- (await sparkClient.query_unused_deposit_addresses({
5564
+ (await this.queryAllUnusedDepositAddresses({
5484
5565
  identityPublicKey: await this.config.signer.getIdentityPublicKey(),
5485
5566
  network: NetworkToProto[this.config.getNetwork()]
5486
- })).depositAddresses.map((addr) => [addr.depositAddress, addr])
5567
+ })).map((addr) => [addr.depositAddress, addr])
5487
5568
  );
5488
5569
  let vout = 0;
5489
5570
  const responses = [];
@@ -5587,14 +5668,16 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5587
5668
  hexToBytes7(receiverAddress.identityPublicKey)
5588
5669
  );
5589
5670
  return await this.withLeaves(async () => {
5590
- let leavesToSend = await this.selectLeaves(amountSats);
5671
+ let leavesToSend = (await this.selectLeaves([amountSats])).get(
5672
+ amountSats
5673
+ );
5591
5674
  leavesToSend = await this.checkRefreshTimelockNodes(leavesToSend);
5592
5675
  leavesToSend = await this.checkExtendTimeLockNodes(leavesToSend);
5593
5676
  const leafKeyTweaks = await Promise.all(
5594
5677
  leavesToSend.map(async (leaf) => ({
5595
5678
  leaf,
5596
5679
  signingPubKey: await this.config.signer.generatePublicKey(
5597
- sha2567(leaf.id)
5680
+ sha2566(leaf.id)
5598
5681
  ),
5599
5682
  newSigningPubKey: await this.config.signer.generatePublicKey()
5600
5683
  }))
@@ -5643,7 +5726,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5643
5726
  const nodesToAdd = [];
5644
5727
  for (const node of nodesToExtend) {
5645
5728
  const signingPubKey = await this.config.signer.generatePublicKey(
5646
- sha2567(node.id)
5729
+ sha2566(node.id)
5647
5730
  );
5648
5731
  const { nodes: nodes2 } = await this.transferService.extendTimelock(
5649
5732
  node,
@@ -5710,7 +5793,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5710
5793
  const { nodes: nodes2 } = await this.transferService.refreshTimelockNodes(
5711
5794
  [node],
5712
5795
  parentNode,
5713
- await this.config.signer.generatePublicKey(sha2567(node.id))
5796
+ await this.config.signer.generatePublicKey(sha2566(node.id))
5714
5797
  );
5715
5798
  if (nodes2.length !== 1) {
5716
5799
  throw new Error(`expected 1 node, got ${nodes2.length}`);
@@ -5762,7 +5845,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5762
5845
  },
5763
5846
  signingPubKey: leafPubKey,
5764
5847
  newSigningPubKey: await this.config.signer.generatePublicKey(
5765
- sha2567(leaf.leaf.id)
5848
+ sha2566(leaf.leaf.id)
5766
5849
  )
5767
5850
  });
5768
5851
  }
@@ -5830,7 +5913,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5830
5913
  if (type && transfer.type !== type) {
5831
5914
  continue;
5832
5915
  }
5833
- if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /* TRANSFER_STATUSR_RECEIVER_REFUND_SIGNED */ && transfer.status !== 10 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_APPLIED */) {
5916
+ if (transfer.status !== 2 /* TRANSFER_STATUS_SENDER_KEY_TWEAKED */ && transfer.status !== 3 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAKED */ && transfer.status !== 4 /* TRANSFER_STATUS_RECEIVER_REFUND_SIGNED */ && transfer.status !== 10 /* TRANSFER_STATUS_RECEIVER_KEY_TWEAK_APPLIED */) {
5834
5917
  continue;
5835
5918
  }
5836
5919
  promises.push(
@@ -5955,22 +6038,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5955
6038
  const sparkFallbackAddress = decodeInvoice(
5956
6039
  invoice2.invoice.encodedInvoice
5957
6040
  ).fallbackAddress;
5958
- if (sparkFallbackAddress && isValidSparkFallback(hexToBytes7(sparkFallbackAddress))) {
5959
- const invoiceIdentityPubkey = sparkFallbackAddress.slice(6);
5960
- const expectedIdentityPubkey = receiverIdentityPubkey2 ?? await this.getIdentityPublicKey();
5961
- if (invoiceIdentityPubkey !== expectedIdentityPubkey) {
5962
- throw new ValidationError(
5963
- "Mismatch between spark identity embedded in lightning invoice and designated recipient spark identity",
5964
- {
5965
- field: "sparkFallbackAddress",
5966
- value: invoiceIdentityPubkey,
5967
- expected: expectedIdentityPubkey
5968
- }
5969
- );
5970
- }
5971
- } else {
6041
+ if (!sparkFallbackAddress) {
5972
6042
  throw new ValidationError(
5973
- "No valid spark fallback address found in lightning invoice",
6043
+ "No spark fallback address found in lightning invoice",
5974
6044
  {
5975
6045
  field: "sparkFallbackAddress",
5976
6046
  value: sparkFallbackAddress,
@@ -5978,6 +6048,17 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
5978
6048
  }
5979
6049
  );
5980
6050
  }
6051
+ const expectedIdentityPubkey = receiverIdentityPubkey2 ?? await this.getIdentityPublicKey();
6052
+ if (sparkFallbackAddress !== expectedIdentityPubkey) {
6053
+ throw new ValidationError(
6054
+ "Mismatch between spark identity embedded in lightning invoice and designated recipient spark identity",
6055
+ {
6056
+ field: "sparkFallbackAddress",
6057
+ value: sparkFallbackAddress,
6058
+ expected: expectedIdentityPubkey
6059
+ }
6060
+ );
6061
+ }
5981
6062
  }
5982
6063
  return invoice2;
5983
6064
  };
@@ -6056,9 +6137,8 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6056
6137
  "No valid spark address found in invoice. Defaulting to lightning."
6057
6138
  );
6058
6139
  } else {
6059
- const identityPublicKey = sparkFallbackAddress.slice(6);
6060
6140
  const receiverSparkAddress = encodeSparkAddress({
6061
- identityPublicKey,
6141
+ identityPublicKey: sparkFallbackAddress,
6062
6142
  network: Network[invoiceNetwork]
6063
6143
  });
6064
6144
  return await this.transfer({
@@ -6089,14 +6169,14 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6089
6169
  expected: `${totalAmount} sats`
6090
6170
  });
6091
6171
  }
6092
- let leaves = await this.selectLeaves(totalAmount);
6172
+ let leaves = (await this.selectLeaves([totalAmount])).get(totalAmount);
6093
6173
  leaves = await this.checkRefreshTimelockNodes(leaves);
6094
6174
  leaves = await this.checkExtendTimeLockNodes(leaves);
6095
6175
  const leavesToSend = await Promise.all(
6096
6176
  leaves.map(async (leaf) => ({
6097
6177
  leaf,
6098
6178
  signingPubKey: await this.config.signer.generatePublicKey(
6099
- sha2567(leaf.id)
6179
+ sha2566(leaf.id)
6100
6180
  ),
6101
6181
  newSigningPubKey: await this.config.signer.generatePublicKey()
6102
6182
  }))
@@ -6199,13 +6279,18 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6199
6279
  *
6200
6280
  * @param {Object} params - Parameters for the withdrawal
6201
6281
  * @param {string} params.onchainAddress - The Bitcoin address where the funds should be sent
6202
- * @param {number} [params.amountSats] - The amount in satoshis to withdraw. If not specified, attempts to withdraw all available funds
6282
+ * @param {CoopExitFeeQuote} params.feeQuote - The fee quote for the withdrawal
6283
+ * @param {ExitSpeed} params.exitSpeed - The exit speed chosen for the withdrawal
6284
+ * @param {number} [params.amountSats] - The amount in satoshis to withdraw. If not specified, attempts to withdraw all available funds and deductFeeFromWithdrawalAmount is set to true.
6285
+ * @param {boolean} [params.deductFeeFromWithdrawalAmount] - Controls how the withdrawal fee is handled. If true, the fee is deducted from the withdrawal amount (amountSats), meaning the recipient will receive amountSats minus the fee. If false, the fee is paid separately from the wallet balance, meaning the recipient will receive the full amountSats.
6203
6286
  * @returns {Promise<CoopExitRequest | null | undefined>} The withdrawal request details, or null/undefined if the request cannot be completed
6204
6287
  */
6205
6288
  async withdraw({
6206
6289
  onchainAddress,
6207
6290
  exitSpeed,
6208
- amountSats
6291
+ feeQuote,
6292
+ amountSats,
6293
+ deductFeeFromWithdrawalAmount = true
6209
6294
  }) {
6210
6295
  if (!Number.isSafeInteger(amountSats)) {
6211
6296
  throw new ValidationError("Sats amount must be less than 2^53", {
@@ -6215,7 +6300,13 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6215
6300
  });
6216
6301
  }
6217
6302
  return await this.withLeaves(async () => {
6218
- return await this.coopExit(onchainAddress, exitSpeed, amountSats);
6303
+ return await this.coopExit(
6304
+ onchainAddress,
6305
+ feeQuote,
6306
+ exitSpeed,
6307
+ deductFeeFromWithdrawalAmount,
6308
+ amountSats
6309
+ );
6219
6310
  });
6220
6311
  }
6221
6312
  /**
@@ -6226,7 +6317,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6226
6317
  * @returns {Promise<Object | null | undefined>} The exit request details
6227
6318
  * @private
6228
6319
  */
6229
- async coopExit(onchainAddress, exitSpeed, targetAmountSats) {
6320
+ async coopExit(onchainAddress, feeEstimate, exitSpeed, deductFeeFromWithdrawalAmount, targetAmountSats) {
6230
6321
  if (!Number.isSafeInteger(targetAmountSats)) {
6231
6322
  throw new ValidationError("Sats amount must be less than 2^53", {
6232
6323
  field: "targetAmountSats",
@@ -6234,41 +6325,34 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6234
6325
  expected: "smaller or equal to " + Number.MAX_SAFE_INTEGER
6235
6326
  });
6236
6327
  }
6237
- let leavesToSend = [];
6238
- if (targetAmountSats) {
6239
- leavesToSend = await this.selectLeaves(targetAmountSats);
6240
- } else {
6241
- leavesToSend = this.leaves.map((leaf) => ({
6242
- ...leaf
6243
- }));
6328
+ if (!targetAmountSats) {
6329
+ deductFeeFromWithdrawalAmount = true;
6244
6330
  }
6245
- const sspClient = this.getSspClient();
6246
- const feeEstimate = await sspClient.getCoopExitFeeEstimate({
6247
- leafExternalIds: leavesToSend.map((leaf) => leaf.id),
6248
- withdrawalAddress: onchainAddress
6249
- });
6250
- if (feeEstimate) {
6251
- let fee;
6252
- switch (exitSpeed) {
6253
- case ExitSpeed_default.FAST:
6254
- fee = (feeEstimate.speedFast?.l1BroadcastFee.originalValue || 0) + (feeEstimate.speedFast?.userFee.originalValue || 0);
6255
- break;
6256
- case ExitSpeed_default.MEDIUM:
6257
- fee = (feeEstimate.speedMedium?.l1BroadcastFee.originalValue || 0) + (feeEstimate.speedMedium?.userFee.originalValue || 0);
6258
- break;
6259
- case ExitSpeed_default.SLOW:
6260
- fee = (feeEstimate.speedSlow?.l1BroadcastFee.originalValue || 0) + (feeEstimate.speedSlow?.userFee.originalValue || 0);
6261
- break;
6262
- default:
6263
- throw new ValidationError("Invalid exit speed", {
6264
- field: "exitSpeed",
6265
- value: exitSpeed,
6266
- expected: "FAST, MEDIUM, or SLOW"
6267
- });
6268
- }
6269
- if (fee !== void 0 && fee > leavesToSend.reduce((acc, leaf) => acc + leaf.value, 0)) {
6331
+ let fee;
6332
+ switch (exitSpeed) {
6333
+ case ExitSpeed_default.FAST:
6334
+ fee = (feeEstimate.l1BroadcastFeeFast?.originalValue || 0) + (feeEstimate.userFeeFast?.originalValue || 0);
6335
+ break;
6336
+ case ExitSpeed_default.MEDIUM:
6337
+ fee = (feeEstimate.l1BroadcastFeeMedium?.originalValue || 0) + (feeEstimate.userFeeMedium?.originalValue || 0);
6338
+ break;
6339
+ case ExitSpeed_default.SLOW:
6340
+ fee = (feeEstimate.l1BroadcastFeeSlow?.originalValue || 0) + (feeEstimate.userFeeSlow?.originalValue || 0);
6341
+ break;
6342
+ default:
6343
+ throw new ValidationError("Invalid exit speed", {
6344
+ field: "exitSpeed",
6345
+ value: exitSpeed,
6346
+ expected: "FAST, MEDIUM, or SLOW"
6347
+ });
6348
+ }
6349
+ let leavesToSendToSsp = [];
6350
+ let leavesToSendToSE = [];
6351
+ if (deductFeeFromWithdrawalAmount) {
6352
+ leavesToSendToSsp = targetAmountSats ? (await this.selectLeaves([targetAmountSats])).get(targetAmountSats) : this.leaves;
6353
+ if (fee > leavesToSendToSsp.reduce((acc, leaf) => acc + leaf.value, 0)) {
6270
6354
  throw new ValidationError(
6271
- "The fee for the withdrawal is greater than the target amount",
6355
+ "The fee for the withdrawal is greater than the target withdrawal amount",
6272
6356
  {
6273
6357
  field: "fee",
6274
6358
  value: fee,
@@ -6276,25 +6360,56 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6276
6360
  }
6277
6361
  );
6278
6362
  }
6363
+ } else {
6364
+ if (!targetAmountSats) {
6365
+ throw new ValidationError(
6366
+ "targetAmountSats is required when deductFeeFromWithdrawalAmount is false",
6367
+ {
6368
+ field: "targetAmountSats",
6369
+ value: targetAmountSats,
6370
+ expected: "defined when deductFeeFromWithdrawalAmount is false"
6371
+ }
6372
+ );
6373
+ }
6374
+ const leaves = await this.selectLeaves([targetAmountSats, fee]);
6375
+ const leavesForTargetAmount = leaves.get(targetAmountSats);
6376
+ const leavesForFee = leaves.get(fee);
6377
+ if (!leavesForTargetAmount || !leavesForFee) {
6378
+ throw new Error("Failed to select leaves for target amount and fee");
6379
+ }
6380
+ leavesToSendToSsp = leavesForTargetAmount;
6381
+ leavesToSendToSE = leavesForFee;
6279
6382
  }
6280
- leavesToSend = await this.checkRefreshTimelockNodes(leavesToSend);
6281
- leavesToSend = await this.checkExtendTimeLockNodes(leavesToSend);
6383
+ leavesToSendToSsp = await this.checkRefreshTimelockNodes(leavesToSendToSsp);
6384
+ leavesToSendToSsp = await this.checkExtendTimeLockNodes(leavesToSendToSsp);
6385
+ leavesToSendToSE = await this.checkRefreshTimelockNodes(leavesToSendToSE);
6386
+ leavesToSendToSE = await this.checkExtendTimeLockNodes(leavesToSendToSE);
6282
6387
  const leafKeyTweaks = await Promise.all(
6283
- leavesToSend.map(async (leaf) => ({
6388
+ [...leavesToSendToSE, ...leavesToSendToSsp].map(async (leaf) => ({
6284
6389
  leaf,
6285
6390
  signingPubKey: await this.config.signer.generatePublicKey(
6286
- sha2567(leaf.id)
6391
+ sha2566(leaf.id)
6287
6392
  ),
6288
6393
  newSigningPubKey: await this.config.signer.generatePublicKey()
6289
6394
  }))
6290
6395
  );
6291
- const coopExitRequest = await sspClient.requestCoopExit({
6292
- leafExternalIds: leavesToSend.map((leaf) => leaf.id),
6396
+ const requestCoopExitParams = {
6397
+ leafExternalIds: leavesToSendToSsp.map((leaf) => leaf.id),
6293
6398
  withdrawalAddress: onchainAddress,
6294
6399
  idempotencyKey: uuidv74(),
6295
6400
  exitSpeed,
6296
- withdrawAll: true
6297
- });
6401
+ withdrawAll: deductFeeFromWithdrawalAmount
6402
+ };
6403
+ if (!deductFeeFromWithdrawalAmount) {
6404
+ requestCoopExitParams.feeQuoteId = feeEstimate.id;
6405
+ requestCoopExitParams.feeLeafExternalIds = leavesToSendToSE.map(
6406
+ (leaf) => leaf.id
6407
+ );
6408
+ }
6409
+ const sspClient = this.getSspClient();
6410
+ const coopExitRequest = await sspClient.requestCoopExit(
6411
+ requestCoopExitParams
6412
+ );
6298
6413
  if (!coopExitRequest?.rawConnectorTransaction) {
6299
6414
  throw new Error("Failed to request coop exit");
6300
6415
  }
@@ -6332,9 +6447,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6332
6447
  * @param {Object} params - Input parameters for fee estimation
6333
6448
  * @param {number} params.amountSats - The amount in satoshis to withdraw
6334
6449
  * @param {string} params.withdrawalAddress - The Bitcoin address where the funds should be sent
6335
- * @returns {Promise<CoopExitFeeEstimatesOutput | null>} Fee estimate for the withdrawal
6450
+ * @returns {Promise<CoopExitFeeQuote | null>} Fee estimate for the withdrawal
6336
6451
  */
6337
- async getWithdrawalFeeEstimate({
6452
+ async getWithdrawalFeeQuote({
6338
6453
  amountSats,
6339
6454
  withdrawalAddress
6340
6455
  }) {
@@ -6346,10 +6461,10 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6346
6461
  expected: "smaller or equal to " + Number.MAX_SAFE_INTEGER
6347
6462
  });
6348
6463
  }
6349
- let leaves = await this.selectLeaves(amountSats);
6464
+ let leaves = (await this.selectLeaves([amountSats])).get(amountSats);
6350
6465
  leaves = await this.checkRefreshTimelockNodes(leaves);
6351
6466
  leaves = await this.checkExtendTimeLockNodes(leaves);
6352
- const feeEstimate = await sspClient.getCoopExitFeeEstimate({
6467
+ const feeEstimate = await sspClient.getCoopExitFeeQuote({
6353
6468
  leafExternalIds: leaves.map((leaf) => leaf.id),
6354
6469
  withdrawalAddress
6355
6470
  });
@@ -6374,7 +6489,14 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6374
6489
  * @returns {Promise<Transfer | undefined>} The transfer
6375
6490
  */
6376
6491
  async getTransfer(id) {
6377
- return await this.transferService.queryTransfer(id);
6492
+ const transfer = await this.transferService.queryTransfer(id);
6493
+ if (!transfer) {
6494
+ return void 0;
6495
+ }
6496
+ return mapTransferToWalletTransfer(
6497
+ transfer,
6498
+ bytesToHex4(await this.config.signer.getIdentityPublicKey())
6499
+ );
6378
6500
  }
6379
6501
  // ***** Token Flow *****
6380
6502
  /**
@@ -6385,10 +6507,9 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6385
6507
  */
6386
6508
  async syncTokenOutputs() {
6387
6509
  this.tokenOutputs.clear();
6388
- const unsortedTokenOutputs = await this.tokenTransactionService.fetchOwnedTokenOutputs(
6389
- [await this.config.signer.getIdentityPublicKey()],
6390
- []
6391
- );
6510
+ const unsortedTokenOutputs = await this.tokenTransactionService.fetchOwnedTokenOutputs({
6511
+ ownerPublicKeys: [await this.config.signer.getIdentityPublicKey()]
6512
+ });
6392
6513
  const filteredTokenOutputs = unsortedTokenOutputs.filter(
6393
6514
  (output) => !this.pendingWithdrawnOutputIds.includes(output.output?.id || "")
6394
6515
  );
@@ -6487,29 +6608,21 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6487
6608
  * Retrieves token transaction history for specified tokens owned by the wallet.
6488
6609
  * Can optionally filter by specific transaction hashes.
6489
6610
  *
6490
- * @param tokenPublicKeys - Array of token public keys to query transactions for
6611
+ * @param ownerPublicKeys - Optional array of owner public keys to query transactions for
6612
+ * @param issuerPublicKeys - Optional array of issuer public keys to query transactions for
6491
6613
  * @param tokenTransactionHashes - Optional array of specific transaction hashes to filter by
6614
+ * @param tokenIdentifiers - Optional array of token identifiers to filter by
6615
+ * @param outputIds - Optional array of output IDs to filter by
6492
6616
  * @returns Promise resolving to array of token transactions with their current status
6493
6617
  */
6494
- async queryTokenTransactions(tokenPublicKeys, tokenTransactionHashes) {
6495
- const sparkClient = await this.connectionManager.createSparkClient(
6496
- this.config.getCoordinatorAddress()
6497
- );
6498
- let queryParams;
6499
- if (tokenTransactionHashes?.length) {
6500
- queryParams = {
6501
- tokenPublicKeys: tokenPublicKeys?.map(hexToBytes7),
6502
- ownerPublicKeys: [hexToBytes7(await this.getIdentityPublicKey())],
6503
- tokenTransactionHashes: tokenTransactionHashes.map(hexToBytes7)
6504
- };
6505
- } else {
6506
- queryParams = {
6507
- tokenPublicKeys: tokenPublicKeys?.map(hexToBytes7),
6508
- ownerPublicKeys: [hexToBytes7(await this.getIdentityPublicKey())]
6509
- };
6510
- }
6511
- const response = await sparkClient.query_token_transactions(queryParams);
6512
- return response.tokenTransactionsWithStatus;
6618
+ async queryTokenTransactions(ownerPublicKeys, issuerPublicKeys, tokenTransactionHashes, tokenIdentifiers, outputIds) {
6619
+ return this.tokenTransactionService.queryTokenTransactions({
6620
+ ownerPublicKeys,
6621
+ issuerPublicKeys,
6622
+ tokenTransactionHashes,
6623
+ tokenIdentifiers,
6624
+ outputIds
6625
+ });
6513
6626
  }
6514
6627
  async getTokenL1Address() {
6515
6628
  return getP2WPKHAddressFromPublicKey(
@@ -6525,7 +6638,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6525
6638
  * @returns {Promise<string>} The signed message
6526
6639
  */
6527
6640
  async signMessageWithIdentityKey(message, compact) {
6528
- const hash = sha2567(message);
6641
+ const hash = sha2566(message);
6529
6642
  const signature = await this.config.signer.signMessageWithIdentityKey(
6530
6643
  hash,
6531
6644
  compact
@@ -6540,7 +6653,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6540
6653
  * @returns {Promise<boolean>} Whether the message is valid
6541
6654
  */
6542
6655
  async validateMessageWithIdentityKey(message, signature) {
6543
- const hash = sha2567(message);
6656
+ const hash = sha2566(message);
6544
6657
  if (typeof signature === "string") {
6545
6658
  signature = hexToBytes7(signature);
6546
6659
  }
@@ -6847,7 +6960,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6847
6960
  });
6848
6961
  }
6849
6962
  const signingPubKey = await this.config.signer.generatePublicKey(
6850
- sha2567(node.id)
6963
+ sha2566(node.id)
6851
6964
  );
6852
6965
  const result = await this.transferService.refreshTimelockNodes(
6853
6966
  [node],
@@ -6899,7 +7012,7 @@ var SparkWallet = class _SparkWallet extends EventEmitter {
6899
7012
  });
6900
7013
  }
6901
7014
  const signingPubKey = await this.config.signer.generatePublicKey(
6902
- sha2567(node.id)
7015
+ sha2566(node.id)
6903
7016
  );
6904
7017
  const result = await this.transferService.refreshTimelockRefundTx(
6905
7018
  node,