@atomiqlabs/sdk 8.8.3 → 8.9.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 (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 +41 -3
  35. package/dist/swapper/Swapper.js +93 -48
  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 +134 -52
  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
@@ -1,5 +1,5 @@
1
1
  import { ISwap, ISwapInit } from "../ISwap";
2
- import { ChainType, SpvWithdrawalClaimedState, SpvWithdrawalClosedState, SpvWithdrawalFrontedState } from "@atomiqlabs/base";
2
+ import { BtcTx, ChainType, SpvWithdrawalClaimedState, SpvWithdrawalClosedState, SpvWithdrawalFrontedState } from "@atomiqlabs/base";
3
3
  import { SwapType } from "../../enums/SwapType";
4
4
  import { SpvFromBTCTypeDefinition, SpvFromBTCWrapper } from "./SpvFromBTCWrapper";
5
5
  import { Transaction } from "@scure/btc-signer";
@@ -14,7 +14,9 @@ import { TokenAmount } from "../../types/TokenAmount";
14
14
  import { BtcToken, SCToken } from "../../types/Token";
15
15
  import { LoggerType } from "../../utils/Logger";
16
16
  import { PriceInfoType } from "../../types/PriceInfoType";
17
- import { SwapExecutionAction, SwapExecutionActionBitcoin } from "../../types/SwapExecutionAction";
17
+ import { SwapExecutionActionSignPSBT, SwapExecutionActionSignSmartChainTx, SwapExecutionActionWait } from "../../types/SwapExecutionAction";
18
+ import { SwapExecutionStepPayment, SwapExecutionStepSettlement } from "../../types/SwapExecutionStep";
19
+ import { SwapStateInfo } from "../../types/SwapStateInfo";
18
20
  /**
19
21
  * State enum for SPV vault (UTXO-controlled vault) based swaps
20
22
  * @category Swaps/Bitcoin → Smart chain
@@ -404,13 +406,15 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
404
406
  /**
405
407
  * Returns the raw PSBT (not funded), the wallet should fund the PSBT (add its inputs) and importantly **set the nSequence field of the
406
408
  * 2nd input** (input 1 - indexing from 0) to the value returned in `in1sequence`, sign the PSBT and then pass
407
- * it back to the swap with {@link submitPsbt} function.
409
+ * it back to the swap with {@link submitPsbt} function. The transaction should use at least the returned `feeRate`
410
+ * sats/vB as the transaction fee.
408
411
  */
409
412
  getPsbt(): Promise<{
410
413
  psbt: Transaction;
411
414
  psbtHex: string;
412
415
  psbtBase64: string;
413
416
  in1sequence: number;
417
+ feeRate: number;
414
418
  }>;
415
419
  /**
416
420
  * Returns the PSBT that is already funded with wallet's UTXOs (runs a coin-selection algorithm to choose UTXOs to use),
@@ -439,6 +443,7 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
439
443
  psbtHex: string;
440
444
  psbtBase64: string;
441
445
  signInputs: number[];
446
+ feeRate: number;
442
447
  }>;
443
448
  /**
444
449
  * @inheritDoc
@@ -477,20 +482,44 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
477
482
  spendFully?: boolean;
478
483
  }): Promise<boolean>;
479
484
  /**
480
- * @inheritDoc
481
- *
482
- * @param options.bitcoinFeeRate Optional fee rate to use for the created Bitcoin transaction
483
- * @param options.bitcoinWallet Optional bitcoin wallet address specification to return a funded PSBT,
484
- * if not provided a raw PSBT is returned instead which necessitates the implementor to manually add
485
- * inputs to the bitcoin transaction and **set the nSequence field of the 2nd input** (input 1 -
486
- * indexing from 0) to the value returned in `in1sequence`
485
+ * @internal
487
486
  */
488
- txsExecute(options?: {
487
+ protected _getExecutionStatus(options?: {
489
488
  bitcoinFeeRate?: number;
490
489
  bitcoinWallet?: MinimalBitcoinWalletInterface;
491
- }): Promise<[
492
- SwapExecutionActionBitcoin<"RAW_PSBT" | "FUNDED_PSBT">
493
- ]>;
490
+ manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"];
491
+ maxWaitTillAutomaticSettlementSeconds?: number;
492
+ }): Promise<{
493
+ steps: [SwapExecutionStepPayment<"BITCOIN">, SwapExecutionStepSettlement<T["ChainId"], "awaiting_automatic" | "awaiting_manual">];
494
+ buildCurrentAction: (actionOptions?: {
495
+ bitcoinFeeRate?: number;
496
+ bitcoinWallet?: MinimalBitcoinWalletInterface;
497
+ manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"];
498
+ maxWaitTillAutomaticSettlementSeconds?: number;
499
+ }) => Promise<SwapExecutionActionSignPSBT | SwapExecutionActionWait<"BITCOIN_CONFS" | "SETTLEMENT"> | SwapExecutionActionSignSmartChainTx<T> | undefined>;
500
+ state: number;
501
+ }>;
502
+ /**
503
+ * @inheritDoc
504
+ * @internal
505
+ */
506
+ _submitExecutionTransactions(txs: (T["SignedTXType"] | Transaction | string)[], abortSignal?: AbortSignal, requiredStates?: SpvFromBTCSwapState[], idempotent?: boolean): Promise<string[]>;
507
+ /**
508
+ * @internal
509
+ */
510
+ private _buildDepositPsbtAction;
511
+ /**
512
+ * @internal
513
+ */
514
+ private _buildWaitBitcoinConfirmationsAction;
515
+ /**
516
+ * @internal
517
+ */
518
+ private _buildWaitSettlementAction;
519
+ /**
520
+ * @internal
521
+ */
522
+ private _buildClaimSmartChainTxAction;
494
523
  /**
495
524
  * @inheritDoc
496
525
  *
@@ -503,12 +532,38 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
503
532
  * @param options.maxWaitTillAutomaticSettlementSeconds Maximum time to wait for an automatic settlement after
504
533
  * the bitcoin transaction is confirmed (defaults to 60 seconds)
505
534
  */
506
- getCurrentActions(options?: {
535
+ getExecutionAction(options?: {
536
+ bitcoinFeeRate?: number;
537
+ bitcoinWallet?: MinimalBitcoinWalletInterface;
538
+ manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"];
539
+ maxWaitTillAutomaticSettlementSeconds?: number;
540
+ }): Promise<SwapExecutionActionSignPSBT | SwapExecutionActionWait<"BITCOIN_CONFS" | "SETTLEMENT"> | SwapExecutionActionSignSmartChainTx<T> | undefined>;
541
+ /**
542
+ * @inheritDoc
543
+ */
544
+ getExecutionStatus(options?: {
545
+ skipBuildingAction?: boolean;
507
546
  bitcoinFeeRate?: number;
508
547
  bitcoinWallet?: MinimalBitcoinWalletInterface;
509
548
  manualSettlementSmartChainSigner?: string | T["Signer"] | T["NativeSigner"];
510
549
  maxWaitTillAutomaticSettlementSeconds?: number;
511
- }): Promise<SwapExecutionAction<T>[]>;
550
+ }): Promise<{
551
+ steps: [
552
+ SwapExecutionStepPayment<"BITCOIN">,
553
+ SwapExecutionStepSettlement<T["ChainId"], "awaiting_automatic" | "awaiting_manual">
554
+ ];
555
+ currentAction: SwapExecutionActionSignPSBT | SwapExecutionActionWait<"BITCOIN_CONFS" | "SETTLEMENT"> | SwapExecutionActionSignSmartChainTx<T> | undefined;
556
+ stateInfo: SwapStateInfo<SpvFromBTCSwapState>;
557
+ }>;
558
+ /**
559
+ * @inheritDoc
560
+ */
561
+ getExecutionSteps(options?: {
562
+ maxWaitTillAutomaticSettlementSeconds?: number;
563
+ }): Promise<[
564
+ SwapExecutionStepPayment<"BITCOIN">,
565
+ SwapExecutionStepSettlement<T["ChainId"], "awaiting_automatic" | "awaiting_manual">
566
+ ]>;
512
567
  /**
513
568
  * Checks whether a bitcoin payment was already made, returns the payment or null when no payment has been made.
514
569
  * @internal
@@ -517,6 +572,7 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
517
572
  txId: string;
518
573
  confirmations: number;
519
574
  targetConfirmations: number;
575
+ btcTx: BtcTx;
520
576
  inputAddresses?: string[];
521
577
  } | null>;
522
578
  /**
@@ -556,11 +612,11 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
556
612
  /**
557
613
  * Periodically checks the chain to see whether the swap was finished (claimed or refunded)
558
614
  *
559
- * @param abortSignal
560
615
  * @param interval How often to check (in seconds), default to 5s
616
+ * @param abortSignal
561
617
  * @internal
562
618
  */
563
- protected watchdogWaitTillResult(abortSignal?: AbortSignal, interval?: number): Promise<SpvWithdrawalClaimedState | SpvWithdrawalFrontedState | SpvWithdrawalClosedState>;
619
+ protected watchdogWaitTillResult(interval?: number, abortSignal?: AbortSignal): Promise<SpvWithdrawalClaimedState | SpvWithdrawalFrontedState | SpvWithdrawalClosedState>;
564
620
  /**
565
621
  * Waits till the swap is successfully settled (claimed), should be called after sending the claim (settlement)
566
622
  * transactions manually to wait till the SDK processes the settlement and updates the swap state accordingly.
@@ -581,11 +637,12 @@ export declare class SpvFromBTCSwap<T extends ChainType> extends ISwap<T, SpvFro
581
637
  * @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled (by default
582
638
  * it waits indefinitely)
583
639
  * @param abortSignal Abort signal
640
+ * @param pollIntervalSeconds How often to poll via the watchdog
584
641
  *
585
642
  * @returns {boolean} whether the swap was claimed or fronted automatically or not, if the swap was not claimed
586
643
  * the user can claim manually through the {@link claim} function
587
644
  */
588
- waitTillClaimedOrFronted(maxWaitTimeSeconds?: number, abortSignal?: AbortSignal): Promise<boolean>;
645
+ waitTillClaimedOrFronted(maxWaitTimeSeconds?: number, abortSignal?: AbortSignal, pollIntervalSeconds?: number): Promise<boolean>;
589
646
  /**
590
647
  * Waits till the bitcoin transaction confirms and swap settled on the destination chain
591
648
  *
@@ -9,7 +9,6 @@ const BitcoinUtils_1 = require("../../utils/BitcoinUtils");
9
9
  const btc_signer_1 = require("@scure/btc-signer");
10
10
  const buffer_1 = require("buffer");
11
11
  const IBitcoinWallet_1 = require("../../bitcoin/wallet/IBitcoinWallet");
12
- const IntermediaryAPI_1 = require("../../intermediaries/apis/IntermediaryAPI");
13
12
  const FeeType_1 = require("../../enums/FeeType");
14
13
  const PercentagePPM_1 = require("../../types/fees/PercentagePPM");
15
14
  const TokenAmount_1 = require("../../types/TokenAmount");
@@ -334,7 +333,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
334
333
  * @inheritDoc
335
334
  */
336
335
  isFinished() {
337
- return this._state === SpvFromBTCSwapState.CLAIMED || this._state === SpvFromBTCSwapState.QUOTE_EXPIRED || this._state === SpvFromBTCSwapState.FAILED;
336
+ return this.isSuccessful() || this.isFailed() || this.isQuoteExpired();
338
337
  }
339
338
  /**
340
339
  * @inheritDoc
@@ -588,7 +587,8 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
588
587
  /**
589
588
  * Returns the raw PSBT (not funded), the wallet should fund the PSBT (add its inputs) and importantly **set the nSequence field of the
590
589
  * 2nd input** (input 1 - indexing from 0) to the value returned in `in1sequence`, sign the PSBT and then pass
591
- * it back to the swap with {@link submitPsbt} function.
590
+ * it back to the swap with {@link submitPsbt} function. The transaction should use at least the returned `feeRate`
591
+ * sats/vB as the transaction fee.
592
592
  */
593
593
  async getPsbt() {
594
594
  const res = await this.getTransactionDetails();
@@ -623,7 +623,8 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
623
623
  psbt,
624
624
  psbtHex: serializedPsbt.toString("hex"),
625
625
  psbtBase64: serializedPsbt.toString("base64"),
626
- in1sequence: res.in1sequence
626
+ in1sequence: res.in1sequence,
627
+ feeRate: this.minimumBtcFeeRate
627
628
  };
628
629
  }
629
630
  /**
@@ -671,7 +672,8 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
671
672
  psbt,
672
673
  psbtHex: serializedPsbt.toString("hex"),
673
674
  psbtBase64: serializedPsbt.toString("base64"),
674
- signInputs
675
+ signInputs,
676
+ feeRate
675
677
  };
676
678
  }
677
679
  /**
@@ -738,7 +740,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
738
740
  this.posted = true;
739
741
  await this._saveAndEmit(SpvFromBTCSwapState.SIGNED);
740
742
  try {
741
- await IntermediaryAPI_1.IntermediaryAPI.initSpvFromBTC(this.chainIdentifier, this.url, {
743
+ await this.wrapper._lpApi.initSpvFromBTC(this.chainIdentifier, this.url, {
742
744
  quoteId: this.quoteId,
743
745
  psbtHex: buffer_1.Buffer.from(psbt.toPSBT(0)).toString("hex")
744
746
  });
@@ -820,32 +822,267 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
820
822
  throw new Error("Unexpected state reached!");
821
823
  }
822
824
  /**
823
- * @inheritDoc
824
- *
825
- * @param options.bitcoinFeeRate Optional fee rate to use for the created Bitcoin transaction
826
- * @param options.bitcoinWallet Optional bitcoin wallet address specification to return a funded PSBT,
827
- * if not provided a raw PSBT is returned instead which necessitates the implementor to manually add
828
- * inputs to the bitcoin transaction and **set the nSequence field of the 2nd input** (input 1 -
829
- * indexing from 0) to the value returned in `in1sequence`
825
+ * @internal
830
826
  */
831
- async txsExecute(options) {
832
- if (this._state === SpvFromBTCSwapState.CREATED) {
833
- if (!await this._verifyQuoteValid())
834
- throw new Error("Quote already expired or close to expiry!");
835
- return [
827
+ async _getExecutionStatus(options) {
828
+ const state = this._state;
829
+ const now = Date.now();
830
+ let confirmations;
831
+ let bitcoinPaymentStatus = "inactive";
832
+ let destinationSettlementStatus = "inactive";
833
+ let buildCurrentAction = async () => undefined;
834
+ switch (state) {
835
+ case SpvFromBTCSwapState.QUOTE_EXPIRED:
836
+ case SpvFromBTCSwapState.DECLINED:
837
+ case SpvFromBTCSwapState.FAILED:
838
+ bitcoinPaymentStatus = "expired";
839
+ break;
840
+ case SpvFromBTCSwapState.CREATED: {
841
+ const quoteValid = await this._verifyQuoteValid();
842
+ bitcoinPaymentStatus = quoteValid ? "awaiting" : "soft_expired";
843
+ if (quoteValid) {
844
+ buildCurrentAction = this._buildDepositPsbtAction.bind(this);
845
+ }
846
+ break;
847
+ }
848
+ case SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED:
849
+ case SpvFromBTCSwapState.SIGNED:
850
+ case SpvFromBTCSwapState.POSTED:
851
+ case SpvFromBTCSwapState.BROADCASTED:
852
+ case SpvFromBTCSwapState.FRONTED: {
853
+ const bitcoinPayment = await this.getBitcoinPayment();
854
+ let bitcoinConfirmationDelay = -1;
855
+ let knownBitcoinPaymentStatus;
856
+ if (bitcoinPayment != null) {
857
+ if (bitcoinPayment.confirmations >= bitcoinPayment.targetConfirmations) {
858
+ knownBitcoinPaymentStatus = "confirmed";
859
+ }
860
+ else {
861
+ const result = await this.wrapper._btcRpc.getConfirmationDelay(bitcoinPayment.btcTx, bitcoinPayment.targetConfirmations);
862
+ confirmations = {
863
+ current: bitcoinPayment.confirmations,
864
+ target: bitcoinPayment.targetConfirmations,
865
+ etaSeconds: result ?? -1
866
+ };
867
+ knownBitcoinPaymentStatus = "received";
868
+ bitcoinConfirmationDelay = result ?? -1;
869
+ }
870
+ }
871
+ if (state === SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED)
872
+ bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "soft_expired";
873
+ if (state === SpvFromBTCSwapState.POSTED || state === SpvFromBTCSwapState.SIGNED)
874
+ bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "awaiting";
875
+ if (state === SpvFromBTCSwapState.BROADCASTED)
876
+ bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "received";
877
+ destinationSettlementStatus = "inactive";
878
+ if (state === SpvFromBTCSwapState.FRONTED) {
879
+ bitcoinPaymentStatus = knownBitcoinPaymentStatus ?? "received";
880
+ destinationSettlementStatus = "settled";
881
+ }
882
+ if (state === SpvFromBTCSwapState.SIGNED ||
883
+ state === SpvFromBTCSwapState.POSTED ||
884
+ state === SpvFromBTCSwapState.BROADCASTED) {
885
+ buildCurrentAction = this._buildWaitBitcoinConfirmationsAction.bind(this, bitcoinConfirmationDelay);
886
+ }
887
+ break;
888
+ }
889
+ case SpvFromBTCSwapState.BTC_TX_CONFIRMED:
890
+ bitcoinPaymentStatus = "confirmed";
891
+ if (this.btcTxConfirmedAt == null ||
892
+ options?.maxWaitTillAutomaticSettlementSeconds === 0 ||
893
+ (now - this.btcTxConfirmedAt) > (options?.maxWaitTillAutomaticSettlementSeconds ?? 60) * 1000) {
894
+ destinationSettlementStatus = "awaiting_manual";
895
+ buildCurrentAction = this._buildClaimSmartChainTxAction.bind(this);
896
+ }
897
+ else {
898
+ destinationSettlementStatus = "awaiting_automatic";
899
+ buildCurrentAction = this._buildWaitSettlementAction.bind(this, options?.maxWaitTillAutomaticSettlementSeconds);
900
+ }
901
+ break;
902
+ case SpvFromBTCSwapState.CLAIMED:
903
+ bitcoinPaymentStatus = "confirmed";
904
+ destinationSettlementStatus = "settled";
905
+ break;
906
+ case SpvFromBTCSwapState.CLOSED:
907
+ bitcoinPaymentStatus = "confirmed";
908
+ destinationSettlementStatus = "expired";
909
+ break;
910
+ }
911
+ if (bitcoinPaymentStatus === "confirmed") {
912
+ confirmations = {
913
+ current: this.getRequiredConfirmationsCount(),
914
+ target: this.getRequiredConfirmationsCount(),
915
+ etaSeconds: 0
916
+ };
917
+ }
918
+ return {
919
+ steps: [
836
920
  {
837
- name: "Payment",
838
- description: "Send funds to the bitcoin swap address",
921
+ type: "Payment",
922
+ side: "source",
839
923
  chain: "BITCOIN",
840
- txs: [
841
- options?.bitcoinWallet == null
842
- ? { ...await this.getPsbt(), type: "RAW_PSBT" }
843
- : { ...await this.getFundedPsbt(options.bitcoinWallet, options?.bitcoinFeeRate), type: "FUNDED_PSBT" }
844
- ]
924
+ title: "Bitcoin payment",
925
+ description: "Sign and submit the Bitcoin swap PSBT, then wait for the bitcoin transaction to confirm",
926
+ status: bitcoinPaymentStatus,
927
+ confirmations,
928
+ initTxId: this._data?.btcTx?.txid,
929
+ settleTxId: bitcoinPaymentStatus === "confirmed" ? this._data?.btcTx?.txid : undefined
930
+ },
931
+ {
932
+ type: "Settlement",
933
+ side: "destination",
934
+ chain: this.chainIdentifier,
935
+ title: "Destination settlement",
936
+ description: `Wait for automatic settlement on the ${this.chainIdentifier} side, or settle manually if it takes too long`,
937
+ status: destinationSettlementStatus,
938
+ initTxId: this._frontTxId ?? this._claimTxId,
939
+ settleTxId: this._frontTxId ?? this._claimTxId
940
+ }
941
+ ],
942
+ buildCurrentAction,
943
+ state
944
+ };
945
+ }
946
+ /**
947
+ * @inheritDoc
948
+ * @internal
949
+ */
950
+ async _submitExecutionTransactions(txs, abortSignal, requiredStates, idempotent) {
951
+ if (txs.length === 0)
952
+ throw new Error("Need to submit at least 1 transaction in the array, submitted empty array of transactions!");
953
+ // Handle idempotent calls
954
+ if (idempotent) {
955
+ let idempotencyTriggered = false;
956
+ const txIds = [];
957
+ for (let tx of txs) {
958
+ let parsedTx;
959
+ if (typeof (tx) === "string") {
960
+ try {
961
+ parsedTx = await this.wrapper._chain.deserializeSignedTx(tx);
962
+ }
963
+ catch (e) { }
964
+ try {
965
+ parsedTx = (0, BitcoinUtils_1.parsePsbtTransaction)(tx);
966
+ }
967
+ catch (e) { }
968
+ }
969
+ else {
970
+ parsedTx = tx;
845
971
  }
846
- ];
972
+ if (parsedTx == null) {
973
+ this.logger.debug("_submitExecutionTransactions(): Failed to parse provided execution transaction: ", tx);
974
+ continue;
975
+ }
976
+ if (parsedTx instanceof btc_signer_1.Transaction) {
977
+ // Bitcoin tx
978
+ const btcTx = await this.wrapper._btcRpc.parseTransaction(buffer_1.Buffer.from(parsedTx.toBytes(true)).toString("hex"));
979
+ if (btcTx.txid === this._data?.getTxId()) {
980
+ if (this._state !== SpvFromBTCSwapState.SIGNED && this._state !== SpvFromBTCSwapState.DECLINED)
981
+ idempotencyTriggered = true;
982
+ }
983
+ txIds.push(btcTx.txid);
984
+ }
985
+ else {
986
+ // SC tx
987
+ if (this.wrapper._chain.getTxId != null) {
988
+ const txId = await this.wrapper._chain.getTxId(parsedTx);
989
+ if (this._claimTxId === txId)
990
+ idempotencyTriggered = true;
991
+ txIds.push(txId);
992
+ }
993
+ }
994
+ }
995
+ if (idempotencyTriggered)
996
+ return txIds;
997
+ }
998
+ if (requiredStates != null && !requiredStates.includes(this._state))
999
+ throw new Error("Swap state has changed before transactions were submitted!");
1000
+ if (this._state === SpvFromBTCSwapState.CREATED || this._state === SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED) {
1001
+ let psbt;
1002
+ if (txs.length !== 1)
1003
+ throw new Error("Need to submit exactly 1 signed PSBT!");
1004
+ if (typeof (txs[0]) !== "string" && !(txs[0] instanceof btc_signer_1.Transaction))
1005
+ throw new Error("Must submit a valid PSBT as hex/base64 string or `@scure/btc-signer` Transaction object!");
1006
+ psbt = txs[0];
1007
+ return [await this.submitPsbt(psbt)];
1008
+ }
1009
+ if (this._state === SpvFromBTCSwapState.BTC_TX_CONFIRMED) {
1010
+ const parsedTxs = [];
1011
+ for (let tx of txs) {
1012
+ parsedTxs.push(typeof (tx) === "string" ? await this.wrapper._chain.deserializeSignedTx(tx) : tx);
1013
+ }
1014
+ const txIds = await this.wrapper._chain.sendSignedAndConfirm(parsedTxs, true, abortSignal, false);
1015
+ await this.waitTillClaimed(undefined, abortSignal);
1016
+ return txIds;
847
1017
  }
848
- throw new Error("Invalid swap state to obtain execution txns, required CREATED");
1018
+ throw new Error("Invalid swap state for transaction submission!");
1019
+ }
1020
+ /**
1021
+ * @internal
1022
+ */
1023
+ async _buildDepositPsbtAction(actionOptions) {
1024
+ return {
1025
+ type: "SignPSBT",
1026
+ name: "Deposit on Bitcoin",
1027
+ description: "Send funds to the bitcoin swap address",
1028
+ chain: "BITCOIN",
1029
+ txs: [
1030
+ actionOptions?.bitcoinWallet == null
1031
+ ? { ...await this.getPsbt(), type: "RAW_PSBT" }
1032
+ : { ...await this.getFundedPsbt(actionOptions.bitcoinWallet, actionOptions?.bitcoinFeeRate), type: "FUNDED_PSBT" }
1033
+ ],
1034
+ submitPsbt: async (signedPsbt, idempotent) => {
1035
+ return this._submitExecutionTransactions(Array.isArray(signedPsbt) ? signedPsbt : [signedPsbt], undefined, [SpvFromBTCSwapState.CREATED, SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED], idempotent);
1036
+ }
1037
+ };
1038
+ }
1039
+ /**
1040
+ * @internal
1041
+ */
1042
+ async _buildWaitBitcoinConfirmationsAction(confirmationDelay) {
1043
+ return {
1044
+ type: "Wait",
1045
+ name: "Bitcoin confirmations",
1046
+ description: "Wait for bitcoin transaction to confirm",
1047
+ pollTimeSeconds: 10,
1048
+ expectedTimeSeconds: confirmationDelay === -1 ? -1 : Math.floor(confirmationDelay / 1000),
1049
+ wait: async (maxWaitTimeSeconds, pollIntervalSeconds, abortSignal, btcConfirmationsCallback) => {
1050
+ const abortController = (0, Utils_1.extendAbortController)(abortSignal, maxWaitTimeSeconds, "Timed out waiting for bitcoin transaction");
1051
+ await this.waitForBitcoinTransaction(btcConfirmationsCallback, pollIntervalSeconds, abortController.signal);
1052
+ }
1053
+ };
1054
+ }
1055
+ /**
1056
+ * @internal
1057
+ */
1058
+ async _buildWaitSettlementAction(maxWaitTillAutomaticSettlementSeconds) {
1059
+ return {
1060
+ type: "Wait",
1061
+ name: "Automatic settlement",
1062
+ description: "Wait for bitcoin transaction to confirm",
1063
+ pollTimeSeconds: 5,
1064
+ expectedTimeSeconds: 10,
1065
+ wait: async (maxWaitTimeSeconds, pollIntervalSeconds, abortSignal) => {
1066
+ await this.waitTillClaimedOrFronted(maxWaitTimeSeconds ?? maxWaitTillAutomaticSettlementSeconds ?? 60, abortSignal, pollIntervalSeconds);
1067
+ }
1068
+ };
1069
+ }
1070
+ /**
1071
+ * @internal
1072
+ */
1073
+ async _buildClaimSmartChainTxAction(actionOptions) {
1074
+ const signerAddress = await this.wrapper._getSignerAddress(actionOptions?.manualSettlementSmartChainSigner);
1075
+ return {
1076
+ type: "SignSmartChainTransaction",
1077
+ name: "Settle manually",
1078
+ description: "Manually settle the swap on the destination smart chain",
1079
+ chain: this.chainIdentifier,
1080
+ txs: await this.prepareTransactions(this.txsClaim(actionOptions?.manualSettlementSmartChainSigner)),
1081
+ submitTransactions: async (txs, abortSignal, idempotent) => {
1082
+ return this._submitExecutionTransactions(txs, abortSignal, [SpvFromBTCSwapState.BTC_TX_CONFIRMED], idempotent);
1083
+ },
1084
+ requiredSigner: signerAddress ?? this._getInitiator()
1085
+ };
849
1086
  }
850
1087
  /**
851
1088
  * @inheritDoc
@@ -859,26 +1096,26 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
859
1096
  * @param options.maxWaitTillAutomaticSettlementSeconds Maximum time to wait for an automatic settlement after
860
1097
  * the bitcoin transaction is confirmed (defaults to 60 seconds)
861
1098
  */
862
- async getCurrentActions(options) {
863
- if (this._state === SpvFromBTCSwapState.CREATED) {
864
- try {
865
- return await this.txsExecute(options);
866
- }
867
- catch (e) { }
868
- }
869
- if (this._state === SpvFromBTCSwapState.BTC_TX_CONFIRMED) {
870
- if (this.btcTxConfirmedAt == null ||
871
- options?.maxWaitTillAutomaticSettlementSeconds === 0 ||
872
- (Date.now() - this.btcTxConfirmedAt) > (options?.maxWaitTillAutomaticSettlementSeconds ?? 60) * 1000) {
873
- return [{
874
- name: "Claim",
875
- description: "Manually settle (claim) the swap on the destination smart chain",
876
- chain: this.chainIdentifier,
877
- txs: await this.txsClaim(options?.manualSettlementSmartChainSigner)
878
- }];
879
- }
880
- }
881
- return [];
1099
+ async getExecutionAction(options) {
1100
+ const executionStatus = await this._getExecutionStatus(options);
1101
+ return executionStatus.buildCurrentAction(options);
1102
+ }
1103
+ /**
1104
+ * @inheritDoc
1105
+ */
1106
+ async getExecutionStatus(options) {
1107
+ const executionStatus = await this._getExecutionStatus(options);
1108
+ return {
1109
+ steps: executionStatus.steps,
1110
+ currentAction: options?.skipBuildingAction ? undefined : await executionStatus.buildCurrentAction(options),
1111
+ stateInfo: this._getStateInfo(executionStatus.state)
1112
+ };
1113
+ }
1114
+ /**
1115
+ * @inheritDoc
1116
+ */
1117
+ async getExecutionSteps(options) {
1118
+ return (await this._getExecutionStatus(options)).steps;
882
1119
  }
883
1120
  //////////////////////////////
884
1121
  //// Bitcoin tx listener
@@ -896,6 +1133,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
896
1133
  txId: result.txid,
897
1134
  confirmations: result.confirmations ?? 0,
898
1135
  targetConfirmations: this.vaultRequiredConfirmations,
1136
+ btcTx: result,
899
1137
  inputAddresses: result.inputAddresses
900
1138
  };
901
1139
  }
@@ -1053,11 +1291,11 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
1053
1291
  /**
1054
1292
  * Periodically checks the chain to see whether the swap was finished (claimed or refunded)
1055
1293
  *
1056
- * @param abortSignal
1057
1294
  * @param interval How often to check (in seconds), default to 5s
1295
+ * @param abortSignal
1058
1296
  * @internal
1059
1297
  */
1060
- async watchdogWaitTillResult(abortSignal, interval = 5) {
1298
+ async watchdogWaitTillResult(interval = 5, abortSignal) {
1061
1299
  if (this._data == null)
1062
1300
  throw new Error("Cannot await the result before the btc transaction is sent!");
1063
1301
  let status = { type: base_1.SpvWithdrawalStateType.NOT_FOUND };
@@ -1099,11 +1337,12 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
1099
1337
  * @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled (by default
1100
1338
  * it waits indefinitely)
1101
1339
  * @param abortSignal Abort signal
1340
+ * @param pollIntervalSeconds How often to poll via the watchdog
1102
1341
  *
1103
1342
  * @returns {boolean} whether the swap was claimed or fronted automatically or not, if the swap was not claimed
1104
1343
  * the user can claim manually through the {@link claim} function
1105
1344
  */
1106
- async waitTillClaimedOrFronted(maxWaitTimeSeconds, abortSignal) {
1345
+ async waitTillClaimedOrFronted(maxWaitTimeSeconds, abortSignal, pollIntervalSeconds) {
1107
1346
  if (this._state === SpvFromBTCSwapState.CLAIMED || this._state === SpvFromBTCSwapState.FRONTED)
1108
1347
  return Promise.resolve(true);
1109
1348
  const abortController = (0, Utils_1.extendAbortController)(abortSignal);
@@ -1118,7 +1357,7 @@ class SpvFromBTCSwap extends ISwap_1.ISwap {
1118
1357
  let res;
1119
1358
  try {
1120
1359
  res = await Promise.race([
1121
- this.watchdogWaitTillResult(abortController.signal),
1360
+ this.watchdogWaitTillResult(pollIntervalSeconds, abortController.signal),
1122
1361
  this.waitTillState(SpvFromBTCSwapState.CLAIMED, "eq", abortController.signal).then(() => 0),
1123
1362
  this.waitTillState(SpvFromBTCSwapState.FRONTED, "eq", abortController.signal).then(() => 1),
1124
1363
  this.waitTillState(SpvFromBTCSwapState.FAILED, "eq", abortController.signal).then(() => 2),
@@ -9,6 +9,7 @@ import { UnifiedSwapEventListener } from "../../events/UnifiedSwapEventListener"
9
9
  import { ISwapPrice } from "../../prices/abstract/ISwapPrice";
10
10
  import { EventEmitter } from "events";
11
11
  import { Intermediary } from "../../intermediaries/Intermediary";
12
+ import { IntermediaryAPI } from "../../intermediaries/apis/IntermediaryAPI";
12
13
  import { CoinselectAddressTypes } from "../../bitcoin/coinselect2";
13
14
  import { Transaction } from "@scure/btc-signer";
14
15
  import { ISwap } from "../ISwap";
@@ -138,6 +139,7 @@ export declare class SpvFromBTCWrapper<T extends ChainType> extends ISwapWrapper
138
139
  * @param versionedContracts
139
140
  * @param versionedSynchronizer
140
141
  * @param btcRpc Bitcoin RPC which also supports getting transactions by txoHash
142
+ * @param lpApi
141
143
  * @param options
142
144
  * @param events Instance to use for emitting events
143
145
  */
@@ -151,7 +153,7 @@ export declare class SpvFromBTCWrapper<T extends ChainType> extends ISwapWrapper
151
153
  [version: string]: {
152
154
  synchronizer: RelaySynchronizer<any, T["TX"], any>;
153
155
  };
154
- }, btcRpc: BitcoinRpcWithAddressIndex<any>, options?: AllOptional<SpvFromBTCWrapperOptions>, events?: EventEmitter<{
156
+ }, btcRpc: BitcoinRpcWithAddressIndex<any>, lpApi: IntermediaryAPI, options?: AllOptional<SpvFromBTCWrapperOptions>, events?: EventEmitter<{
155
157
  swapState: [ISwap];
156
158
  }>);
157
159
  private processEventFront;