@atomiqlabs/sdk 8.8.3 → 8.9.0

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 (130) hide show
  1. package/api/index.d.ts +1 -0
  2. package/api/index.js +3 -0
  3. package/dist/ApiList.d.ts +37 -0
  4. package/dist/ApiList.js +30 -0
  5. package/dist/api/ApiEndpoints.d.ts +393 -0
  6. package/dist/api/ApiEndpoints.js +2 -0
  7. package/dist/api/ApiParser.d.ts +10 -0
  8. package/dist/api/ApiParser.js +134 -0
  9. package/dist/api/ApiTypes.d.ts +157 -0
  10. package/dist/api/ApiTypes.js +75 -0
  11. package/dist/api/SerializedAction.d.ts +40 -0
  12. package/dist/api/SerializedAction.js +59 -0
  13. package/dist/api/SwapperApi.d.ts +50 -0
  14. package/dist/api/SwapperApi.js +431 -0
  15. package/dist/api/index.d.ts +5 -0
  16. package/dist/api/index.js +24 -0
  17. package/dist/events/UnifiedSwapEventListener.d.ts +4 -3
  18. package/dist/events/UnifiedSwapEventListener.js +8 -2
  19. package/dist/http/HttpUtils.d.ts +4 -2
  20. package/dist/http/HttpUtils.js +10 -4
  21. package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +2 -1
  22. package/dist/http/paramcoders/client/StreamingFetchPromise.js +3 -2
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +1 -0
  25. package/dist/intermediaries/IntermediaryDiscovery.d.ts +7 -2
  26. package/dist/intermediaries/IntermediaryDiscovery.js +4 -4
  27. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +171 -14
  28. package/dist/intermediaries/apis/IntermediaryAPI.js +174 -28
  29. package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -0
  30. package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -0
  31. package/dist/storage/IUnifiedStorage.d.ts +45 -3
  32. package/dist/storage/UnifiedSwapStorage.d.ts +8 -2
  33. package/dist/storage/UnifiedSwapStorage.js +46 -8
  34. package/dist/swapper/Swapper.d.ts +36 -3
  35. package/dist/swapper/Swapper.js +54 -18
  36. package/dist/swapper/SwapperUtils.d.ts +18 -2
  37. package/dist/swapper/SwapperUtils.js +39 -1
  38. package/dist/swaps/ISwap.d.ts +70 -9
  39. package/dist/swaps/ISwap.js +28 -6
  40. package/dist/swaps/ISwapWrapper.d.ts +11 -1
  41. package/dist/swaps/ISwapWrapper.js +23 -3
  42. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +1 -1
  43. package/dist/swaps/escrow_swaps/IEscrowSwap.js +4 -2
  44. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +2 -1
  45. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +2 -2
  46. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +3 -1
  47. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +3 -2
  48. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +47 -31
  49. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +201 -67
  50. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +3 -1
  51. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +6 -6
  52. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +82 -15
  53. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +304 -98
  54. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +3 -1
  55. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +6 -6
  56. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +75 -42
  57. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +424 -87
  58. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +3 -1
  59. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +7 -7
  60. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +54 -11
  61. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +214 -41
  62. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +2 -1
  63. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +7 -8
  64. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +3 -1
  65. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +5 -5
  66. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +76 -19
  67. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +290 -51
  68. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +3 -1
  69. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +5 -5
  70. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +53 -12
  71. package/dist/swaps/trusted/ln/LnForGasSwap.js +163 -49
  72. package/dist/swaps/trusted/ln/LnForGasWrapper.js +1 -2
  73. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +14 -13
  74. package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +30 -47
  75. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +3 -1
  76. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +4 -4
  77. package/dist/types/SwapExecutionAction.d.ts +141 -34
  78. package/dist/types/SwapExecutionAction.js +104 -0
  79. package/dist/types/SwapExecutionStep.d.ts +144 -0
  80. package/dist/types/SwapExecutionStep.js +87 -0
  81. package/dist/types/TokenAmount.d.ts +6 -0
  82. package/dist/types/TokenAmount.js +26 -1
  83. package/dist/utils/BitcoinUtils.d.ts +2 -0
  84. package/dist/utils/BitcoinUtils.js +34 -1
  85. package/dist/utils/Utils.d.ts +3 -1
  86. package/dist/utils/Utils.js +7 -1
  87. package/package.json +7 -4
  88. package/src/api/ApiEndpoints.ts +427 -0
  89. package/src/api/ApiParser.ts +138 -0
  90. package/src/api/ApiTypes.ts +229 -0
  91. package/src/api/SerializedAction.ts +97 -0
  92. package/src/api/SwapperApi.ts +545 -0
  93. package/src/api/index.ts +5 -0
  94. package/src/events/UnifiedSwapEventListener.ts +11 -3
  95. package/src/http/HttpUtils.ts +10 -4
  96. package/src/http/paramcoders/client/StreamingFetchPromise.ts +4 -2
  97. package/src/index.ts +1 -0
  98. package/src/intermediaries/IntermediaryDiscovery.ts +9 -2
  99. package/src/intermediaries/apis/IntermediaryAPI.ts +314 -30
  100. package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -0
  101. package/src/storage/IUnifiedStorage.ts +45 -4
  102. package/src/storage/UnifiedSwapStorage.ts +42 -8
  103. package/src/swapper/Swapper.ts +87 -18
  104. package/src/swapper/SwapperUtils.ts +42 -2
  105. package/src/swaps/ISwap.ts +88 -16
  106. package/src/swaps/ISwapWrapper.ts +28 -3
  107. package/src/swaps/escrow_swaps/IEscrowSwap.ts +5 -3
  108. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +3 -1
  109. package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +4 -1
  110. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +264 -67
  111. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +6 -4
  112. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +390 -89
  113. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +6 -4
  114. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +548 -94
  115. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +7 -5
  116. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +276 -45
  117. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +7 -6
  118. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +5 -3
  119. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +393 -57
  120. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +5 -3
  121. package/src/swaps/trusted/ln/LnForGasSwap.ts +211 -47
  122. package/src/swaps/trusted/ln/LnForGasWrapper.ts +1 -2
  123. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +32 -51
  124. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +5 -3
  125. package/src/types/SwapExecutionAction.ts +266 -43
  126. package/src/types/SwapExecutionStep.ts +224 -0
  127. package/src/types/TokenAmount.ts +36 -2
  128. package/src/utils/BitcoinUtils.ts +32 -0
  129. package/src/utils/Utils.ts +10 -1
  130. package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +0 -258
@@ -586,10 +586,11 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
586
586
  *
587
587
  * @throws {Error} If an invalid secret preimage is provided
588
588
  */
589
- setSecretPreimage(secret) {
589
+ async setSecretPreimage(secret) {
590
590
  if (!this.isValidSecretPreimage(secret))
591
591
  throw new Error("Invalid secret preimage provided, hash doesn't match!");
592
592
  this.secret = secret;
593
+ await this._broadcastSecret().catch(e => this.logger.error("setSecretPreimage(): Failed to broadcast swap secret: ", e));
593
594
  }
594
595
  /**
595
596
  * Returns whether the secret preimage for this swap is known
@@ -657,28 +658,188 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
657
658
  throw new Error("Invalid state reached!");
658
659
  }
659
660
  /**
660
- * @inheritDoc
661
+ * @internal
661
662
  */
662
- async txsExecute() {
663
- if (this._state === FromBTCLNAutoSwapState.PR_CREATED) {
664
- if (!await this._verifyQuoteValid())
665
- throw new Error("Quote already expired or close to expiry!");
666
- return [
663
+ async _getExecutionStatus(options) {
664
+ if (options?.secret != null)
665
+ await this.setSecretPreimage(options.secret);
666
+ const state = this._state;
667
+ const now = Date.now();
668
+ let lightningPaymentStatus = "inactive";
669
+ let destinationSettlementStatus = "inactive";
670
+ let buildCurrentAction = async () => undefined;
671
+ switch (state) {
672
+ case FromBTCLNAutoSwapState.PR_CREATED: {
673
+ const quoteValid = await this._verifyQuoteValid();
674
+ lightningPaymentStatus = quoteValid ? "awaiting" : "soft_expired";
675
+ if (quoteValid && this.pr != null && this.pr.toLowerCase().startsWith("ln")) {
676
+ buildCurrentAction = this._buildLightningPaymentAction.bind(this);
677
+ }
678
+ break;
679
+ }
680
+ case FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED:
681
+ lightningPaymentStatus = "soft_expired";
682
+ break;
683
+ case FromBTCLNAutoSwapState.QUOTE_EXPIRED:
684
+ lightningPaymentStatus = "expired";
685
+ break;
686
+ case FromBTCLNAutoSwapState.PR_PAID:
687
+ lightningPaymentStatus = "received";
688
+ destinationSettlementStatus = "waiting_lp";
689
+ buildCurrentAction = this._buildWaitLpAction.bind(this);
690
+ break;
691
+ case FromBTCLNAutoSwapState.CLAIM_COMMITED:
692
+ lightningPaymentStatus = "received";
693
+ if (this._commitedAt == null ||
694
+ options?.maxWaitTillAutomaticSettlementSeconds === 0 ||
695
+ (now - this._commitedAt) > (options?.maxWaitTillAutomaticSettlementSeconds ?? 60) * 1000) {
696
+ destinationSettlementStatus = "awaiting_manual";
697
+ if (this.hasSecretPreimage()) {
698
+ //TODO: Maybe add an action that would prompt the user to reveal the pre-image
699
+ buildCurrentAction = this._buildClaimSmartChainTxAction.bind(this);
700
+ }
701
+ }
702
+ else {
703
+ destinationSettlementStatus = "awaiting_automatic";
704
+ //TODO: Maybe add an action that would prompt the user to reveal the pre-image
705
+ buildCurrentAction = this._buildWaitSettlementAction.bind(this, options?.maxWaitTillAutomaticSettlementSeconds);
706
+ }
707
+ break;
708
+ case FromBTCLNAutoSwapState.CLAIM_CLAIMED:
709
+ lightningPaymentStatus = "confirmed";
710
+ destinationSettlementStatus = "settled";
711
+ break;
712
+ case FromBTCLNAutoSwapState.EXPIRED:
713
+ case FromBTCLNAutoSwapState.FAILED:
714
+ lightningPaymentStatus = "expired";
715
+ destinationSettlementStatus = "expired";
716
+ break;
717
+ }
718
+ return {
719
+ steps: [
667
720
  {
668
- name: "Payment",
669
- description: "Initiates the swap by paying up the lightning network invoice",
721
+ type: "Payment",
722
+ side: "source",
670
723
  chain: "LIGHTNING",
671
- txs: [
672
- {
673
- type: "BOLT11_PAYMENT_REQUEST",
674
- address: this.getAddress(),
675
- hyperlink: this.getHyperlink()
676
- }
677
- ]
724
+ title: "Lightning payment",
725
+ description: "Pay the Lightning network invoice to initiate the swap",
726
+ status: lightningPaymentStatus,
727
+ initTxId: this.getInputTxId(),
728
+ settleTxId: lightningPaymentStatus === "confirmed" ? this.getInputTxId() : undefined
729
+ },
730
+ {
731
+ type: "Settlement",
732
+ side: "destination",
733
+ chain: this.chainIdentifier,
734
+ title: "Destination settlement",
735
+ description: `Wait for the LP to initiate on the ${this.chainIdentifier} side, then wait for automatic settlement, or settle manually if it takes too long`,
736
+ status: destinationSettlementStatus,
737
+ initTxId: this._commitTxId,
738
+ settleTxId: this._claimTxId
678
739
  }
679
- ];
740
+ ],
741
+ buildCurrentAction,
742
+ state
743
+ };
744
+ }
745
+ /**
746
+ * @internal
747
+ */
748
+ async _buildLightningPaymentAction() {
749
+ return {
750
+ type: "SendToAddress",
751
+ name: "Deposit on Lightning",
752
+ description: "Pay the lightning network invoice to initiate the swap",
753
+ chain: "LIGHTNING",
754
+ txs: [{
755
+ type: "BOLT11_PAYMENT_REQUEST",
756
+ address: this.getAddress(),
757
+ hyperlink: this.getHyperlink(),
758
+ amount: this.getInput()
759
+ }],
760
+ waitForTransactions: async (maxWaitTimeSeconds, pollIntervalSeconds, abortSignal) => {
761
+ const abortController = (0, Utils_1.extendAbortController)(abortSignal, maxWaitTimeSeconds, "Timed out waiting for lightning payment");
762
+ const success = await this._waitForLpPaymentReceived(pollIntervalSeconds, abortController.signal);
763
+ if (!success)
764
+ throw new Error("Quote expired while waiting for Lightning payment");
765
+ return this.getInputTxId();
766
+ }
767
+ };
768
+ }
769
+ /**
770
+ * @internal
771
+ */
772
+ async _buildWaitLpAction() {
773
+ return {
774
+ type: "Wait",
775
+ name: "Awaiting LP payout",
776
+ description: "Wait for the LP to create the swap HTLC on the destination smart chain",
777
+ pollTimeSeconds: 5,
778
+ expectedTimeSeconds: 10,
779
+ wait: async (maxWaitTimeSeconds, pollIntervalSeconds, abortSignal) => {
780
+ const abortController = (0, Utils_1.extendAbortController)(abortSignal, maxWaitTimeSeconds, "Timed out waiting for LP payout");
781
+ await this.waitTillCommited(pollIntervalSeconds, abortController.signal);
782
+ }
783
+ };
784
+ }
785
+ /**
786
+ * @internal
787
+ */
788
+ async _buildWaitSettlementAction(maxWaitTillAutomaticSettlementSeconds) {
789
+ return {
790
+ type: "Wait",
791
+ name: "Automatic settlement",
792
+ description: "Wait for automatic settlement by the watchtower",
793
+ pollTimeSeconds: 5,
794
+ expectedTimeSeconds: 10,
795
+ wait: async (maxWaitTimeSeconds, pollIntervalSeconds, abortSignal) => {
796
+ await this.waitTillClaimed(maxWaitTimeSeconds ?? maxWaitTillAutomaticSettlementSeconds ?? 60, abortSignal, undefined, pollIntervalSeconds);
797
+ }
798
+ };
799
+ }
800
+ /**
801
+ * @inheritDoc
802
+ * @internal
803
+ */
804
+ async _submitExecutionTransactions(txs, abortSignal, requiredStates, idempotent) {
805
+ const parsedTxs = [];
806
+ for (let tx of txs) {
807
+ parsedTxs.push(typeof (tx) === "string" ? await this.wrapper._chain.deserializeSignedTx(tx) : tx);
808
+ }
809
+ if (idempotent) {
810
+ // Handle idempotent calls
811
+ if (this.wrapper._chain.getTxId != null) {
812
+ const txIds = await Promise.all(parsedTxs.map(tx => this.wrapper._chain.getTxId(tx)));
813
+ const foundTxId = txIds.find(txId => this._claimTxId === txId);
814
+ if (foundTxId != null)
815
+ return txIds;
816
+ }
817
+ }
818
+ if (requiredStates != null && !requiredStates.includes(this._state))
819
+ throw new Error("Swap state has changed before transactions were submitted!");
820
+ if (this._state === FromBTCLNAutoSwapState.CLAIM_COMMITED) {
821
+ const txIds = await this.wrapper._chain.sendSignedAndConfirm(parsedTxs, true, abortSignal, false);
822
+ await this.waitTillClaimed(undefined, abortSignal);
823
+ return txIds;
680
824
  }
681
- throw new Error("Invalid swap state to obtain execution txns, required PR_CREATED");
825
+ throw new Error("Invalid swap state for transaction submission!");
826
+ }
827
+ /**
828
+ * @internal
829
+ */
830
+ async _buildClaimSmartChainTxAction(actionOptions) {
831
+ const signerAddress = await this.wrapper._getSignerAddress(actionOptions?.manualSettlementSmartChainSigner);
832
+ return {
833
+ type: "SignSmartChainTransaction",
834
+ name: "Settle manually",
835
+ description: "Manually settle (claim) the swap on the destination smart chain",
836
+ chain: this.chainIdentifier,
837
+ txs: await this.prepareTransactions(this.txsClaim(actionOptions?.manualSettlementSmartChainSigner, actionOptions?.secret)),
838
+ submitTransactions: async (txs, abortSignal, idempotent) => {
839
+ return this._submitExecutionTransactions(txs, abortSignal, [FromBTCLNAutoSwapState.CLAIM_COMMITED], idempotent);
840
+ },
841
+ requiredSigner: signerAddress ?? this._getInitiator()
842
+ };
682
843
  }
683
844
  /**
684
845
  *
@@ -688,28 +849,27 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
688
849
  * @param options.secret A swap secret to broadcast to watchtowers, generally only needed if the swap
689
850
  * was recovered from on-chain data, or the pre-image was generated outside the SDK
690
851
  */
691
- async getCurrentActions(options) {
692
- if (options?.secret != null)
693
- this.setSecretPreimage(options.secret);
694
- if (this._state === FromBTCLNAutoSwapState.PR_CREATED) {
695
- try {
696
- return await this.txsExecute();
697
- }
698
- catch (e) { }
699
- }
700
- if (this.isClaimable()) {
701
- if (this._commitedAt == null ||
702
- options?.maxWaitTillAutomaticSettlementSeconds === 0 ||
703
- (Date.now() - this._commitedAt) > (options?.maxWaitTillAutomaticSettlementSeconds ?? 60) * 1000) {
704
- return [{
705
- name: "Claim",
706
- description: "Manually settle (claim) the swap on the destination smart chain",
707
- chain: this.chainIdentifier,
708
- txs: await this.txsClaim(options?.manualSettlementSmartChainSigner)
709
- }];
710
- }
711
- }
712
- return [];
852
+ async getExecutionAction(options) {
853
+ const executionStatus = await this._getExecutionStatus(options);
854
+ return executionStatus.buildCurrentAction(options);
855
+ }
856
+ /**
857
+ * @inheritDoc
858
+ */
859
+ // TODO: Figure how we gonna trigger an LNURL-withdraw with the execution actions
860
+ async getExecutionStatus(options) {
861
+ const executionStatus = await this._getExecutionStatus(options);
862
+ return {
863
+ steps: executionStatus.steps,
864
+ currentAction: options?.skipBuildingAction ? undefined : await executionStatus.buildCurrentAction(options),
865
+ stateInfo: this._getStateInfo(executionStatus.state)
866
+ };
867
+ }
868
+ /**
869
+ * @inheritDoc
870
+ */
871
+ async getExecutionSteps(options) {
872
+ return (await this._getExecutionStatus(options)).steps;
713
873
  }
714
874
  //////////////////////////////
715
875
  //// Payment
@@ -734,7 +894,7 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
734
894
  const paymentHash = this.getPaymentHash();
735
895
  if (paymentHash == null)
736
896
  throw new Error("Failed to check LP payment received, payment hash not known (probably recovered swap?)");
737
- const resp = await IntermediaryAPI_1.IntermediaryAPI.getInvoiceStatus(this.url, paymentHash.toString("hex"));
897
+ const resp = await this.wrapper._lpApi.getInvoiceStatus(this.url, paymentHash.toString("hex"));
738
898
  switch (resp.code) {
739
899
  case IntermediaryAPI_1.InvoiceStatusResponseCodes.PAID:
740
900
  const data = new (this.wrapper._swapDataDeserializer(this._contractVersion))(resp.data.data);
@@ -776,44 +936,6 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
776
936
  }
777
937
  return false;
778
938
  }
779
- /**
780
- * Checks the data returned by the intermediary in the payment auth request
781
- *
782
- * @param data Parsed swap data as returned by the intermediary
783
- *
784
- * @throws {IntermediaryError} If the returned are not valid
785
- * @throws {Error} If the swap is already committed on-chain
786
- *
787
- * @private
788
- */
789
- async checkIntermediaryReturnedData(data) {
790
- if (!data.isPayOut())
791
- throw new IntermediaryError_1.IntermediaryError("Invalid not pay out");
792
- if (data.getType() !== base_1.ChainSwapType.HTLC)
793
- throw new IntermediaryError_1.IntermediaryError("Invalid swap type");
794
- if (!data.isOfferer(this.getSwapData().getOfferer()))
795
- throw new IntermediaryError_1.IntermediaryError("Invalid offerer used");
796
- if (!data.isClaimer(this._getInitiator()))
797
- throw new IntermediaryError_1.IntermediaryError("Invalid claimer used");
798
- if (!data.isToken(this.getSwapData().getToken()))
799
- throw new IntermediaryError_1.IntermediaryError("Invalid token used");
800
- if (data.getSecurityDeposit() !== this.getSwapData().getSecurityDeposit())
801
- throw new IntermediaryError_1.IntermediaryError("Invalid security deposit!");
802
- if (data.getClaimerBounty() !== this.getSwapData().getClaimerBounty())
803
- throw new IntermediaryError_1.IntermediaryError("Invalid security deposit!");
804
- if (data.getAmount() < this.getSwapData().getAmount())
805
- throw new IntermediaryError_1.IntermediaryError("Invalid amount received!");
806
- if (data.getClaimHash() !== this.getSwapData().getClaimHash())
807
- throw new IntermediaryError_1.IntermediaryError("Invalid payment hash used!");
808
- if (!data.isDepositToken(this.getSwapData().getDepositToken()))
809
- throw new IntermediaryError_1.IntermediaryError("Invalid deposit token used!");
810
- if (data.hasSuccessAction())
811
- throw new IntermediaryError_1.IntermediaryError("Invalid has success action");
812
- if (await this.wrapper._contract(this._contractVersion).isExpired(this._getInitiator(), data))
813
- throw new IntermediaryError_1.IntermediaryError("Not enough time to claim!");
814
- if (this.wrapper._getHtlcTimeout(data) <= (Date.now() / 1000))
815
- throw new IntermediaryError_1.IntermediaryError("HTLC expires too soon!");
816
- }
817
939
  /**
818
940
  * Waits till a lightning network payment is received by the intermediary, and the intermediary
819
941
  * initiates the swap HTLC on the smart chain side. After the HTLC is initiated you can wait
@@ -823,16 +945,17 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
823
945
  * If this swap is using an LNURL-withdraw link as input, it automatically posts the
824
946
  * generated invoice to the LNURL service to pay it.
825
947
  *
826
- * @param onPaymentReceived Callback as for when the LP reports having received the ln payment
948
+ * @remarks For internal use, rather use {@link waitForPayment} which properly waits till the LP also
949
+ * offers a swap HTLC.
950
+ *
827
951
  * @param abortSignal Abort signal to stop waiting for payment
828
952
  * @param checkIntervalSeconds How often to poll the intermediary for answer (default 5 seconds)
953
+ *
954
+ * @internal
829
955
  */
830
- async waitForPayment(onPaymentReceived, checkIntervalSeconds, abortSignal) {
956
+ async _waitForLpPaymentReceived(checkIntervalSeconds, abortSignal) {
831
957
  checkIntervalSeconds ??= 5;
832
- if (this._state === FromBTCLNAutoSwapState.PR_PAID) {
833
- await this.waitTillCommited(checkIntervalSeconds, abortSignal);
834
- }
835
- if (this._state >= FromBTCLNAutoSwapState.CLAIM_COMMITED)
958
+ if (this._state >= FromBTCLNAutoSwapState.PR_PAID)
836
959
  return true;
837
960
  if (this._state !== FromBTCLNAutoSwapState.PR_CREATED)
838
961
  throw new Error("Must be in PR_CREATED state!");
@@ -873,7 +996,7 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
873
996
  promises.push((async () => {
874
997
  let resp = { code: IntermediaryAPI_1.InvoiceStatusResponseCodes.PENDING, msg: "" };
875
998
  while (!abortController.signal.aborted && resp.code === IntermediaryAPI_1.InvoiceStatusResponseCodes.PENDING) {
876
- resp = await IntermediaryAPI_1.IntermediaryAPI.getInvoiceStatus(this.url, paymentHash.toString("hex"));
999
+ resp = await this.wrapper._lpApi.getInvoiceStatus(this.url, paymentHash.toString("hex"));
877
1000
  if (resp.code === IntermediaryAPI_1.InvoiceStatusResponseCodes.PENDING)
878
1001
  await (0, TimeoutUtils_1.timeoutPromise)(checkIntervalSeconds * 1000, abortController.signal);
879
1002
  }
@@ -894,9 +1017,72 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
894
1017
  abortController.abort();
895
1018
  if (!paymentResult)
896
1019
  return false;
897
- if (onPaymentReceived != null)
898
- onPaymentReceived(this.getInputTxId());
899
1020
  }
1021
+ return this._state >= FromBTCLNAutoSwapState.PR_PAID;
1022
+ }
1023
+ /**
1024
+ * Checks the data returned by the intermediary in the payment auth request
1025
+ *
1026
+ * @param data Parsed swap data as returned by the intermediary
1027
+ *
1028
+ * @throws {IntermediaryError} If the returned are not valid
1029
+ * @throws {Error} If the swap is already committed on-chain
1030
+ *
1031
+ * @private
1032
+ */
1033
+ async checkIntermediaryReturnedData(data) {
1034
+ if (!data.isPayOut())
1035
+ throw new IntermediaryError_1.IntermediaryError("Invalid not pay out");
1036
+ if (data.getType() !== base_1.ChainSwapType.HTLC)
1037
+ throw new IntermediaryError_1.IntermediaryError("Invalid swap type");
1038
+ if (!data.isOfferer(this.getSwapData().getOfferer()))
1039
+ throw new IntermediaryError_1.IntermediaryError("Invalid offerer used");
1040
+ if (!data.isClaimer(this._getInitiator()))
1041
+ throw new IntermediaryError_1.IntermediaryError("Invalid claimer used");
1042
+ if (!data.isToken(this.getSwapData().getToken()))
1043
+ throw new IntermediaryError_1.IntermediaryError("Invalid token used");
1044
+ if (data.getSecurityDeposit() !== this.getSwapData().getSecurityDeposit())
1045
+ throw new IntermediaryError_1.IntermediaryError("Invalid security deposit!");
1046
+ if (data.getClaimerBounty() !== this.getSwapData().getClaimerBounty())
1047
+ throw new IntermediaryError_1.IntermediaryError("Invalid security deposit!");
1048
+ if (data.getAmount() < this.getSwapData().getAmount())
1049
+ throw new IntermediaryError_1.IntermediaryError("Invalid amount received!");
1050
+ if (data.getClaimHash() !== this.getSwapData().getClaimHash())
1051
+ throw new IntermediaryError_1.IntermediaryError("Invalid payment hash used!");
1052
+ if (!data.isDepositToken(this.getSwapData().getDepositToken()))
1053
+ throw new IntermediaryError_1.IntermediaryError("Invalid deposit token used!");
1054
+ if (data.hasSuccessAction())
1055
+ throw new IntermediaryError_1.IntermediaryError("Invalid has success action");
1056
+ if (await this.wrapper._contract(this._contractVersion).isExpired(this._getInitiator(), data))
1057
+ throw new IntermediaryError_1.IntermediaryError("Not enough time to claim!");
1058
+ if (this.wrapper._getHtlcTimeout(data) <= (Date.now() / 1000))
1059
+ throw new IntermediaryError_1.IntermediaryError("HTLC expires too soon!");
1060
+ }
1061
+ /**
1062
+ * Waits till a lightning network payment is received by the intermediary, and the intermediary
1063
+ * initiates the swap HTLC on the smart chain side. After the HTLC is initiated you can wait
1064
+ * for an automatic settlement by the watchtowers with the {@link waitTillClaimed} function,
1065
+ * or settle manually using the {@link claim} or {@link txsClaim} functions.
1066
+ *
1067
+ * If this swap is using an LNURL-withdraw link as input, it automatically posts the
1068
+ * generated invoice to the LNURL service to pay it.
1069
+ *
1070
+ * @param onPaymentReceived Callback as for when the LP reports having received the ln payment
1071
+ * @param abortSignal Abort signal to stop waiting for payment
1072
+ * @param checkIntervalSeconds How often to poll the intermediary for answer (default 5 seconds)
1073
+ */
1074
+ async waitForPayment(onPaymentReceived, checkIntervalSeconds, abortSignal) {
1075
+ checkIntervalSeconds ??= 5;
1076
+ if (this._state === FromBTCLNAutoSwapState.PR_PAID) {
1077
+ await this.waitTillCommited(checkIntervalSeconds, abortSignal);
1078
+ }
1079
+ if (this._state >= FromBTCLNAutoSwapState.CLAIM_COMMITED)
1080
+ return true;
1081
+ const success = await this._waitForLpPaymentReceived(checkIntervalSeconds, abortSignal);
1082
+ if (!success)
1083
+ return false;
1084
+ if (onPaymentReceived != null)
1085
+ onPaymentReceived(this.getInputTxId());
900
1086
  if (this._state === FromBTCLNAutoSwapState.PR_PAID) {
901
1087
  await this.waitTillCommited(checkIntervalSeconds, abortSignal);
902
1088
  }
@@ -930,7 +1116,7 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
930
1116
  abortController.abort();
931
1117
  throw e;
932
1118
  }
933
- if (result === false) {
1119
+ if (result === null) {
934
1120
  this.logger.debug("waitTillCommited(): Resolved from watchdog - HTLC expired");
935
1121
  if (this._state === FromBTCLNAutoSwapState.PR_PAID) {
936
1122
  await this._saveAndEmit(FromBTCLNAutoSwapState.EXPIRED);
@@ -938,12 +1124,15 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
938
1124
  return;
939
1125
  }
940
1126
  if (this._state === FromBTCLNAutoSwapState.PR_PAID) {
1127
+ if (typeof (result) === "object" && result.getInitTxId != null && this._commitTxId == null)
1128
+ this._commitTxId = await result.getInitTxId();
941
1129
  this._commitedAt ??= Date.now();
942
1130
  await this._saveAndEmit(FromBTCLNAutoSwapState.CLAIM_COMMITED);
943
1131
  }
944
- if (result === 0)
1132
+ if (result === 0) {
945
1133
  this.logger.debug("waitTillCommited(): Resolved from state changed");
946
- if (result === true) {
1134
+ }
1135
+ else if (result != null) {
947
1136
  this.logger.debug("waitTillCommited(): Resolved from watchdog - commited");
948
1137
  if (this.secret != null)
949
1138
  await this._broadcastSecret().catch(e => {
@@ -1019,12 +1208,13 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
1019
1208
  * @param abortSignal AbortSignal
1020
1209
  * @param secret A swap secret to broadcast to watchtowers, generally only needed if the swap
1021
1210
  * was recovered from on-chain data, or the pre-image was generated outside the SDK
1211
+ * @param pollIntervalSeconds How often to poll via the watchdog
1022
1212
  *
1023
1213
  * @throws {Error} If swap is in invalid state (must be {@link FromBTCLNAutoSwapState.CLAIM_COMMITED})
1024
1214
  * @throws {Error} If the LP refunded sooner than we were able to claim
1025
1215
  * @returns {boolean} whether the swap was claimed in time or not
1026
1216
  */
1027
- async waitTillClaimed(maxWaitTimeSeconds, abortSignal, secret) {
1217
+ async waitTillClaimed(maxWaitTimeSeconds, abortSignal, secret, pollIntervalSeconds) {
1028
1218
  if (this._state === FromBTCLNAutoSwapState.CLAIM_CLAIMED)
1029
1219
  return Promise.resolve(true);
1030
1220
  if (this._state !== FromBTCLNAutoSwapState.CLAIM_COMMITED)
@@ -1048,7 +1238,7 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
1048
1238
  let res;
1049
1239
  try {
1050
1240
  res = await Promise.race([
1051
- this.watchdogWaitTillResult(undefined, abortController.signal),
1241
+ this.watchdogWaitTillResult(pollIntervalSeconds, abortController.signal),
1052
1242
  this.waitTillState(FromBTCLNAutoSwapState.CLAIM_CLAIMED, "eq", abortController.signal).then(() => 0),
1053
1243
  this.waitTillState(FromBTCLNAutoSwapState.EXPIRED, "eq", abortController.signal).then(() => 1),
1054
1244
  ]);
@@ -1260,6 +1450,8 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
1260
1450
  async _forciblySetOnchainState(commitStatus) {
1261
1451
  switch (commitStatus?.type) {
1262
1452
  case base_1.SwapCommitStateType.PAID:
1453
+ if (this._commitTxId == null && commitStatus.getInitTxId != null)
1454
+ this._commitTxId = await commitStatus.getInitTxId();
1263
1455
  if (this._claimTxId == null)
1264
1456
  this._claimTxId = await commitStatus.getClaimTxId();
1265
1457
  if (this.secret == null || this.pr == null)
@@ -1267,25 +1459,39 @@ class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
1267
1459
  this._state = FromBTCLNAutoSwapState.CLAIM_CLAIMED;
1268
1460
  return true;
1269
1461
  case base_1.SwapCommitStateType.NOT_COMMITED:
1270
- if (this._refundTxId == null && commitStatus.getRefundTxId != null)
1462
+ let changed = false;
1463
+ if (this._commitTxId == null && commitStatus.getInitTxId != null) {
1464
+ this._commitTxId = await commitStatus.getInitTxId();
1465
+ changed = true;
1466
+ }
1467
+ if (this._refundTxId == null && commitStatus.getRefundTxId != null) {
1271
1468
  this._refundTxId = await commitStatus.getRefundTxId();
1469
+ changed = true;
1470
+ }
1272
1471
  if (this._refundTxId != null) {
1273
1472
  this._state = FromBTCLNAutoSwapState.FAILED;
1274
- return true;
1473
+ changed = true;
1275
1474
  }
1276
- break;
1475
+ return changed;
1277
1476
  case base_1.SwapCommitStateType.EXPIRED:
1477
+ if (this._commitTxId == null && commitStatus.getInitTxId != null)
1478
+ this._commitTxId = await commitStatus.getInitTxId();
1278
1479
  if (this._refundTxId == null && commitStatus.getRefundTxId != null)
1279
1480
  this._refundTxId = await commitStatus.getRefundTxId();
1280
1481
  this._state = this._refundTxId == null ? FromBTCLNAutoSwapState.QUOTE_EXPIRED : FromBTCLNAutoSwapState.FAILED;
1281
1482
  return true;
1282
1483
  case base_1.SwapCommitStateType.COMMITED:
1484
+ let save = false;
1485
+ if (this._commitTxId == null && commitStatus.getInitTxId != null) {
1486
+ this._commitTxId = await commitStatus.getInitTxId();
1487
+ save = true;
1488
+ }
1283
1489
  if (this._state !== FromBTCLNAutoSwapState.CLAIM_COMMITED && this._state !== FromBTCLNAutoSwapState.EXPIRED) {
1284
1490
  this._commitedAt ??= Date.now();
1285
1491
  this._state = FromBTCLNAutoSwapState.CLAIM_COMMITED;
1286
- return true;
1492
+ save = true;
1287
1493
  }
1288
- break;
1494
+ return save;
1289
1495
  }
1290
1496
  return false;
1291
1497
  }
@@ -5,6 +5,7 @@ import { ChainType, ClaimEvent, InitializeEvent, LightningNetworkApi, Messenger,
5
5
  import { Intermediary } from "../../../../intermediaries/Intermediary";
6
6
  import { Buffer } from "buffer";
7
7
  import { SwapType } from "../../../../enums/SwapType";
8
+ import { IntermediaryAPI } from "../../../../intermediaries/apis/IntermediaryAPI";
8
9
  import { ISwapPrice } from "../../../../prices/abstract/ISwapPrice";
9
10
  import { EventEmitter } from "events";
10
11
  import { ISwapWrapperOptions, WrapperCtorTokens } from "../../../ISwapWrapper";
@@ -113,6 +114,7 @@ export declare class FromBTCLNAutoWrapper<T extends ChainType> extends IFromBTCL
113
114
  * @param versionedContracts
114
115
  * @param lnApi
115
116
  * @param messenger
117
+ * @param lpApi
116
118
  * @param options
117
119
  * @param events Instance to use for emitting events
118
120
  */
@@ -121,7 +123,7 @@ export declare class FromBTCLNAutoWrapper<T extends ChainType> extends IFromBTCL
121
123
  swapContract: T["Contract"];
122
124
  swapDataConstructor: new (data: any) => T["Data"];
123
125
  };
124
- }, lnApi: LightningNetworkApi, messenger: Messenger, options?: AllOptional<FromBTCLNAutoWrapperOptions>, events?: EventEmitter<{
126
+ }, lnApi: LightningNetworkApi, messenger: Messenger, lpApi: IntermediaryAPI, options?: AllOptional<FromBTCLNAutoWrapperOptions>, events?: EventEmitter<{
125
127
  swapState: [ISwap];
126
128
  }>);
127
129
  /**
@@ -9,7 +9,6 @@ const UserError_1 = require("../../../../errors/UserError");
9
9
  const IntermediaryError_1 = require("../../../../errors/IntermediaryError");
10
10
  const SwapType_1 = require("../../../../enums/SwapType");
11
11
  const Utils_1 = require("../../../../utils/Utils");
12
- const IntermediaryAPI_1 = require("../../../../intermediaries/apis/IntermediaryAPI");
13
12
  const RequestError_1 = require("../../../../errors/RequestError");
14
13
  const FromBTCLNAutoSwap_1 = require("./FromBTCLNAutoSwap");
15
14
  const IFromBTCLNWrapper_1 = require("../IFromBTCLNWrapper");
@@ -34,11 +33,12 @@ class FromBTCLNAutoWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
34
33
  * @param versionedContracts
35
34
  * @param lnApi
36
35
  * @param messenger
36
+ * @param lpApi
37
37
  * @param options
38
38
  * @param events Instance to use for emitting events
39
39
  */
40
- constructor(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lnApi, messenger, options, events) {
41
- super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lnApi, {
40
+ constructor(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lnApi, messenger, lpApi, options, events) {
41
+ super(chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lnApi, lpApi, {
42
42
  ...options,
43
43
  safetyFactor: options?.safetyFactor ?? 2,
44
44
  bitcoinBlocktime: options?.bitcoinBlocktime ?? 10 * 60,
@@ -270,7 +270,7 @@ class FromBTCLNAutoWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
270
270
  const abortController = (0, Utils_1.extendAbortController)(_abortController.signal);
271
271
  const liquidityPromise = this.preFetchIntermediaryLiquidity(amountData, lp, abortController, version);
272
272
  const { lnCapacityPromise, resp } = await (0, RetryUtils_1.tryWithRetries)(async (retryCount) => {
273
- const { lnPublicKey, response } = IntermediaryAPI_1.IntermediaryAPI.initFromBTCLNAuto(this.chainIdentifier, lp.url, {
273
+ const { lnPublicKey, response } = this._lpApi.initFromBTCLNAuto(this.chainIdentifier, lp.url, {
274
274
  paymentHash,
275
275
  amount: amountData.amount,
276
276
  claimer: recipient,
@@ -281,7 +281,7 @@ class FromBTCLNAutoWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
281
281
  additionalParams,
282
282
  gasToken: this._chain.getNativeCurrencyAddress(),
283
283
  gasAmount: _options.gasAmount,
284
- claimerBounty: (0, Utils_1.throwIfUndefined)(_preFetches.claimerBountyPrefetch[version])
284
+ claimerBounty: (0, Utils_1.throwIfUndefined)(_preFetches.claimerBountyPrefetch[version], "Watchtower fee pre-fetch failed!")
285
285
  }, this._options.postRequestTimeout, abortController.signal, retryCount > 0 ? false : undefined);
286
286
  let lnCapacityPromise;
287
287
  if (!_options.unsafeSkipLnNodeCheck) {
@@ -307,7 +307,7 @@ class FromBTCLNAutoWrapper extends IFromBTCLNWrapper_1.IFromBTCLNWrapper {
307
307
  this.verifyReturnedPrice(lp.services[SwapType_1.SwapType.FROM_BTCLN_AUTO], false, resp.btcAmountSwap, resp.total, amountData.token, { swapFeeBtc: resp.swapFeeBtc }, _preFetches.pricePrefetchPromise, _preFetches.usdPricePrefetchPromise, abortController.signal),
308
308
  _options.gasAmount === 0n ? Promise.resolve(undefined) : this.verifyReturnedPrice({ ...lp.services[SwapType_1.SwapType.FROM_BTCLN_AUTO], swapBaseFee: 0 }, //Base fee should be charged only on the amount, not on gas
309
309
  false, resp.btcAmountGas, resp.totalGas + resp.claimerBounty, nativeTokenAddress, { swapFeeBtc: resp.gasSwapFeeBtc }, _preFetches.gasTokenPricePrefetchPromise, _preFetches.usdPricePrefetchPromise, abortController.signal),
310
- this.verifyIntermediaryLiquidity(resp.total, (0, Utils_1.throwIfUndefined)(liquidityPromise)),
310
+ this.verifyIntermediaryLiquidity(resp.total, (0, Utils_1.throwIfUndefined)(liquidityPromise, "LP liquidity pre-fetch failed!")),
311
311
  _options.unsafeSkipLnNodeCheck ? Promise.resolve() : this.verifyLnNodeCapacity(lp, decodedPr, lnCapacityPromise, abortController.signal)
312
312
  ]);
313
313
  const swapInit = {