@buildonspark/spark-sdk 0.5.0 → 0.5.1

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 (81) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/bare/index.cjs +1608 -3635
  3. package/dist/bare/index.d.cts +27 -435
  4. package/dist/bare/index.d.ts +27 -435
  5. package/dist/bare/index.js +1608 -3634
  6. package/dist/{chunk-RU434ZAE.js → chunk-F3BFSHVR.js} +357 -391
  7. package/dist/{chunk-UYEB2VPG.js → chunk-IOIEBLMK.js} +7 -1
  8. package/dist/{chunk-EU3I7GFB.js → chunk-STB6WMU7.js} +1 -1
  9. package/dist/{chunk-JE3MXMPW.js → chunk-UTECVGQQ.js} +93 -202
  10. package/dist/{chunk-ZP6Z6DFX.js → chunk-YFVVYZCS.js} +37 -5
  11. package/dist/{client-D1dLzWu0.d.ts → client-C9kc4cog.d.cts} +9 -3
  12. package/dist/{client-CVn0R_eM.d.cts → client-eyjf4knu.d.ts} +9 -3
  13. package/dist/graphql/objects/index.cjs +7 -1
  14. package/dist/graphql/objects/index.d.cts +3 -3
  15. package/dist/graphql/objects/index.d.ts +3 -3
  16. package/dist/graphql/objects/index.js +1 -1
  17. package/dist/index.browser.d.ts +27 -435
  18. package/dist/index.browser.js +1613 -3639
  19. package/dist/index.node.cjs +1613 -3640
  20. package/dist/index.node.d.cts +7 -8
  21. package/dist/index.node.d.ts +7 -8
  22. package/dist/index.node.js +5 -7
  23. package/dist/native/index.react-native.cjs +1613 -3640
  24. package/dist/native/index.react-native.d.cts +27 -435
  25. package/dist/native/index.react-native.d.ts +27 -435
  26. package/dist/native/index.react-native.js +1613 -3639
  27. package/dist/proto/spark.cjs +93 -202
  28. package/dist/proto/spark.d.cts +1 -1
  29. package/dist/proto/spark.d.ts +1 -1
  30. package/dist/proto/spark.js +1 -1
  31. package/dist/proto/spark_token.cjs +36 -4
  32. package/dist/proto/spark_token.d.cts +4 -1
  33. package/dist/proto/spark_token.d.ts +4 -1
  34. package/dist/proto/spark_token.js +2 -2
  35. package/dist/{spark-2Fxnvl8K.d.cts → spark-d6w3BLGZ.d.cts} +10 -328
  36. package/dist/{spark-2Fxnvl8K.d.ts → spark-d6w3BLGZ.d.ts} +10 -328
  37. package/dist/{spark-wallet.node-DlhZiDgY.d.ts → spark-wallet.node-MReThHBY.d.ts} +6 -7
  38. package/dist/{spark-wallet.node-xKJXzAEd.d.cts → spark-wallet.node-eR0svGws.d.cts} +6 -7
  39. package/dist/tests/test-utils.cjs +409 -2429
  40. package/dist/tests/test-utils.d.cts +3 -3
  41. package/dist/tests/test-utils.d.ts +3 -3
  42. package/dist/tests/test-utils.js +5 -5
  43. package/dist/types/index.cjs +100 -203
  44. package/dist/types/index.d.cts +2 -2
  45. package/dist/types/index.d.ts +2 -2
  46. package/dist/types/index.js +3 -3
  47. package/package.json +3 -3
  48. package/src/graphql/client.ts +36 -1
  49. package/src/graphql/objects/LightningSendRequestStatus.ts +25 -13
  50. package/src/proto/common.ts +1 -1
  51. package/src/proto/google/protobuf/descriptor.ts +1 -1
  52. package/src/proto/google/protobuf/duration.ts +1 -1
  53. package/src/proto/google/protobuf/empty.ts +1 -1
  54. package/src/proto/google/protobuf/timestamp.ts +1 -1
  55. package/src/proto/mock.ts +1 -1
  56. package/src/proto/spark.ts +113 -446
  57. package/src/proto/spark_authn.ts +1 -1
  58. package/src/proto/spark_token.ts +41 -2
  59. package/src/proto/validate/validate.ts +1 -1
  60. package/src/services/connection/connection.ts +23 -60
  61. package/src/services/coop-exit.ts +3 -5
  62. package/src/services/deposit.ts +1 -1
  63. package/src/services/lightning.ts +1 -1
  64. package/src/services/signing.ts +5 -6
  65. package/src/services/transfer.ts +250 -240
  66. package/src/services/wallet-config.ts +22 -5
  67. package/src/spark-wallet/proto-descriptors.ts +1 -1
  68. package/src/spark-wallet/proto-reflection.ts +0 -2
  69. package/src/spark-wallet/spark-wallet.ts +2 -2
  70. package/src/spark_descriptors.pb +0 -0
  71. package/src/tests/bufbuild-reflection.test.ts +2 -3
  72. package/src/tests/integration/coop-exit.test.ts +6 -1
  73. package/src/tests/integration/htlc.test.ts +5 -0
  74. package/src/tests/integration/lightning.test.ts +24 -4
  75. package/src/tests/integration/time-sync.test.ts +18 -0
  76. package/src/tests/integration/transfer.test.ts +42 -7
  77. package/src/tests/ssp-client-retry.test.ts +161 -0
  78. package/src/tests/token-hashing.test.ts +92 -0
  79. package/src/utils/token-hashing.ts +4 -51
  80. package/src/utils/transaction.ts +1 -2
  81. package/src/utils/unilateral-exit.ts +139 -142
@@ -16,7 +16,6 @@ import {
16
16
  QueryTransfersResponse,
17
17
  RenewNodeZeroTimelockSigningJob,
18
18
  RenewRefundTimelockSigningJob,
19
- SecretProof,
20
19
  SendLeafKeyTweak,
21
20
  SendLeafKeyTweaks,
22
21
  SigningJob,
@@ -45,6 +44,7 @@ import {
45
44
  createInitialTimelockNodeTx,
46
45
  createInitialTimelockRefundTxs,
47
46
  createZeroTimelockNodeTx,
47
+ getCurrentTimelock,
48
48
  } from "../utils/transaction.js";
49
49
  import { getTransferPackageSigningPayload } from "../utils/transfer_package.js";
50
50
  import { WalletConfigService } from "./config.js";
@@ -297,27 +297,29 @@ export class BaseTransferService {
297
297
  );
298
298
 
299
299
  const sparkFrost = getSparkFrost();
300
- const encryptedKeyTweaks: { [key: string]: Uint8Array } = {};
301
- for (const [key, value] of keyTweakInputMap) {
302
- const protoToEncrypt: SendLeafKeyTweaks = {
303
- leavesToSend: value,
304
- };
300
+ const encryptedKeyTweaksEntries = await Promise.all(
301
+ Array.from(keyTweakInputMap.entries()).map(async ([key, value]) => {
302
+ const protoToEncrypt: SendLeafKeyTweaks = {
303
+ leavesToSend: value,
304
+ };
305
305
 
306
- const protoToEncryptBinary =
307
- SendLeafKeyTweaks.encode(protoToEncrypt).finish();
306
+ const protoToEncryptBinary =
307
+ SendLeafKeyTweaks.encode(protoToEncrypt).finish();
308
308
 
309
- const operator = this.config.getSigningOperators()[key];
310
- if (!operator) {
311
- throw new SparkValidationError("Operator not found");
312
- }
309
+ const operator = this.config.getSigningOperators()[key];
310
+ if (!operator) {
311
+ throw new SparkValidationError("Operator not found");
312
+ }
313
313
 
314
- const encryptedProto = await sparkFrost.encryptEcies(
315
- protoToEncryptBinary,
316
- hexToBytes(operator.identityPublicKey),
317
- );
318
- encryptedKeyTweaks[key] = Uint8Array.from(encryptedProto);
319
- }
314
+ const encryptedProto = await sparkFrost.encryptEcies(
315
+ protoToEncryptBinary,
316
+ hexToBytes(operator.identityPublicKey),
317
+ );
320
318
 
319
+ return [key, Uint8Array.from(encryptedProto)] as const;
320
+ }),
321
+ );
322
+ const encryptedKeyTweaks = Object.fromEntries(encryptedKeyTweaksEntries);
321
323
  const transferPackage: TransferPackage = {
322
324
  leavesToSend: cpfpLeafSigningJobs,
323
325
  keyTweakPackage: encryptedKeyTweaks,
@@ -376,26 +378,29 @@ export class BaseTransferService {
376
378
  );
377
379
 
378
380
  const sparkFrost = getSparkFrost();
379
- const encryptedKeyTweaks: { [key: string]: Uint8Array } = {};
380
- for (const [key, value] of keyTweakInputMap) {
381
- const protoToEncrypt: SendLeafKeyTweaks = {
382
- leavesToSend: value,
383
- };
381
+ const encryptedKeyTweaksEntries = await Promise.all(
382
+ Array.from(keyTweakInputMap.entries()).map(async ([key, value]) => {
383
+ const protoToEncrypt: SendLeafKeyTweaks = {
384
+ leavesToSend: value,
385
+ };
384
386
 
385
- const protoToEncryptBinary =
386
- SendLeafKeyTweaks.encode(protoToEncrypt).finish();
387
+ const protoToEncryptBinary =
388
+ SendLeafKeyTweaks.encode(protoToEncrypt).finish();
387
389
 
388
- const operator = this.config.getSigningOperators()[key];
389
- if (!operator) {
390
- throw new SparkValidationError("Operator not found");
391
- }
390
+ const operator = this.config.getSigningOperators()[key];
391
+ if (!operator) {
392
+ throw new SparkValidationError("Operator not found");
393
+ }
392
394
 
393
- const encryptedProto = await sparkFrost.encryptEcies(
394
- protoToEncryptBinary,
395
- hexToBytes(operator.identityPublicKey),
396
- );
397
- encryptedKeyTweaks[key] = Uint8Array.from(encryptedProto);
398
- }
395
+ const encryptedProto = await sparkFrost.encryptEcies(
396
+ protoToEncryptBinary,
397
+ hexToBytes(operator.identityPublicKey),
398
+ );
399
+
400
+ return [key, Uint8Array.from(encryptedProto)] as const;
401
+ }),
402
+ );
403
+ const encryptedKeyTweaks = Object.fromEntries(encryptedKeyTweaksEntries);
399
404
 
400
405
  const transferPackage: TransferPackage = {
401
406
  leavesToSend: cpfpLeafSigningJobs,
@@ -581,21 +586,27 @@ export class BaseTransferService {
581
586
  ): Promise<Map<string, SendLeafKeyTweak[]>> {
582
587
  const leavesTweaksMap = new Map<string, SendLeafKeyTweak[]>();
583
588
 
584
- for (const leaf of leaves) {
585
- const cpfpRefundSignature = cpfpRefundSignatureMap.get(leaf.leaf.id);
586
- const directRefundSignature = directRefundSignatureMap.get(leaf.leaf.id);
587
- const directFromCpfpRefundSignature =
588
- directFromCpfpRefundSignatureMap.get(leaf.leaf.id);
589
-
590
- const leafTweaksMap = await this.prepareSingleSendTransferKeyTweak(
591
- transferID,
592
- leaf,
593
- receiverIdentityPubkey,
594
- cpfpRefundSignature,
595
- directRefundSignature,
596
- directFromCpfpRefundSignature,
597
- );
598
- for (const [identifier, leafTweak] of leafTweaksMap) {
589
+ const results = await Promise.all(
590
+ leaves.map(async (leaf) => {
591
+ const cpfpRefundSignature = cpfpRefundSignatureMap.get(leaf.leaf.id);
592
+ const directRefundSignature = directRefundSignatureMap.get(
593
+ leaf.leaf.id,
594
+ );
595
+ const directFromCpfpRefundSignature =
596
+ directFromCpfpRefundSignatureMap.get(leaf.leaf.id);
597
+
598
+ return await this.prepareSingleSendTransferKeyTweak(
599
+ transferID,
600
+ leaf,
601
+ receiverIdentityPubkey,
602
+ cpfpRefundSignature,
603
+ directRefundSignature,
604
+ directFromCpfpRefundSignature,
605
+ );
606
+ }),
607
+ );
608
+ for (const result of results) {
609
+ for (const [identifier, leafTweak] of result) {
599
610
  leavesTweaksMap.set(identifier, [
600
611
  ...(leavesTweaksMap.get(identifier) || []),
601
612
  leafTweak,
@@ -714,15 +725,10 @@ export class TransferService extends BaseTransferService {
714
725
  }
715
726
 
716
727
  async claimTransfer(transfer: Transfer, leaves: LeafKeyTweak[]) {
717
- let proofMap: Map<string, Uint8Array[]> | undefined;
718
728
  if (transfer.status === TransferStatus.TRANSFER_STATUS_SENDER_KEY_TWEAKED) {
719
- proofMap = await this.claimTransferTweakKeys(transfer, leaves);
729
+ await this.claimTransferTweakKeys(transfer, leaves);
720
730
  }
721
- const signatures = await this.claimTransferSignRefunds(
722
- transfer,
723
- leaves,
724
- proofMap,
725
- );
731
+ const signatures = await this.claimTransferSignRefunds(transfer, leaves);
726
732
  return await this.finalizeNodeSignatures(signatures);
727
733
  }
728
734
 
@@ -786,39 +792,41 @@ export class TransferService extends BaseTransferService {
786
792
  transfer: Transfer,
787
793
  ): Promise<Map<string, Uint8Array>> {
788
794
  const leafPubKeyMap = new Map<string, Uint8Array>();
789
- for (const leaf of transfer.leaves) {
790
- if (!leaf.leaf) {
791
- throw new Error("Leaf is undefined");
792
- }
795
+ await Promise.all(
796
+ transfer.leaves.map(async (leaf) => {
797
+ if (!leaf.leaf) {
798
+ throw new Error("Leaf is undefined");
799
+ }
793
800
 
794
- const encoder = new TextEncoder();
795
- const leafIdBytes = encoder.encode(leaf.leaf.id);
796
- const transferIdBytes = encoder.encode(transfer.id);
801
+ const encoder = new TextEncoder();
802
+ const leafIdBytes = encoder.encode(leaf.leaf.id);
803
+ const transferIdBytes = encoder.encode(transfer.id);
797
804
 
798
- const payload = new Uint8Array([
799
- ...leafIdBytes,
800
- ...transferIdBytes,
801
- ...leaf.secretCipher,
802
- ]);
805
+ const payload = new Uint8Array([
806
+ ...leafIdBytes,
807
+ ...transferIdBytes,
808
+ ...leaf.secretCipher,
809
+ ]);
803
810
 
804
- const payloadHash = sha256(payload);
811
+ const payloadHash = sha256(payload);
805
812
 
806
- if (
807
- !secp256k1.verify(
808
- leaf.signature,
809
- payloadHash,
810
- transfer.senderIdentityPublicKey,
811
- )
812
- ) {
813
- throw new Error("Signature verification failed");
814
- }
813
+ if (
814
+ !secp256k1.verify(
815
+ leaf.signature,
816
+ payloadHash,
817
+ transfer.senderIdentityPublicKey,
818
+ )
819
+ ) {
820
+ throw new Error("Signature verification failed");
821
+ }
815
822
 
816
- const leafSecret = await this.config.signer.decryptEcies(
817
- leaf.secretCipher,
818
- );
823
+ const leafSecret = await this.config.signer.decryptEcies(
824
+ leaf.secretCipher,
825
+ );
819
826
 
820
- leafPubKeyMap.set(leaf.leaf.id, leafSecret);
821
- }
827
+ leafPubKeyMap.set(leaf.leaf.id, leafSecret);
828
+ }),
829
+ );
822
830
  return leafPubKeyMap;
823
831
  }
824
832
 
@@ -919,45 +927,47 @@ export class TransferService extends BaseTransferService {
919
927
  }> {
920
928
  const transferId = uuidv7();
921
929
  const leafDataMap = new Map<string, LeafRefundSigningData>();
922
- for (const leaf of leaves) {
923
- const signingNonceCommitment =
924
- await this.config.signer.getRandomSigningCommitment();
925
- const directSigningNonceCommitment =
926
- await this.config.signer.getRandomSigningCommitment();
927
- const directFromCpfpRefundSigningNonceCommitment =
928
- await this.config.signer.getRandomSigningCommitment();
929
-
930
- const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
931
- const refundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
932
-
933
- const directTx =
934
- leaf.leaf.directTx.length > 0
935
- ? getTxFromRawTxBytes(leaf.leaf.directTx)
936
- : undefined;
937
-
938
- const directRefundTx =
939
- leaf.leaf.directRefundTx.length > 0
940
- ? getTxFromRawTxBytes(leaf.leaf.directRefundTx)
941
- : undefined;
942
- const directFromCpfpRefundTx =
943
- leaf.leaf.directFromCpfpRefundTx.length > 0
944
- ? getTxFromRawTxBytes(leaf.leaf.directFromCpfpRefundTx)
945
- : undefined;
946
-
947
- leafDataMap.set(leaf.leaf.id, {
948
- keyDerivation: leaf.keyDerivation,
949
- receivingPubkey: receiverIdentityPubkey,
950
- signingNonceCommitment,
951
- directSigningNonceCommitment,
952
- tx,
953
- directTx,
954
- refundTx,
955
- directRefundTx,
956
- directFromCpfpRefundTx,
957
- directFromCpfpRefundSigningNonceCommitment,
958
- vout: leaf.leaf.vout,
959
- });
960
- }
930
+ await Promise.all(
931
+ leaves.map(async (leaf) => {
932
+ const signingNonceCommitment =
933
+ await this.config.signer.getRandomSigningCommitment();
934
+ const directSigningNonceCommitment =
935
+ await this.config.signer.getRandomSigningCommitment();
936
+ const directFromCpfpRefundSigningNonceCommitment =
937
+ await this.config.signer.getRandomSigningCommitment();
938
+
939
+ const tx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
940
+ const refundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
941
+
942
+ const directTx =
943
+ leaf.leaf.directTx.length > 0
944
+ ? getTxFromRawTxBytes(leaf.leaf.directTx)
945
+ : undefined;
946
+
947
+ const directRefundTx =
948
+ leaf.leaf.directRefundTx.length > 0
949
+ ? getTxFromRawTxBytes(leaf.leaf.directRefundTx)
950
+ : undefined;
951
+ const directFromCpfpRefundTx =
952
+ leaf.leaf.directFromCpfpRefundTx.length > 0
953
+ ? getTxFromRawTxBytes(leaf.leaf.directFromCpfpRefundTx)
954
+ : undefined;
955
+
956
+ leafDataMap.set(leaf.leaf.id, {
957
+ keyDerivation: leaf.keyDerivation,
958
+ receivingPubkey: receiverIdentityPubkey,
959
+ signingNonceCommitment,
960
+ directSigningNonceCommitment,
961
+ tx,
962
+ directTx,
963
+ refundTx,
964
+ directRefundTx,
965
+ directFromCpfpRefundTx,
966
+ directFromCpfpRefundSigningNonceCommitment,
967
+ vout: leaf.leaf.vout,
968
+ });
969
+ }),
970
+ );
961
971
 
962
972
  const signingJobs = await this.prepareRefundSoSigningJobs(
963
973
  leaves,
@@ -1033,82 +1043,92 @@ export class TransferService extends BaseTransferService {
1033
1043
  isForClaim?: boolean,
1034
1044
  ): Promise<LeafRefundTxSigningJob[]> {
1035
1045
  const signingJobs: LeafRefundTxSigningJob[] = [];
1036
- for (const leaf of leaves) {
1037
- const refundSigningData = leafDataMap.get(leaf.leaf.id);
1038
- if (!refundSigningData) {
1039
- throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
1040
- }
1046
+ const results = await Promise.all(
1047
+ leaves.map(async (leaf) => {
1048
+ const refundSigningData = leafDataMap.get(leaf.leaf.id);
1049
+ if (!refundSigningData) {
1050
+ throw new Error(`Leaf data not found for leaf ${leaf.leaf.id}`);
1051
+ }
1041
1052
 
1042
- const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
1053
+ const nodeTx = getTxFromRawTxBytes(leaf.leaf.nodeTx);
1043
1054
 
1044
- let directNodeTx: Transaction | undefined;
1045
- if (leaf.leaf.directTx.length > 0) {
1046
- directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
1047
- }
1055
+ let directNodeTx: Transaction | undefined;
1056
+ if (leaf.leaf.directTx.length > 0) {
1057
+ directNodeTx = getTxFromRawTxBytes(leaf.leaf.directTx);
1058
+ }
1048
1059
 
1049
- const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
1060
+ const currRefundTx = getTxFromRawTxBytes(leaf.leaf.refundTx);
1050
1061
 
1051
- const currentSequence = currRefundTx.getInput(0).sequence;
1052
- if (!currentSequence) {
1053
- throw new SparkValidationError("Invalid refund transaction", {
1054
- field: "sequence",
1055
- value: currRefundTx.getInput(0),
1056
- expected: "Non-null sequence",
1057
- });
1058
- }
1062
+ const currentSequence = currRefundTx.getInput(0).sequence;
1063
+ if (!currentSequence) {
1064
+ throw new SparkValidationError("Invalid refund transaction", {
1065
+ field: "sequence",
1066
+ value: currRefundTx.getInput(0),
1067
+ expected: "Non-null sequence",
1068
+ });
1069
+ }
1059
1070
 
1060
- const refundTxsParams = {
1061
- nodeTx: nodeTx,
1062
- directNodeTx: directNodeTx,
1063
- sequence: currentSequence,
1064
- receivingPubkey: refundSigningData.receivingPubkey,
1065
- network: this.config.getNetwork(),
1066
- };
1071
+ const refundTxsParams = {
1072
+ nodeTx: nodeTx,
1073
+ directNodeTx: directNodeTx,
1074
+ sequence: currentSequence,
1075
+ receivingPubkey: refundSigningData.receivingPubkey,
1076
+ network: this.config.getNetwork(),
1077
+ };
1067
1078
 
1068
- const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
1069
- isForClaim
1070
- ? createCurrentTimelockRefundTxs(refundTxsParams)
1071
- : createDecrementedTimelockRefundTxs(refundTxsParams);
1072
-
1073
- refundSigningData.refundTx = cpfpRefundTx;
1074
- refundSigningData.directRefundTx = directRefundTx;
1075
- refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
1076
-
1077
- const cpfpRefundNonceCommitmentProto =
1078
- refundSigningData.signingNonceCommitment;
1079
- const directRefundNonceCommitmentProto =
1080
- refundSigningData.directSigningNonceCommitment;
1081
- const directFromCpfpRefundNonceCommitmentProto =
1082
- refundSigningData.directFromCpfpRefundSigningNonceCommitment;
1083
-
1084
- const signingPublicKey =
1085
- await this.config.signer.getPublicKeyFromDerivation(
1086
- refundSigningData.keyDerivation,
1087
- );
1088
- signingJobs.push({
1089
- leafId: leaf.leaf.id,
1090
- refundTxSigningJob: {
1091
- signingPublicKey,
1092
- rawTx: cpfpRefundTx.toBytes(),
1093
- signingNonceCommitment: cpfpRefundNonceCommitmentProto.commitment,
1094
- },
1095
- directRefundTxSigningJob: directRefundTx
1096
- ? {
1097
- signingPublicKey,
1098
- rawTx: directRefundTx.toBytes(),
1099
- signingNonceCommitment:
1100
- directRefundNonceCommitmentProto.commitment,
1101
- }
1102
- : undefined,
1103
- directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx
1104
- ? {
1105
- signingPublicKey,
1106
- rawTx: directFromCpfpRefundTx.toBytes(),
1107
- signingNonceCommitment:
1108
- directFromCpfpRefundNonceCommitmentProto.commitment,
1109
- }
1110
- : undefined,
1111
- });
1079
+ const { cpfpRefundTx, directRefundTx, directFromCpfpRefundTx } =
1080
+ isForClaim
1081
+ ? createCurrentTimelockRefundTxs(refundTxsParams)
1082
+ : createDecrementedTimelockRefundTxs(refundTxsParams);
1083
+
1084
+ const isZeroNode = !getCurrentTimelock(nodeTx.getInput(0).sequence);
1085
+
1086
+ refundSigningData.refundTx = cpfpRefundTx;
1087
+ refundSigningData.directRefundTx =
1088
+ directRefundTx && !isZeroNode ? directRefundTx : undefined;
1089
+ refundSigningData.directFromCpfpRefundTx = directFromCpfpRefundTx;
1090
+
1091
+ const cpfpRefundNonceCommitmentProto =
1092
+ refundSigningData.signingNonceCommitment;
1093
+ const directRefundNonceCommitmentProto =
1094
+ refundSigningData.directSigningNonceCommitment;
1095
+ const directFromCpfpRefundNonceCommitmentProto =
1096
+ refundSigningData.directFromCpfpRefundSigningNonceCommitment;
1097
+
1098
+ const signingPublicKey =
1099
+ await this.config.signer.getPublicKeyFromDerivation(
1100
+ refundSigningData.keyDerivation,
1101
+ );
1102
+ return {
1103
+ leafId: leaf.leaf.id,
1104
+ refundTxSigningJob: {
1105
+ signingPublicKey,
1106
+ rawTx: cpfpRefundTx.toBytes(),
1107
+ signingNonceCommitment: cpfpRefundNonceCommitmentProto.commitment,
1108
+ },
1109
+ directRefundTxSigningJob:
1110
+ directRefundTx && !isZeroNode
1111
+ ? {
1112
+ signingPublicKey,
1113
+ rawTx: directRefundTx.toBytes(),
1114
+ signingNonceCommitment:
1115
+ directRefundNonceCommitmentProto.commitment,
1116
+ }
1117
+ : undefined,
1118
+ directFromCpfpRefundTxSigningJob: directFromCpfpRefundTx
1119
+ ? {
1120
+ signingPublicKey,
1121
+ rawTx: directFromCpfpRefundTx.toBytes(),
1122
+ signingNonceCommitment:
1123
+ directFromCpfpRefundNonceCommitmentProto.commitment,
1124
+ }
1125
+ : undefined,
1126
+ };
1127
+ }),
1128
+ );
1129
+
1130
+ for (const result of results) {
1131
+ signingJobs.push(result);
1112
1132
  }
1113
1133
 
1114
1134
  return signingJobs;
@@ -1117,9 +1137,8 @@ export class TransferService extends BaseTransferService {
1117
1137
  async claimTransferTweakKeys(
1118
1138
  transfer: Transfer,
1119
1139
  leaves: LeafKeyTweak[],
1120
- ): Promise<Map<string, Uint8Array[]>> {
1121
- const { leafDataMap: leavesTweaksMap, proofMap } =
1122
- await this.prepareClaimLeavesKeyTweaks(leaves);
1140
+ ): Promise<void> {
1141
+ const leavesTweaksMap = await this.prepareClaimLeavesKeyTweaks(leaves);
1123
1142
 
1124
1143
  const errors: Error[] = [];
1125
1144
 
@@ -1164,21 +1183,18 @@ export class TransferService extends BaseTransferService {
1164
1183
  if (errors.length > 0) {
1165
1184
  throw errors[0];
1166
1185
  }
1167
-
1168
- return proofMap;
1169
1186
  }
1170
1187
 
1171
- private async prepareClaimLeavesKeyTweaks(leaves: LeafKeyTweak[]): Promise<{
1172
- leafDataMap: Map<string, ClaimLeafKeyTweak[]>;
1173
- proofMap: Map<string, Uint8Array[]>;
1174
- }> {
1188
+ private async prepareClaimLeavesKeyTweaks(
1189
+ leaves: LeafKeyTweak[],
1190
+ ): Promise<Map<string, ClaimLeafKeyTweak[]>> {
1175
1191
  const leafDataMap = new Map<string, ClaimLeafKeyTweak[]>();
1176
- const proofMap = new Map<string, Uint8Array[]>();
1177
- for (const leaf of leaves) {
1178
- const { leafKeyTweaks: leafData, proofs } =
1179
- await this.prepareClaimLeafKeyTweaks(leaf);
1180
- proofMap.set(leaf.leaf.id, proofs);
1181
1192
 
1193
+ const results = await Promise.all(
1194
+ leaves.map((leaf) => this.prepareClaimLeafKeyTweaks(leaf)),
1195
+ );
1196
+
1197
+ for (const { leafKeyTweaks: leafData } of results) {
1182
1198
  for (const [identifier, leafTweak] of leafData) {
1183
1199
  leafDataMap.set(identifier, [
1184
1200
  ...(leafDataMap.get(identifier) || []),
@@ -1186,7 +1202,8 @@ export class TransferService extends BaseTransferService {
1186
1202
  ]);
1187
1203
  }
1188
1204
  }
1189
- return { leafDataMap, proofMap };
1205
+
1206
+ return leafDataMap;
1190
1207
  }
1191
1208
 
1192
1209
  private async prepareClaimLeafKeyTweaks(leaf: LeafKeyTweak): Promise<{
@@ -1249,32 +1266,33 @@ export class TransferService extends BaseTransferService {
1249
1266
  async claimTransferSignRefunds(
1250
1267
  transfer: Transfer,
1251
1268
  leafKeys: LeafKeyTweak[],
1252
- proofMap?: Map<string, Uint8Array[]>,
1253
1269
  ): Promise<NodeSignatures[]> {
1254
1270
  const leafDataMap: Map<string, LeafRefundSigningData> = new Map();
1255
- for (const leafKey of leafKeys) {
1256
- const tx = getTxFromRawTxBytes(leafKey.leaf.nodeTx);
1257
- const directTx =
1258
- leafKey.leaf.directTx.length > 0
1259
- ? getTxFromRawTxBytes(leafKey.leaf.directTx)
1260
- : undefined;
1261
-
1262
- leafDataMap.set(leafKey.leaf.id, {
1263
- keyDerivation: leafKey.newKeyDerivation,
1264
- receivingPubkey: await this.config.signer.getPublicKeyFromDerivation(
1265
- leafKey.newKeyDerivation,
1266
- ),
1267
- signingNonceCommitment:
1268
- await this.config.signer.getRandomSigningCommitment(),
1269
- directSigningNonceCommitment:
1270
- await this.config.signer.getRandomSigningCommitment(),
1271
- directFromCpfpRefundSigningNonceCommitment:
1272
- await this.config.signer.getRandomSigningCommitment(),
1273
- tx,
1274
- directTx,
1275
- vout: leafKey.leaf.vout,
1276
- });
1277
- }
1271
+ await Promise.all(
1272
+ leafKeys.map(async (leafKey) => {
1273
+ const tx = getTxFromRawTxBytes(leafKey.leaf.nodeTx);
1274
+ const directTx =
1275
+ leafKey.leaf.directTx.length > 0
1276
+ ? getTxFromRawTxBytes(leafKey.leaf.directTx)
1277
+ : undefined;
1278
+
1279
+ leafDataMap.set(leafKey.leaf.id, {
1280
+ keyDerivation: leafKey.newKeyDerivation,
1281
+ receivingPubkey: await this.config.signer.getPublicKeyFromDerivation(
1282
+ leafKey.newKeyDerivation,
1283
+ ),
1284
+ signingNonceCommitment:
1285
+ await this.config.signer.getRandomSigningCommitment(),
1286
+ directSigningNonceCommitment:
1287
+ await this.config.signer.getRandomSigningCommitment(),
1288
+ directFromCpfpRefundSigningNonceCommitment:
1289
+ await this.config.signer.getRandomSigningCommitment(),
1290
+ tx,
1291
+ directTx,
1292
+ vout: leafKey.leaf.vout,
1293
+ });
1294
+ }),
1295
+ );
1278
1296
 
1279
1297
  const signingJobs = await this.prepareRefundSoSigningJobs(
1280
1298
  leafKeys,
@@ -1287,14 +1305,6 @@ export class TransferService extends BaseTransferService {
1287
1305
  );
1288
1306
  let resp: ClaimTransferSignRefundsResponse;
1289
1307
 
1290
- const secretProofMap: { [key: string]: SecretProof } = {};
1291
- if (proofMap) {
1292
- for (const [leafId, proof] of proofMap.entries()) {
1293
- secretProofMap[leafId] = {
1294
- proofs: proof,
1295
- };
1296
- }
1297
- }
1298
1308
  try {
1299
1309
  resp = await sparkClient.claim_transfer_sign_refunds_v2({
1300
1310
  transferId: transfer.id,