@atomiqlabs/sdk 8.1.8 → 8.3.5
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.
- package/dist/bitcoin/coinselect2/utils.d.ts +6 -0
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +41 -5
- package/dist/bitcoin/wallet/BitcoinWallet.js +36 -1
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +52 -2
- package/dist/bitcoin/wallet/IBitcoinWallet.js +2 -1
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +42 -7
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +36 -1
- package/dist/enums/FeeType.d.ts +8 -1
- package/dist/enums/FeeType.js +8 -1
- package/dist/enums/SwapAmountType.d.ts +7 -0
- package/dist/enums/SwapAmountType.js +7 -0
- package/dist/enums/SwapDirection.d.ts +7 -0
- package/dist/enums/SwapDirection.js +7 -0
- package/dist/enums/SwapType.d.ts +62 -1
- package/dist/enums/SwapType.js +62 -1
- package/dist/errors/IntermediaryError.d.ts +4 -0
- package/dist/errors/IntermediaryError.js +1 -0
- package/dist/errors/RequestError.d.ts +15 -1
- package/dist/errors/RequestError.js +8 -0
- package/dist/errors/UserError.d.ts +1 -0
- package/dist/errors/UserError.js +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +7 -6
- package/dist/intermediaries/Intermediary.d.ts +61 -14
- package/dist/intermediaries/Intermediary.js +38 -11
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +62 -29
- package/dist/intermediaries/IntermediaryDiscovery.js +39 -24
- package/dist/prices/RedundantSwapPrice.d.ts +26 -5
- package/dist/prices/RedundantSwapPrice.js +22 -2
- package/dist/prices/SingleSwapPrice.d.ts +10 -7
- package/dist/prices/SingleSwapPrice.js +11 -8
- package/dist/prices/SwapPriceWithChain.d.ts +56 -19
- package/dist/prices/SwapPriceWithChain.js +62 -25
- package/dist/prices/abstract/IPriceProvider.d.ts +4 -4
- package/dist/prices/abstract/IPriceProvider.js +1 -1
- package/dist/prices/abstract/ISwapPrice.d.ts +95 -46
- package/dist/prices/abstract/ISwapPrice.js +104 -56
- package/dist/prices/providers/BinancePriceProvider.d.ts +8 -1
- package/dist/prices/providers/BinancePriceProvider.js +8 -1
- package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +7 -1
- package/dist/prices/providers/CoinGeckoPriceProvider.js +7 -1
- package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +7 -1
- package/dist/prices/providers/CoinPaprikaPriceProvider.js +7 -1
- package/dist/prices/providers/CustomPriceProvider.d.ts +12 -1
- package/dist/prices/providers/CustomPriceProvider.js +12 -1
- package/dist/prices/providers/KrakenPriceProvider.d.ts +10 -1
- package/dist/prices/providers/KrakenPriceProvider.js +10 -1
- package/dist/prices/providers/OKXPriceProvider.d.ts +7 -1
- package/dist/prices/providers/OKXPriceProvider.js +7 -1
- package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +3 -0
- package/dist/prices/providers/abstract/ExchangePriceProvider.js +3 -0
- package/dist/storage/IUnifiedStorage.d.ts +19 -7
- package/dist/storage/UnifiedSwapStorage.d.ts +33 -3
- package/dist/storage/UnifiedSwapStorage.js +29 -1
- package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +31 -7
- package/dist/storage-browser/IndexedDBUnifiedStorage.js +29 -6
- package/dist/storage-browser/LocalStorageManager.d.ts +25 -1
- package/dist/storage-browser/LocalStorageManager.js +25 -1
- package/dist/swapper/Swapper.d.ts +380 -226
- package/dist/swapper/Swapper.js +383 -349
- package/dist/swapper/SwapperFactory.d.ts +66 -18
- package/dist/swapper/SwapperFactory.js +24 -3
- package/dist/swapper/SwapperUtils.d.ts +75 -28
- package/dist/swapper/SwapperUtils.js +107 -60
- package/dist/swapper/SwapperWithChain.d.ts +286 -91
- package/dist/swapper/SwapperWithChain.js +218 -64
- package/dist/swapper/SwapperWithSigner.d.ts +229 -80
- package/dist/swapper/SwapperWithSigner.js +190 -44
- package/dist/swaps/IAddressSwap.d.ts +12 -3
- package/dist/swaps/IAddressSwap.js +3 -2
- package/dist/swaps/IBTCWalletSwap.d.ts +26 -8
- package/dist/swaps/IBTCWalletSwap.js +3 -2
- package/dist/swaps/IClaimableSwap.d.ts +38 -6
- package/dist/swaps/IClaimableSwap.js +3 -2
- package/dist/swaps/IClaimableSwapWrapper.d.ts +11 -1
- package/dist/swaps/IRefundableSwap.d.ts +31 -5
- package/dist/swaps/IRefundableSwap.js +3 -2
- package/dist/swaps/ISwap.d.ts +162 -24
- package/dist/swaps/ISwap.js +92 -35
- package/dist/swaps/ISwapWithGasDrop.d.ts +8 -2
- package/dist/swaps/ISwapWithGasDrop.js +2 -1
- package/dist/swaps/ISwapWrapper.d.ts +161 -52
- package/dist/swaps/ISwapWrapper.js +131 -73
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +51 -6
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +22 -12
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +65 -12
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +38 -19
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +39 -9
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +30 -21
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +31 -15
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +33 -18
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +97 -28
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +91 -27
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +22 -9
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +24 -11
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +278 -60
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +519 -241
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +77 -26
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +132 -50
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +313 -52
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +544 -194
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +87 -26
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +147 -58
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +222 -55
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +462 -244
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +77 -23
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +116 -46
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +195 -58
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +324 -191
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +30 -5
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +44 -19
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +61 -20
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +75 -32
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +76 -50
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +106 -101
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +37 -14
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +66 -20
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +46 -17
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +82 -27
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +350 -88
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +482 -215
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +76 -24
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +247 -124
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +148 -20
- package/dist/swaps/trusted/ln/LnForGasSwap.js +175 -45
- package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +29 -10
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +30 -11
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +202 -49
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +232 -80
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +34 -12
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +33 -14
- package/dist/types/AmountData.d.ts +2 -1
- package/dist/types/CustomPriceFunction.d.ts +8 -2
- package/dist/types/PriceInfoType.d.ts +4 -4
- package/dist/types/PriceInfoType.js +3 -3
- package/dist/types/SwapExecutionAction.d.ts +85 -4
- package/dist/types/SwapWithSigner.d.ts +5 -2
- package/dist/types/SwapWithSigner.js +5 -2
- package/dist/types/Token.d.ts +11 -5
- package/dist/types/Token.js +6 -3
- package/dist/types/TokenAmount.d.ts +3 -0
- package/dist/types/TokenAmount.js +2 -0
- package/dist/types/fees/Fee.d.ts +3 -2
- package/dist/types/fees/FeeBreakdown.d.ts +3 -2
- package/dist/types/fees/PercentagePPM.d.ts +4 -2
- package/dist/types/fees/PercentagePPM.js +2 -1
- package/dist/types/lnurl/LNURLPay.d.ts +20 -12
- package/dist/types/lnurl/LNURLPay.js +8 -4
- package/dist/types/lnurl/LNURLWithdraw.d.ts +17 -10
- package/dist/types/lnurl/LNURLWithdraw.js +8 -4
- package/dist/types/wallets/LightningInvoiceCreateService.d.ts +24 -0
- package/dist/types/wallets/LightningInvoiceCreateService.js +15 -0
- package/dist/types/wallets/MinimalBitcoinWalletInterface.d.ts +3 -1
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.d.ts +4 -2
- package/dist/utils/BitcoinUtils.d.ts +1 -0
- package/dist/utils/BitcoinUtils.js +5 -1
- package/dist/utils/SwapUtils.d.ts +58 -1
- package/dist/utils/SwapUtils.js +55 -1
- package/dist/utils/TokenUtils.d.ts +10 -2
- package/dist/utils/TokenUtils.js +12 -4
- package/package.json +3 -3
- package/src/bitcoin/coinselect2/utils.ts +6 -0
- package/src/bitcoin/wallet/BitcoinWallet.ts +41 -5
- package/src/bitcoin/wallet/IBitcoinWallet.ts +57 -2
- package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +42 -6
- package/src/enums/FeeType.ts +8 -1
- package/src/enums/SwapAmountType.ts +7 -0
- package/src/enums/SwapDirection.ts +7 -0
- package/src/enums/SwapType.ts +62 -2
- package/src/errors/IntermediaryError.ts +4 -0
- package/src/errors/RequestError.ts +15 -1
- package/src/errors/UserError.ts +1 -0
- package/src/index.ts +12 -5
- package/src/intermediaries/Intermediary.ts +61 -14
- package/src/intermediaries/IntermediaryDiscovery.ts +69 -34
- package/src/prices/RedundantSwapPrice.ts +26 -6
- package/src/prices/SingleSwapPrice.ts +11 -8
- package/src/prices/SwapPriceWithChain.ts +63 -26
- package/src/prices/abstract/IPriceProvider.ts +4 -4
- package/src/prices/abstract/ISwapPrice.ts +115 -66
- package/src/prices/providers/BinancePriceProvider.ts +8 -1
- package/src/prices/providers/CoinGeckoPriceProvider.ts +7 -1
- package/src/prices/providers/CoinPaprikaPriceProvider.ts +7 -1
- package/src/prices/providers/CustomPriceProvider.ts +12 -1
- package/src/prices/providers/KrakenPriceProvider.ts +10 -1
- package/src/prices/providers/OKXPriceProvider.ts +7 -1
- package/src/prices/providers/abstract/ExchangePriceProvider.ts +3 -0
- package/src/storage/IUnifiedStorage.ts +19 -7
- package/src/storage/UnifiedSwapStorage.ts +33 -3
- package/src/storage-browser/IndexedDBUnifiedStorage.ts +31 -8
- package/src/storage-browser/LocalStorageManager.ts +25 -1
- package/src/swapper/Swapper.ts +599 -390
- package/src/swapper/SwapperFactory.ts +73 -24
- package/src/swapper/SwapperUtils.ts +107 -60
- package/src/swapper/SwapperWithChain.ts +320 -81
- package/src/swapper/SwapperWithSigner.ts +263 -56
- package/src/swaps/IAddressSwap.ts +13 -3
- package/src/swaps/IBTCWalletSwap.ts +26 -10
- package/src/swaps/IClaimableSwap.ts +41 -6
- package/src/swaps/IClaimableSwapWrapper.ts +11 -2
- package/src/swaps/IRefundableSwap.ts +34 -5
- package/src/swaps/ISwap.ts +224 -85
- package/src/swaps/ISwapWithGasDrop.ts +8 -2
- package/src/swaps/ISwapWrapper.ts +216 -98
- package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +64 -18
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +83 -37
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +61 -30
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +37 -19
- package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +123 -50
- package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +24 -11
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +562 -258
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +156 -62
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +592 -227
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +177 -74
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +483 -245
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +141 -59
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +350 -195
- package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +48 -23
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +87 -40
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +110 -110
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +89 -34
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +101 -31
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +556 -259
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +292 -148
- package/src/swaps/trusted/ln/LnForGasSwap.ts +186 -47
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +34 -15
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +262 -88
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +41 -19
- package/src/types/AmountData.ts +2 -1
- package/src/types/CustomPriceFunction.ts +8 -2
- package/src/types/PriceInfoType.ts +4 -4
- package/src/types/SwapExecutionAction.ts +97 -5
- package/src/types/SwapWithSigner.ts +8 -4
- package/src/types/Token.ts +12 -5
- package/src/types/TokenAmount.ts +3 -0
- package/src/types/fees/Fee.ts +3 -2
- package/src/types/fees/FeeBreakdown.ts +3 -2
- package/src/types/fees/PercentagePPM.ts +4 -2
- package/src/types/lnurl/LNURLPay.ts +20 -12
- package/src/types/lnurl/LNURLWithdraw.ts +17 -10
- package/src/types/wallets/LightningInvoiceCreateService.ts +30 -0
- package/src/types/wallets/MinimalBitcoinWalletInterface.ts +3 -1
- package/src/types/wallets/MinimalLightningNetworkWalletInterface.ts +4 -2
- package/src/utils/BitcoinUtils.ts +5 -0
- package/src/utils/SwapUtils.ts +63 -1
- package/src/utils/TokenUtils.ts +12 -4
- package/dist/bitcoin/BitcoinRpcWithAddressIndex.d.ts +0 -68
- package/dist/bitcoin/BitcoinRpcWithAddressIndex.js +0 -2
- package/dist/bitcoin/LightningNetworkApi.d.ts +0 -12
- package/dist/bitcoin/LightningNetworkApi.js +0 -2
- package/dist/bitcoin/mempool/MempoolApi.d.ts +0 -350
- package/dist/bitcoin/mempool/MempoolApi.js +0 -311
- package/dist/bitcoin/mempool/MempoolBitcoinBlock.d.ts +0 -44
- package/dist/bitcoin/mempool/MempoolBitcoinBlock.js +0 -48
- package/dist/bitcoin/mempool/MempoolBitcoinRpc.d.ts +0 -119
- package/dist/bitcoin/mempool/MempoolBitcoinRpc.js +0 -361
- package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.d.ts +0 -22
- package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.js +0 -105
- package/dist/errors/PaymentAuthError.d.ts +0 -11
- package/dist/errors/PaymentAuthError.js +0 -23
- package/src/errors/PaymentAuthError.ts +0 -26
|
@@ -16,38 +16,81 @@ const Token_1 = require("../../../../types/Token");
|
|
|
16
16
|
const Logger_1 = require("../../../../utils/Logger");
|
|
17
17
|
const BitcoinWalletUtils_1 = require("../../../../utils/BitcoinWalletUtils");
|
|
18
18
|
/**
|
|
19
|
-
* State enum for
|
|
20
|
-
*
|
|
19
|
+
* State enum for legacy escrow based Bitcoin -> Smart chain swaps.
|
|
20
|
+
*
|
|
21
|
+
* @category Swaps/Legacy/Bitcoin → Smart chain
|
|
21
22
|
*/
|
|
22
23
|
var FromBTCSwapState;
|
|
23
24
|
(function (FromBTCSwapState) {
|
|
25
|
+
/**
|
|
26
|
+
* Bitcoin swap address has expired and the intermediary (LP) has already refunded
|
|
27
|
+
* its funds. No BTC should be sent anymore!
|
|
28
|
+
*/
|
|
24
29
|
FromBTCSwapState[FromBTCSwapState["FAILED"] = -4] = "FAILED";
|
|
30
|
+
/**
|
|
31
|
+
* Bitcoin swap address has expired, user should not send any BTC anymore! Though
|
|
32
|
+
* the intermediary (LP) hasn't refunded yet. So if there is a transaction already
|
|
33
|
+
* in-flight the swap might still succeed.
|
|
34
|
+
*/
|
|
25
35
|
FromBTCSwapState[FromBTCSwapState["EXPIRED"] = -3] = "EXPIRED";
|
|
36
|
+
/**
|
|
37
|
+
* Swap has expired for good and there is no way how it can be executed anymore
|
|
38
|
+
*/
|
|
26
39
|
FromBTCSwapState[FromBTCSwapState["QUOTE_EXPIRED"] = -2] = "QUOTE_EXPIRED";
|
|
40
|
+
/**
|
|
41
|
+
* A swap is almost expired, and it should be presented to the user as expired, though
|
|
42
|
+
* there is still a chance that it will be processed
|
|
43
|
+
*/
|
|
27
44
|
FromBTCSwapState[FromBTCSwapState["QUOTE_SOFT_EXPIRED"] = -1] = "QUOTE_SOFT_EXPIRED";
|
|
45
|
+
/**
|
|
46
|
+
* Swap quote was created, use the {@link FromBTCSwap.commit} or {@link FromBTCSwap.txsCommit} functions
|
|
47
|
+
* to initiate it by creating the swap escrow on the destination smart chain
|
|
48
|
+
*/
|
|
28
49
|
FromBTCSwapState[FromBTCSwapState["PR_CREATED"] = 0] = "PR_CREATED";
|
|
50
|
+
/**
|
|
51
|
+
* Swap escrow was initiated (committed) on the destination chain, user can send the BTC to the
|
|
52
|
+
* swap address with the {@link FromBTCSwap.getFundedPsbt}, {@link FromBTCSwap.getAddress} or
|
|
53
|
+
* {@link FromBTCSwap.getHyperlink} functions.
|
|
54
|
+
*/
|
|
29
55
|
FromBTCSwapState[FromBTCSwapState["CLAIM_COMMITED"] = 1] = "CLAIM_COMMITED";
|
|
56
|
+
/**
|
|
57
|
+
* Input bitcoin transaction was confirmed, wait for automatic settlement by the watchtower
|
|
58
|
+
* or settle manually using the {@link FromBTCSwap.claim} or {@link FromBTCSwap.txsClaim}
|
|
59
|
+
* function.
|
|
60
|
+
*/
|
|
30
61
|
FromBTCSwapState[FromBTCSwapState["BTC_TX_CONFIRMED"] = 2] = "BTC_TX_CONFIRMED";
|
|
62
|
+
/**
|
|
63
|
+
* Swap successfully settled and funds received on the destination chain
|
|
64
|
+
*/
|
|
31
65
|
FromBTCSwapState[FromBTCSwapState["CLAIM_CLAIMED"] = 3] = "CLAIM_CLAIMED";
|
|
32
66
|
})(FromBTCSwapState = exports.FromBTCSwapState || (exports.FromBTCSwapState = {}));
|
|
33
67
|
function isFromBTCSwapInit(obj) {
|
|
34
|
-
return typeof (obj.
|
|
35
|
-
typeof (obj.
|
|
36
|
-
typeof (obj.
|
|
37
|
-
typeof (obj.requiredConfirmations) === "number" &&
|
|
68
|
+
return typeof (obj.data) === "object" &&
|
|
69
|
+
(obj.address == null || typeof (obj.address) === "string") &&
|
|
70
|
+
(obj.amount == null || typeof (obj.amount) === "bigint") &&
|
|
71
|
+
(obj.requiredConfirmations == null || typeof (obj.requiredConfirmations) === "number") &&
|
|
38
72
|
(0, IEscrowSelfInitSwap_1.isIEscrowSelfInitSwapInit)(obj);
|
|
39
73
|
}
|
|
40
74
|
exports.isFromBTCSwapInit = isFromBTCSwapInit;
|
|
75
|
+
/**
|
|
76
|
+
* Legacy escrow (PrTLC) based swap for Bitcoin -> Smart chains, requires manual initiation
|
|
77
|
+
* of the swap escrow on the destination chain.
|
|
78
|
+
*
|
|
79
|
+
* @category Swaps/Legacy/Bitcoin → Smart chain
|
|
80
|
+
*/
|
|
41
81
|
class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
42
82
|
constructor(wrapper, initOrObject) {
|
|
43
83
|
if (isFromBTCSwapInit(initOrObject) && initOrObject.url != null)
|
|
44
84
|
initOrObject.url += "/frombtc";
|
|
45
85
|
super(wrapper, initOrObject);
|
|
46
|
-
this.inputToken = Token_1.BitcoinTokens.BTC;
|
|
47
86
|
this.TYPE = SwapType_1.SwapType.FROM_BTC;
|
|
87
|
+
/**
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
this.inputToken = Token_1.BitcoinTokens.BTC;
|
|
48
91
|
if (isFromBTCSwapInit(initOrObject)) {
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
92
|
+
this._state = FromBTCSwapState.PR_CREATED;
|
|
93
|
+
this._data = initOrObject.data;
|
|
51
94
|
this.feeRate = initOrObject.feeRate;
|
|
52
95
|
this.address = initOrObject.address;
|
|
53
96
|
this.amount = initOrObject.amount;
|
|
@@ -55,38 +98,46 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
55
98
|
}
|
|
56
99
|
else {
|
|
57
100
|
this.address = initOrObject.address;
|
|
58
|
-
this.amount =
|
|
101
|
+
this.amount = (0, Utils_1.toBigInt)(initOrObject.amount);
|
|
59
102
|
this.senderAddress = initOrObject.senderAddress;
|
|
60
103
|
this.txId = initOrObject.txId;
|
|
61
104
|
this.vout = initOrObject.vout;
|
|
62
|
-
this.requiredConfirmations = initOrObject.requiredConfirmations ?? this.
|
|
105
|
+
this.requiredConfirmations = initOrObject.requiredConfirmations ?? this._data.getConfirmationsHint();
|
|
63
106
|
}
|
|
64
107
|
this.tryRecomputeSwapPrice();
|
|
65
108
|
this.logger = (0, Logger_1.getLogger)("FromBTC(" + this.getIdentifierHashString() + "): ");
|
|
66
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* @inheritDoc
|
|
112
|
+
* @internal
|
|
113
|
+
*/
|
|
67
114
|
getSwapData() {
|
|
68
|
-
return this.
|
|
115
|
+
return this._data;
|
|
69
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* @inheritDoc
|
|
119
|
+
* @internal
|
|
120
|
+
*/
|
|
70
121
|
upgradeVersion() {
|
|
71
122
|
if (this.version == null) {
|
|
72
|
-
switch (this.
|
|
123
|
+
switch (this._state) {
|
|
73
124
|
case -2:
|
|
74
|
-
this.
|
|
125
|
+
this._state = FromBTCSwapState.FAILED;
|
|
75
126
|
break;
|
|
76
127
|
case -1:
|
|
77
|
-
this.
|
|
128
|
+
this._state = FromBTCSwapState.QUOTE_EXPIRED;
|
|
78
129
|
break;
|
|
79
130
|
case 0:
|
|
80
|
-
this.
|
|
131
|
+
this._state = FromBTCSwapState.PR_CREATED;
|
|
81
132
|
break;
|
|
82
133
|
case 1:
|
|
83
|
-
this.
|
|
134
|
+
this._state = FromBTCSwapState.CLAIM_COMMITED;
|
|
84
135
|
break;
|
|
85
136
|
case 2:
|
|
86
|
-
this.
|
|
137
|
+
this._state = FromBTCSwapState.BTC_TX_CONFIRMED;
|
|
87
138
|
break;
|
|
88
139
|
case 3:
|
|
89
|
-
this.
|
|
140
|
+
this._state = FromBTCSwapState.CLAIM_CLAIMED;
|
|
90
141
|
break;
|
|
91
142
|
}
|
|
92
143
|
this.version = 1;
|
|
@@ -98,9 +149,9 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
98
149
|
* Returns bitcoin address where the on-chain BTC should be sent to
|
|
99
150
|
*/
|
|
100
151
|
getAddress() {
|
|
101
|
-
if (this.
|
|
102
|
-
throw new Error("Cannot get bitcoin address of non-
|
|
103
|
-
return this.address;
|
|
152
|
+
if (this._state === FromBTCSwapState.PR_CREATED)
|
|
153
|
+
throw new Error("Cannot get bitcoin address of non-initiated swaps! Initiate swap first with commit() or txsCommit().");
|
|
154
|
+
return this.address ?? "";
|
|
104
155
|
}
|
|
105
156
|
/**
|
|
106
157
|
* Unsafe bitcoin hyperlink getter, returns the address even before the swap is committed!
|
|
@@ -108,16 +159,25 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
108
159
|
* @private
|
|
109
160
|
*/
|
|
110
161
|
_getHyperlink() {
|
|
111
|
-
return "bitcoin:" + this.address + "?amount=" + encodeURIComponent((Number(this.amount) / 100000000).toString(10));
|
|
162
|
+
return this.address == null || this.amount == null ? "" : "bitcoin:" + this.address + "?amount=" + encodeURIComponent((Number(this.amount) / 100000000).toString(10));
|
|
112
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* @inheritDoc
|
|
166
|
+
*/
|
|
113
167
|
getHyperlink() {
|
|
114
|
-
if (this.
|
|
115
|
-
throw new Error("Cannot get bitcoin address of non-
|
|
168
|
+
if (this._state === FromBTCSwapState.PR_CREATED)
|
|
169
|
+
throw new Error("Cannot get bitcoin address of non-initiated swaps! Initiate swap first with commit() or txsCommit().");
|
|
116
170
|
return this._getHyperlink();
|
|
117
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* @inheritDoc
|
|
174
|
+
*/
|
|
118
175
|
getInputAddress() {
|
|
119
176
|
return this.senderAddress ?? null;
|
|
120
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* @inheritDoc
|
|
180
|
+
*/
|
|
121
181
|
getInputTxId() {
|
|
122
182
|
return this.txId ?? null;
|
|
123
183
|
}
|
|
@@ -126,84 +186,149 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
126
186
|
* to that address anymore
|
|
127
187
|
*/
|
|
128
188
|
getTimeoutTime() {
|
|
129
|
-
return Number(this.wrapper.
|
|
189
|
+
return Number(this.wrapper._getOnchainSendTimeout(this._data, this.requiredConfirmations ?? 6)) * 1000;
|
|
130
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* @inheritDoc
|
|
193
|
+
*/
|
|
131
194
|
requiresAction() {
|
|
132
|
-
return this.isClaimable() || (this.
|
|
195
|
+
return this.isClaimable() || (this._state === FromBTCSwapState.CLAIM_COMMITED && this.getTimeoutTime() > Date.now() && this.txId == null);
|
|
133
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* @inheritDoc
|
|
199
|
+
*/
|
|
134
200
|
isFinished() {
|
|
135
|
-
return this.
|
|
201
|
+
return this._state === FromBTCSwapState.CLAIM_CLAIMED || this._state === FromBTCSwapState.QUOTE_EXPIRED || this._state === FromBTCSwapState.FAILED;
|
|
136
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* @inheritDoc
|
|
205
|
+
*/
|
|
137
206
|
isClaimable() {
|
|
138
|
-
return this.
|
|
207
|
+
return this._state === FromBTCSwapState.BTC_TX_CONFIRMED;
|
|
139
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* @inheritDoc
|
|
211
|
+
*/
|
|
140
212
|
isSuccessful() {
|
|
141
|
-
return this.
|
|
213
|
+
return this._state === FromBTCSwapState.CLAIM_CLAIMED;
|
|
142
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* @inheritDoc
|
|
217
|
+
*/
|
|
143
218
|
isFailed() {
|
|
144
|
-
return this.
|
|
219
|
+
return this._state === FromBTCSwapState.FAILED || this._state === FromBTCSwapState.EXPIRED;
|
|
145
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* @inheritDoc
|
|
223
|
+
*/
|
|
146
224
|
isQuoteExpired() {
|
|
147
|
-
return this.
|
|
225
|
+
return this._state === FromBTCSwapState.QUOTE_EXPIRED;
|
|
148
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* @inheritDoc
|
|
229
|
+
*/
|
|
149
230
|
isQuoteSoftExpired() {
|
|
150
|
-
return this.
|
|
231
|
+
return this._state === FromBTCSwapState.QUOTE_EXPIRED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED;
|
|
151
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* @inheritDoc
|
|
235
|
+
* @internal
|
|
236
|
+
*/
|
|
152
237
|
canCommit() {
|
|
153
|
-
if (this.
|
|
238
|
+
if (this._state !== FromBTCSwapState.PR_CREATED)
|
|
239
|
+
return false;
|
|
240
|
+
if (this.requiredConfirmations == null)
|
|
154
241
|
return false;
|
|
155
|
-
const expiry = this.wrapper.
|
|
242
|
+
const expiry = this.wrapper._getOnchainSendTimeout(this._data, this.requiredConfirmations);
|
|
156
243
|
const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
|
|
157
|
-
return (expiry - currentTimestamp) >= this.wrapper.
|
|
244
|
+
return (expiry - currentTimestamp) >= this.wrapper._options.minSendWindow;
|
|
158
245
|
}
|
|
159
246
|
//////////////////////////////
|
|
160
247
|
//// Amounts & fees
|
|
248
|
+
/**
|
|
249
|
+
* @inheritDoc
|
|
250
|
+
*/
|
|
161
251
|
getInputToken() {
|
|
162
252
|
return Token_1.BitcoinTokens.BTC;
|
|
163
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* @inheritDoc
|
|
256
|
+
*/
|
|
164
257
|
getInput() {
|
|
165
|
-
return (0, TokenAmount_1.toTokenAmount)(this.amount, this.inputToken, this.wrapper.
|
|
258
|
+
return (0, TokenAmount_1.toTokenAmount)(this.amount ?? null, this.inputToken, this.wrapper._prices);
|
|
166
259
|
}
|
|
167
260
|
/**
|
|
168
|
-
* Returns claimer bounty, acting as a reward for watchtowers to claim the swap automatically
|
|
261
|
+
* Returns claimer bounty, acting as a reward for watchtowers to claim the swap automatically,
|
|
262
|
+
* this amount is pre-funded by the user on the destination chain when the swap escrow
|
|
263
|
+
* is initiated. For total pre-funded deposit amount see {@link getTotalDeposit}.
|
|
169
264
|
*/
|
|
170
265
|
getClaimerBounty() {
|
|
171
|
-
return (0, TokenAmount_1.toTokenAmount)(this.
|
|
266
|
+
return (0, TokenAmount_1.toTokenAmount)(this._data.getClaimerBounty(), this.wrapper._tokens[this._data.getDepositToken()], this.wrapper._prices);
|
|
172
267
|
}
|
|
173
268
|
//////////////////////////////
|
|
174
269
|
//// Bitcoin tx
|
|
270
|
+
/**
|
|
271
|
+
* If the required number of confirmations is not known, this function tries to infer it by looping through
|
|
272
|
+
* possible confirmation targets and comparing the claim hashes
|
|
273
|
+
*
|
|
274
|
+
* @param btcTx Bitcoin transaction
|
|
275
|
+
* @param vout Output index of the desired output in the bitcoin transaction
|
|
276
|
+
*
|
|
277
|
+
* @private
|
|
278
|
+
*/
|
|
279
|
+
inferRequiredConfirmationsCount(btcTx, vout) {
|
|
280
|
+
const txOut = btcTx.outs[vout];
|
|
281
|
+
for (let i = 1; i <= 20; i++) {
|
|
282
|
+
const computedClaimHash = this.wrapper._contract.getHashForOnchain(buffer_1.Buffer.from(txOut.scriptPubKey.hex, "hex"), BigInt(txOut.value), i);
|
|
283
|
+
if (computedClaimHash.toString("hex") === this._data.getClaimHash()) {
|
|
284
|
+
return i;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* @inheritDoc
|
|
290
|
+
*/
|
|
175
291
|
getRequiredConfirmationsCount() {
|
|
176
|
-
return this.requiredConfirmations;
|
|
292
|
+
return this.requiredConfirmations ?? NaN;
|
|
177
293
|
}
|
|
178
294
|
/**
|
|
179
|
-
* Checks whether a bitcoin payment was already made, returns the payment or null when no payment has been made.
|
|
295
|
+
* Checks whether a bitcoin payment was already made, returns the payment or `null` when no payment has been made.
|
|
296
|
+
*
|
|
297
|
+
* @internal
|
|
180
298
|
*/
|
|
181
299
|
async getBitcoinPayment() {
|
|
182
|
-
const txoHashHint = this.
|
|
300
|
+
const txoHashHint = this._data.getTxoHashHint();
|
|
183
301
|
if (txoHashHint == null)
|
|
184
|
-
throw new Error("Swap data
|
|
185
|
-
|
|
302
|
+
throw new Error("Swap data doesn't include the txo hash hint! Cannot check bitcoin transaction!");
|
|
303
|
+
if (this.address == null)
|
|
304
|
+
throw new Error("Cannot check bitcoin payment, because the address is not known! This can happen after a swap is recovered.");
|
|
305
|
+
const result = await this.wrapper._btcRpc.checkAddressTxos(this.address, buffer_1.Buffer.from(txoHashHint, "hex"));
|
|
186
306
|
if (result == null)
|
|
187
307
|
return null;
|
|
308
|
+
if (this.requiredConfirmations == null) {
|
|
309
|
+
this.requiredConfirmations = this.inferRequiredConfirmationsCount(result.tx, result.vout);
|
|
310
|
+
}
|
|
188
311
|
return {
|
|
189
312
|
inputAddresses: result.tx.inputAddresses,
|
|
190
313
|
txId: result.tx.txid,
|
|
191
314
|
vout: result.vout,
|
|
192
315
|
confirmations: result.tx.confirmations ?? 0,
|
|
193
|
-
targetConfirmations: this.
|
|
316
|
+
targetConfirmations: this.getRequiredConfirmationsCount()
|
|
194
317
|
};
|
|
195
318
|
}
|
|
196
319
|
/**
|
|
197
|
-
*
|
|
320
|
+
* Used to set the txId of the bitcoin payment from the on-chain events listener
|
|
198
321
|
*
|
|
199
|
-
* @param txId
|
|
322
|
+
* @param txId Transaction ID that settled the swap on the smart chain
|
|
323
|
+
*
|
|
324
|
+
* @internal
|
|
200
325
|
*/
|
|
201
326
|
async _setBitcoinTxId(txId) {
|
|
202
327
|
if (this.txId !== txId || this.address == null || this.vout == null || this.senderAddress == null || this.amount == null) {
|
|
203
|
-
const btcTx = await this.wrapper.
|
|
328
|
+
const btcTx = await this.wrapper._btcRpc.getTransaction(txId);
|
|
204
329
|
if (btcTx == null)
|
|
205
330
|
return;
|
|
206
|
-
const txoHashHint = this.
|
|
331
|
+
const txoHashHint = this._data.getTxoHashHint();
|
|
207
332
|
if (txoHashHint != null) {
|
|
208
333
|
const expectedTxoHash = buffer_1.Buffer.from(txoHashHint, "hex");
|
|
209
334
|
const vout = btcTx.outs.findIndex(out => (0, Utils_1.getTxoHash)(out.scriptPubKey.hex, out.value).equals(expectedTxoHash));
|
|
@@ -216,12 +341,14 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
216
341
|
this.amount = BigInt(btcTx.outs[vout].value);
|
|
217
342
|
if (this.address == null)
|
|
218
343
|
try {
|
|
219
|
-
|
|
220
|
-
this.address = (0, btc_signer_1.Address)(this.wrapper.options.bitcoinNetwork).encode(addressData);
|
|
344
|
+
this.address = (0, BitcoinUtils_1.fromOutputScript)(this.wrapper._options.bitcoinNetwork, btcTx.outs[vout].scriptPubKey.hex);
|
|
221
345
|
}
|
|
222
346
|
catch (e) {
|
|
223
347
|
this.logger.warn("_setBitcoinTxId(): Failed to parse address from output script: ", e);
|
|
224
348
|
}
|
|
349
|
+
if (this.requiredConfirmations == null) {
|
|
350
|
+
this.requiredConfirmations = this.inferRequiredConfirmationsCount(btcTx, vout);
|
|
351
|
+
}
|
|
225
352
|
}
|
|
226
353
|
}
|
|
227
354
|
if (btcTx.inputAddresses != null) {
|
|
@@ -231,66 +358,86 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
231
358
|
this.txId = txId;
|
|
232
359
|
}
|
|
233
360
|
/**
|
|
234
|
-
*
|
|
361
|
+
* @inheritDoc
|
|
235
362
|
*
|
|
236
|
-
* @
|
|
237
|
-
* @param checkIntervalSeconds How often to check the bitcoin transaction
|
|
238
|
-
* @param abortSignal Abort signal
|
|
239
|
-
* @throws {Error} if in invalid state (must be CLAIM_COMMITED)
|
|
363
|
+
* @throws {Error} if in invalid state (must be {@link FromBTCSwapState.CLAIM_COMMITED})
|
|
240
364
|
*/
|
|
241
365
|
async waitForBitcoinTransaction(updateCallback, checkIntervalSeconds, abortSignal) {
|
|
242
|
-
if (this.
|
|
366
|
+
if (this._state !== FromBTCSwapState.CLAIM_COMMITED && this._state !== FromBTCSwapState.EXPIRED)
|
|
243
367
|
throw new Error("Must be in COMMITED state!");
|
|
244
|
-
const txoHashHint = this.
|
|
368
|
+
const txoHashHint = this._data.getTxoHashHint();
|
|
245
369
|
if (txoHashHint == null)
|
|
246
|
-
throw new Error("Swap data
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
370
|
+
throw new Error("Swap data doesn't include the txo hash hint! Cannot check bitcoin transaction!");
|
|
371
|
+
if (this.address == null)
|
|
372
|
+
throw new Error("Cannot check bitcoin payment, because the address is not known! This can happen after a swap is recovered.");
|
|
373
|
+
let abortedDueToEnoughConfirmationsResult;
|
|
374
|
+
const abortController = (0, Utils_1.extendAbortController)(abortSignal);
|
|
375
|
+
const result = await this.wrapper._btcRpc.waitForAddressTxo(this.address, buffer_1.Buffer.from(txoHashHint, "hex"), this.requiredConfirmations ?? 6, //In case confirmation count is not known, we use a conservative estimate
|
|
376
|
+
(btcTx, vout, txEtaMs) => {
|
|
377
|
+
let requiredConfirmations = this.requiredConfirmations;
|
|
378
|
+
if (btcTx != null && vout != null && requiredConfirmations == null) {
|
|
379
|
+
requiredConfirmations = this.inferRequiredConfirmationsCount(btcTx, vout);
|
|
380
|
+
}
|
|
381
|
+
if (btcTx != null && (btcTx.txid !== this.txId || (this.requiredConfirmations == null && requiredConfirmations != null))) {
|
|
251
382
|
this.txId = btcTx.txid;
|
|
252
383
|
this.vout = vout;
|
|
384
|
+
this.requiredConfirmations = requiredConfirmations;
|
|
253
385
|
if (btcTx.inputAddresses != null)
|
|
254
386
|
this.senderAddress = btcTx.inputAddresses[0];
|
|
255
387
|
this._saveAndEmit().catch(e => {
|
|
256
388
|
this.logger.error("waitForBitcoinTransaction(): Failed to save swap from within waitForAddressTxo callback:", e);
|
|
257
389
|
});
|
|
258
390
|
}
|
|
259
|
-
|
|
391
|
+
//Abort the loop as soon as the transaction gets enough confirmations, this is required in case
|
|
392
|
+
// we pass a default 6 confirmations to the fn, but then are able to infer the actual confirmation
|
|
393
|
+
// target from the prior block
|
|
394
|
+
if (btcTx?.confirmations != null && requiredConfirmations != null && requiredConfirmations <= btcTx.confirmations && vout != null) {
|
|
395
|
+
abortedDueToEnoughConfirmationsResult = {
|
|
396
|
+
tx: btcTx,
|
|
397
|
+
vout
|
|
398
|
+
};
|
|
399
|
+
abortController.abort();
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
if (updateCallback != null)
|
|
403
|
+
updateCallback(btcTx?.txid, btcTx == null ? undefined : (btcTx?.confirmations ?? 0), requiredConfirmations ?? NaN, txEtaMs);
|
|
404
|
+
}, abortController.signal, checkIntervalSeconds).catch(e => {
|
|
405
|
+
//We catch the case when the loop was aborted due to the transaction getting enough confirmations
|
|
406
|
+
if (abortedDueToEnoughConfirmationsResult != null)
|
|
407
|
+
return abortedDueToEnoughConfirmationsResult;
|
|
408
|
+
throw e;
|
|
409
|
+
});
|
|
260
410
|
if (abortSignal != null)
|
|
261
411
|
abortSignal.throwIfAborted();
|
|
262
412
|
this.txId = result.tx.txid;
|
|
263
413
|
this.vout = result.vout;
|
|
264
414
|
if (result.tx.inputAddresses != null)
|
|
265
415
|
this.senderAddress = result.tx.inputAddresses[0];
|
|
266
|
-
if (this.
|
|
267
|
-
this.
|
|
268
|
-
this.
|
|
416
|
+
if (this._state !== FromBTCSwapState.CLAIM_CLAIMED &&
|
|
417
|
+
this._state !== FromBTCSwapState.FAILED) {
|
|
418
|
+
this._state = FromBTCSwapState.BTC_TX_CONFIRMED;
|
|
269
419
|
}
|
|
270
420
|
await this._saveAndEmit();
|
|
271
421
|
return result.tx.txid;
|
|
272
422
|
}
|
|
273
423
|
/**
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
424
|
+
* Private getter of the funded PSBT that doesn't check current state
|
|
425
|
+
*
|
|
426
|
+
* @param _bitcoinWallet Bitcoin wallet to fund the PSBT with
|
|
427
|
+
* @param feeRate Optional bitcoin fee rate in sats/vB
|
|
428
|
+
* @param additionalOutputs Optional additional outputs that should also be included in the generated PSBT
|
|
277
429
|
*
|
|
278
|
-
* @
|
|
279
|
-
* @param feeRate Optional fee rate for the transaction, needs to be at least as big as {minimumBtcFeeRate} field
|
|
280
|
-
* @param additionalOutputs additional outputs to add to the PSBT - can be used to collect fees from users
|
|
430
|
+
* @private
|
|
281
431
|
*/
|
|
282
|
-
getFundedPsbt(_bitcoinWallet, feeRate, additionalOutputs) {
|
|
283
|
-
if (this.state !== FromBTCSwapState.CLAIM_COMMITED)
|
|
284
|
-
throw new Error("Swap not committed yet, please initiate the swap first with commit() call!");
|
|
285
|
-
return this._getFundedPsbt(_bitcoinWallet, feeRate, additionalOutputs);
|
|
286
|
-
}
|
|
287
432
|
async _getFundedPsbt(_bitcoinWallet, feeRate, additionalOutputs) {
|
|
433
|
+
if (this.address == null)
|
|
434
|
+
throw new Error("Cannot create funded PSBT, because the address is not known! This can happen after a swap is recovered.");
|
|
288
435
|
let bitcoinWallet;
|
|
289
436
|
if ((0, IBitcoinWallet_1.isIBitcoinWallet)(_bitcoinWallet)) {
|
|
290
437
|
bitcoinWallet = _bitcoinWallet;
|
|
291
438
|
}
|
|
292
439
|
else {
|
|
293
|
-
bitcoinWallet = new SingleAddressBitcoinWallet_1.SingleAddressBitcoinWallet(this.wrapper.
|
|
440
|
+
bitcoinWallet = new SingleAddressBitcoinWallet_1.SingleAddressBitcoinWallet(this.wrapper._btcRpc, this.wrapper._options.bitcoinNetwork, _bitcoinWallet);
|
|
294
441
|
}
|
|
295
442
|
//TODO: Maybe re-introduce fee rate check here if passed from the user
|
|
296
443
|
if (feeRate == null) {
|
|
@@ -302,13 +449,13 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
302
449
|
});
|
|
303
450
|
basePsbt.addOutput({
|
|
304
451
|
amount: this.amount,
|
|
305
|
-
script: (0, BitcoinUtils_1.toOutputScript)(this.wrapper.
|
|
452
|
+
script: (0, BitcoinUtils_1.toOutputScript)(this.wrapper._options.bitcoinNetwork, this.address)
|
|
306
453
|
});
|
|
307
454
|
if (additionalOutputs != null)
|
|
308
455
|
additionalOutputs.forEach(output => {
|
|
309
456
|
basePsbt.addOutput({
|
|
310
457
|
amount: output.amount,
|
|
311
|
-
script: output.outputScript ?? (0, BitcoinUtils_1.toOutputScript)(this.wrapper.
|
|
458
|
+
script: output.outputScript ?? (0, BitcoinUtils_1.toOutputScript)(this.wrapper._options.bitcoinNetwork, output.address)
|
|
312
459
|
});
|
|
313
460
|
});
|
|
314
461
|
const psbt = await bitcoinWallet.fundPsbt(basePsbt, feeRate);
|
|
@@ -326,37 +473,58 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
326
473
|
};
|
|
327
474
|
}
|
|
328
475
|
/**
|
|
329
|
-
*
|
|
476
|
+
* @inheritDoc
|
|
477
|
+
*/
|
|
478
|
+
getFundedPsbt(_bitcoinWallet, feeRate, additionalOutputs) {
|
|
479
|
+
if (this._state !== FromBTCSwapState.CLAIM_COMMITED)
|
|
480
|
+
throw new Error("Swap not committed yet, please initiate the swap first with commit() call!");
|
|
481
|
+
return this._getFundedPsbt(_bitcoinWallet, feeRate, additionalOutputs);
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* @inheritDoc
|
|
330
485
|
*
|
|
331
|
-
* @
|
|
486
|
+
* @throws {Error} if the swap is in invalid state (not in {@link FromBTCSwapState.CLAIM_COMMITED}), or if
|
|
487
|
+
* the swap bitcoin address already expired.
|
|
332
488
|
*/
|
|
333
489
|
async submitPsbt(_psbt) {
|
|
334
490
|
const psbt = (0, BitcoinUtils_1.parsePsbtTransaction)(_psbt);
|
|
335
|
-
if (this.
|
|
491
|
+
if (this._state !== FromBTCSwapState.CLAIM_COMMITED)
|
|
336
492
|
throw new Error("Swap not committed yet, please initiate the swap first with commit() call!");
|
|
337
493
|
//Ensure not expired
|
|
338
494
|
if (this.getTimeoutTime() < Date.now()) {
|
|
339
495
|
throw new Error("Swap address expired!");
|
|
340
496
|
}
|
|
341
497
|
const output0 = psbt.getOutput(0);
|
|
342
|
-
if (output0.amount !== this.amount)
|
|
498
|
+
if (this.amount != null && output0.amount !== this.amount)
|
|
343
499
|
throw new Error("PSBT output amount invalid, expected: " + this.amount + " got: " + output0.amount);
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
500
|
+
if (this.address != null) {
|
|
501
|
+
const expectedOutputScript = (0, BitcoinUtils_1.toOutputScript)(this.wrapper._options.bitcoinNetwork, this.address);
|
|
502
|
+
if (output0.script == null || !expectedOutputScript.equals(output0.script))
|
|
503
|
+
throw new Error("PSBT output script invalid!");
|
|
504
|
+
}
|
|
347
505
|
if (!psbt.isFinal)
|
|
348
506
|
psbt.finalize();
|
|
349
|
-
return await this.wrapper.
|
|
507
|
+
return await this.wrapper._btcRpc.sendRawTransaction(buffer_1.Buffer.from(psbt.toBytes(true, true)).toString("hex"));
|
|
350
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* @inheritDoc
|
|
511
|
+
*/
|
|
351
512
|
async estimateBitcoinFee(_bitcoinWallet, feeRate) {
|
|
352
|
-
|
|
513
|
+
if (this.address == null || this.amount == null)
|
|
514
|
+
return null;
|
|
515
|
+
const bitcoinWallet = (0, BitcoinWalletUtils_1.toBitcoinWallet)(_bitcoinWallet, this.wrapper._btcRpc, this.wrapper._options.bitcoinNetwork);
|
|
353
516
|
const txFee = await bitcoinWallet.getTransactionFee(this.address, this.amount, feeRate);
|
|
354
517
|
if (txFee == null)
|
|
355
518
|
return null;
|
|
356
|
-
return (0, TokenAmount_1.toTokenAmount)(BigInt(txFee), Token_1.BitcoinTokens.BTC, this.wrapper.
|
|
519
|
+
return (0, TokenAmount_1.toTokenAmount)(BigInt(txFee), Token_1.BitcoinTokens.BTC, this.wrapper._prices);
|
|
357
520
|
}
|
|
521
|
+
/**
|
|
522
|
+
* @inheritDoc
|
|
523
|
+
*/
|
|
358
524
|
async sendBitcoinTransaction(wallet, feeRate) {
|
|
359
|
-
if (this.
|
|
525
|
+
if (this.address == null || this.amount == null)
|
|
526
|
+
throw new Error("Cannot send bitcoin transaction, because the address is not known! This can happen after a swap is recovered.");
|
|
527
|
+
if (this._state !== FromBTCSwapState.CLAIM_COMMITED)
|
|
360
528
|
throw new Error("Swap not committed yet, please initiate the swap first with commit() call!");
|
|
361
529
|
//Ensure not expired
|
|
362
530
|
if (this.getTimeoutTime() < Date.now()) {
|
|
@@ -391,18 +559,18 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
391
559
|
* user, in case `false` is returned the user should call `swap.claim()` to settle the swap on the destination manually
|
|
392
560
|
*/
|
|
393
561
|
async execute(dstSigner, wallet, callbacks, options) {
|
|
394
|
-
if (this.
|
|
562
|
+
if (this._state === FromBTCSwapState.FAILED)
|
|
395
563
|
throw new Error("Swap failed!");
|
|
396
|
-
if (this.
|
|
564
|
+
if (this._state === FromBTCSwapState.EXPIRED)
|
|
397
565
|
throw new Error("Swap address expired!");
|
|
398
|
-
if (this.
|
|
566
|
+
if (this._state === FromBTCSwapState.QUOTE_EXPIRED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED)
|
|
399
567
|
throw new Error("Swap quote expired!");
|
|
400
|
-
if (this.
|
|
568
|
+
if (this._state === FromBTCSwapState.CLAIM_CLAIMED)
|
|
401
569
|
throw new Error("Swap already settled!");
|
|
402
|
-
if (this.
|
|
570
|
+
if (this._state === FromBTCSwapState.PR_CREATED) {
|
|
403
571
|
await this.commit(dstSigner, options?.abortSignal, undefined, callbacks?.onDestinationCommitSent);
|
|
404
572
|
}
|
|
405
|
-
if (this.
|
|
573
|
+
if (this._state === FromBTCSwapState.CLAIM_COMMITED) {
|
|
406
574
|
if (wallet != null) {
|
|
407
575
|
const bitcoinPaymentSent = await this.getBitcoinPayment();
|
|
408
576
|
if (bitcoinPaymentSent == null) {
|
|
@@ -417,9 +585,9 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
417
585
|
callbacks.onSourceTransactionConfirmed(txId);
|
|
418
586
|
}
|
|
419
587
|
// @ts-ignore
|
|
420
|
-
if (this.
|
|
588
|
+
if (this._state === FromBTCSwapState.CLAIM_CLAIMED)
|
|
421
589
|
return true;
|
|
422
|
-
if (this.
|
|
590
|
+
if (this._state === FromBTCSwapState.BTC_TX_CONFIRMED) {
|
|
423
591
|
const success = await this.waitTillClaimed(options?.maxWaitTillAutomaticSettlementSeconds ?? 60, options?.abortSignal);
|
|
424
592
|
if (success && callbacks?.onSwapSettled != null)
|
|
425
593
|
callbacks.onSwapSettled(this.getOutputTxId());
|
|
@@ -427,9 +595,20 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
427
595
|
}
|
|
428
596
|
throw new Error("Invalid state reached!");
|
|
429
597
|
}
|
|
598
|
+
/**
|
|
599
|
+
* @inheritDoc
|
|
600
|
+
*
|
|
601
|
+
* @param options.bitcoinWallet Bitcoin wallet to use, when provided the function returns a funded
|
|
602
|
+
* psbt (`"FUNDED_PSBT"`), if not passed just a bitcoin receive address is returned (`"ADDRESS"`)
|
|
603
|
+
* @param options.skipChecks Skip checks like making sure init signature is still valid and swap
|
|
604
|
+
* wasn't commited yet (this is handled on swap creation, if you commit right after quoting, you
|
|
605
|
+
* can use `skipChecks=true`)
|
|
606
|
+
*
|
|
607
|
+
* @throws {Error} if the swap or quote is expired, or if triggered in invalid state
|
|
608
|
+
*/
|
|
430
609
|
async txsExecute(options) {
|
|
431
|
-
if (this.
|
|
432
|
-
if (!await this.
|
|
610
|
+
if (this._state === FromBTCSwapState.PR_CREATED) {
|
|
611
|
+
if (!await this._verifyQuoteValid())
|
|
433
612
|
throw new Error("Quote already expired or close to expiry!");
|
|
434
613
|
if (this.getTimeoutTime() < Date.now())
|
|
435
614
|
throw new Error("Swap address already expired or close to expiry!");
|
|
@@ -446,7 +625,7 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
446
625
|
chain: "BITCOIN",
|
|
447
626
|
txs: [
|
|
448
627
|
options?.bitcoinWallet == null ? {
|
|
449
|
-
address: this.address,
|
|
628
|
+
address: this.address ?? "",
|
|
450
629
|
amount: Number(this.amount),
|
|
451
630
|
hyperlink: this._getHyperlink(),
|
|
452
631
|
type: "ADDRESS"
|
|
@@ -458,7 +637,7 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
458
637
|
}
|
|
459
638
|
];
|
|
460
639
|
}
|
|
461
|
-
if (this.
|
|
640
|
+
if (this._state === FromBTCSwapState.CLAIM_COMMITED) {
|
|
462
641
|
if (this.getTimeoutTime() < Date.now())
|
|
463
642
|
throw new Error("Swap address already expired or close to expiry!");
|
|
464
643
|
return [
|
|
@@ -468,7 +647,7 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
468
647
|
chain: "BITCOIN",
|
|
469
648
|
txs: [
|
|
470
649
|
options?.bitcoinWallet == null ? {
|
|
471
|
-
address: this.
|
|
650
|
+
address: this.getAddress(),
|
|
472
651
|
amount: Number(this.amount),
|
|
473
652
|
hyperlink: this._getHyperlink(),
|
|
474
653
|
type: "ADDRESS"
|
|
@@ -485,36 +664,34 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
485
664
|
//////////////////////////////
|
|
486
665
|
//// Commit
|
|
487
666
|
/**
|
|
488
|
-
*
|
|
667
|
+
* @inheritDoc
|
|
489
668
|
*
|
|
490
|
-
* @param _signer Signer to sign the transactions with, must be the same as used in the initialization
|
|
491
|
-
* @param abortSignal Abort signal to stop waiting for the transaction confirmation and abort
|
|
492
|
-
* @param skipChecks Skip checks like making sure init signature is still valid and swap wasn't commited yet
|
|
493
|
-
* (this is handled when swap is created (quoted), if you commit right after quoting, you can use skipChecks=true)
|
|
494
|
-
* @param onBeforeTxSent
|
|
495
669
|
* @throws {Error} If invalid signer is provided that doesn't match the swap data
|
|
496
670
|
*/
|
|
497
671
|
async commit(_signer, abortSignal, skipChecks, onBeforeTxSent) {
|
|
498
|
-
const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper.
|
|
672
|
+
const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper._chain.wrapSigner(_signer);
|
|
499
673
|
this.checkSigner(signer);
|
|
500
674
|
let txCount = 0;
|
|
501
675
|
const txs = await this.txsCommit(skipChecks);
|
|
502
|
-
const result = await this.wrapper.
|
|
676
|
+
const result = await this.wrapper._chain.sendAndConfirm(signer, txs, true, abortSignal, undefined, (txId) => {
|
|
503
677
|
txCount++;
|
|
504
678
|
if (onBeforeTxSent != null && txCount === txs.length)
|
|
505
679
|
onBeforeTxSent(txId);
|
|
506
680
|
return Promise.resolve();
|
|
507
681
|
});
|
|
508
|
-
this.
|
|
509
|
-
if (this.
|
|
682
|
+
this._commitTxId = result[result.length - 1];
|
|
683
|
+
if (this._state === FromBTCSwapState.PR_CREATED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
|
|
510
684
|
await this._saveAndEmit(FromBTCSwapState.CLAIM_COMMITED);
|
|
511
685
|
}
|
|
512
|
-
return this.
|
|
686
|
+
return this._commitTxId;
|
|
513
687
|
}
|
|
688
|
+
/**
|
|
689
|
+
* @inheritDoc
|
|
690
|
+
*/
|
|
514
691
|
async waitTillCommited(abortSignal) {
|
|
515
|
-
if (this.
|
|
692
|
+
if (this._state === FromBTCSwapState.CLAIM_COMMITED || this._state === FromBTCSwapState.CLAIM_CLAIMED)
|
|
516
693
|
return Promise.resolve();
|
|
517
|
-
if (this.
|
|
694
|
+
if (this._state !== FromBTCSwapState.PR_CREATED && this._state !== FromBTCSwapState.QUOTE_SOFT_EXPIRED)
|
|
518
695
|
throw new Error("Invalid state");
|
|
519
696
|
const abortController = (0, Utils_1.extendAbortController)(abortSignal);
|
|
520
697
|
const result = await Promise.race([
|
|
@@ -528,22 +705,28 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
528
705
|
this.logger.debug("waitTillCommited(): Resolved from watchdog - commited");
|
|
529
706
|
if (result === false) {
|
|
530
707
|
this.logger.debug("waitTillCommited(): Resolved from watchdog - signature expired");
|
|
531
|
-
if (this.
|
|
708
|
+
if (this._state === FromBTCSwapState.PR_CREATED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
|
|
532
709
|
await this._saveAndEmit(FromBTCSwapState.QUOTE_EXPIRED);
|
|
533
710
|
}
|
|
534
711
|
return;
|
|
535
712
|
}
|
|
536
|
-
if (this.
|
|
713
|
+
if (this._state === FromBTCSwapState.PR_CREATED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
|
|
537
714
|
await this._saveAndEmit(FromBTCSwapState.CLAIM_COMMITED);
|
|
538
715
|
}
|
|
539
716
|
}
|
|
540
717
|
//////////////////////////////
|
|
541
718
|
//// Claim
|
|
542
719
|
/**
|
|
543
|
-
* Returns transactions
|
|
544
|
-
*
|
|
720
|
+
* Returns transactions for settling (claiming) the swap if the swap requires manual settlement, you can check so
|
|
721
|
+
* with isClaimable. After sending the transaction manually be sure to call the waitTillClaimed function to wait
|
|
722
|
+
* till the claim transaction is observed, processed by the SDK and state of the swap properly updated.
|
|
723
|
+
*
|
|
724
|
+
* @remarks
|
|
725
|
+
* Might also return transactions necessary to sync the bitcoin light client.
|
|
545
726
|
*
|
|
546
|
-
* @
|
|
727
|
+
* @param _signer Address of the signer to create the claim transactions for
|
|
728
|
+
*
|
|
729
|
+
* @throws {Error} If the swap is in invalid state (must be {@link FromBTCSwapState.BTC_TX_CONFIRMED})
|
|
547
730
|
*/
|
|
548
731
|
async txsClaim(_signer) {
|
|
549
732
|
let signer = undefined;
|
|
@@ -555,40 +738,49 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
555
738
|
signer = _signer;
|
|
556
739
|
}
|
|
557
740
|
else {
|
|
558
|
-
signer = await this.wrapper.
|
|
741
|
+
signer = await this.wrapper._chain.wrapSigner(_signer);
|
|
559
742
|
}
|
|
560
743
|
}
|
|
561
|
-
if (this.
|
|
744
|
+
if (this._state !== FromBTCSwapState.BTC_TX_CONFIRMED)
|
|
562
745
|
throw new Error("Must be in BTC_TX_CONFIRMED state!");
|
|
563
746
|
if (this.txId == null || this.vout == null)
|
|
564
747
|
throw new Error("Bitcoin transaction ID not known!");
|
|
565
|
-
const tx = await this.wrapper.
|
|
748
|
+
const tx = await this.wrapper._btcRpc.getTransaction(this.txId);
|
|
566
749
|
if (tx == null)
|
|
567
750
|
throw new Error("Bitcoin transaction not found on the network!");
|
|
751
|
+
this.requiredConfirmations ??= this.inferRequiredConfirmationsCount(tx, this.vout);
|
|
752
|
+
if (this.requiredConfirmations == null)
|
|
753
|
+
throw new Error("Cannot create claim transaction, because required confirmations are not known and cannot be infered! This can happen after a swap is recovered.");
|
|
568
754
|
if (tx.blockhash == null || tx.confirmations == null || tx.blockheight == null || tx.confirmations < this.requiredConfirmations)
|
|
569
755
|
throw new Error("Bitcoin transaction not confirmed yet!");
|
|
570
|
-
return await this.wrapper.
|
|
756
|
+
return await this.wrapper._contract.txsClaimWithTxData(signer ?? this._getInitiator(), this._data, {
|
|
571
757
|
blockhash: tx.blockhash,
|
|
572
758
|
confirmations: tx.confirmations,
|
|
573
759
|
txid: tx.txid,
|
|
574
760
|
hex: tx.hex,
|
|
575
761
|
height: tx.blockheight
|
|
576
|
-
}, this.requiredConfirmations, this.vout, undefined, this.wrapper.
|
|
762
|
+
}, this.requiredConfirmations, this.vout, undefined, this.wrapper._synchronizer, true);
|
|
577
763
|
}
|
|
578
764
|
/**
|
|
579
|
-
*
|
|
765
|
+
* Settles the swap by claiming the funds on the destination chain if the swap requires manual settlement, you can
|
|
766
|
+
* check so with isClaimable.
|
|
767
|
+
*
|
|
768
|
+
* @remarks
|
|
769
|
+
* Might also sync the bitcoin light client during the process.
|
|
580
770
|
*
|
|
581
|
-
* @param _signer Signer to
|
|
582
|
-
* @param abortSignal Abort signal
|
|
583
|
-
* @param onBeforeTxSent
|
|
771
|
+
* @param _signer Signer to use for signing the settlement transactions, can also be different to the recipient
|
|
772
|
+
* @param abortSignal Abort signal
|
|
773
|
+
* @param onBeforeTxSent Optional callback triggered before the claim transaction is broadcasted
|
|
774
|
+
*
|
|
775
|
+
* @returns Transaction ID of the settlement (claim) transaction on the destination smart chain
|
|
584
776
|
*/
|
|
585
777
|
async claim(_signer, abortSignal, onBeforeTxSent) {
|
|
586
|
-
const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper.
|
|
778
|
+
const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper._chain.wrapSigner(_signer);
|
|
587
779
|
let txIds;
|
|
588
780
|
try {
|
|
589
781
|
let txCount = 0;
|
|
590
782
|
const txs = await this.txsClaim(signer);
|
|
591
|
-
txIds = await this.wrapper.
|
|
783
|
+
txIds = await this.wrapper._chain.sendAndConfirm(signer, txs, true, abortSignal, undefined, (txId) => {
|
|
592
784
|
txCount++;
|
|
593
785
|
if (onBeforeTxSent != null && txCount === txs.length)
|
|
594
786
|
onBeforeTxSent(txId);
|
|
@@ -597,42 +789,39 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
597
789
|
}
|
|
598
790
|
catch (e) {
|
|
599
791
|
this.logger.info("claim(): Failed to claim ourselves, checking swap claim state...");
|
|
600
|
-
if (this.
|
|
792
|
+
if (this._state === FromBTCSwapState.CLAIM_CLAIMED) {
|
|
601
793
|
this.logger.info("claim(): Transaction state is CLAIM_CLAIMED, swap was successfully claimed by the watchtower");
|
|
602
|
-
return this.
|
|
794
|
+
return this._claimTxId;
|
|
603
795
|
}
|
|
604
|
-
const status = await this.wrapper.
|
|
796
|
+
const status = await this.wrapper._contract.getCommitStatus(this._getInitiator(), this._data);
|
|
605
797
|
if (status?.type === base_1.SwapCommitStateType.PAID) {
|
|
606
798
|
this.logger.info("claim(): Transaction commit status is PAID, swap was successfully claimed by the watchtower");
|
|
607
|
-
if (this.
|
|
608
|
-
this.
|
|
799
|
+
if (this._claimTxId == null)
|
|
800
|
+
this._claimTxId = await status.getClaimTxId();
|
|
609
801
|
const txId = buffer_1.Buffer.from(await status.getClaimResult(), "hex").reverse().toString("hex");
|
|
610
802
|
await this._setBitcoinTxId(txId);
|
|
611
803
|
await this._saveAndEmit(FromBTCSwapState.CLAIM_CLAIMED);
|
|
612
|
-
return this.
|
|
804
|
+
return this._claimTxId;
|
|
613
805
|
}
|
|
614
806
|
throw e;
|
|
615
807
|
}
|
|
616
|
-
this.
|
|
617
|
-
if (this.
|
|
618
|
-
this.
|
|
808
|
+
this._claimTxId = txIds[txIds.length - 1];
|
|
809
|
+
if (this._state === FromBTCSwapState.CLAIM_COMMITED || this._state === FromBTCSwapState.BTC_TX_CONFIRMED ||
|
|
810
|
+
this._state === FromBTCSwapState.EXPIRED || this._state === FromBTCSwapState.FAILED) {
|
|
619
811
|
await this._saveAndEmit(FromBTCSwapState.CLAIM_CLAIMED);
|
|
620
812
|
}
|
|
621
813
|
return txIds[txIds.length - 1];
|
|
622
814
|
}
|
|
623
815
|
/**
|
|
624
|
-
*
|
|
816
|
+
* @inheritDoc
|
|
625
817
|
*
|
|
626
|
-
* @
|
|
627
|
-
* @param abortSignal AbortSignal
|
|
628
|
-
* @throws {Error} If swap is in invalid state (must be BTC_TX_CONFIRMED)
|
|
818
|
+
* @throws {Error} If swap is in invalid state (must be {@link FromBTCSwapState.BTC_TX_CONFIRMED})
|
|
629
819
|
* @throws {Error} If the LP refunded sooner than we were able to claim
|
|
630
|
-
* @returns {boolean} whether the swap was claimed in time or not
|
|
631
820
|
*/
|
|
632
821
|
async waitTillClaimed(maxWaitTimeSeconds, abortSignal) {
|
|
633
|
-
if (this.
|
|
822
|
+
if (this._state === FromBTCSwapState.CLAIM_CLAIMED)
|
|
634
823
|
return Promise.resolve(true);
|
|
635
|
-
if (this.
|
|
824
|
+
if (this._state !== FromBTCSwapState.BTC_TX_CONFIRMED)
|
|
636
825
|
throw new Error("Invalid state (not BTC_TX_CONFIRMED)");
|
|
637
826
|
const abortController = (0, Utils_1.extendAbortController)(abortSignal);
|
|
638
827
|
let timedOut = false;
|
|
@@ -668,19 +857,19 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
668
857
|
}
|
|
669
858
|
this.logger.debug("waitTillClaimed(): Resolved from watchdog");
|
|
670
859
|
if (res?.type === base_1.SwapCommitStateType.PAID) {
|
|
671
|
-
if (this.
|
|
672
|
-
if (this.
|
|
673
|
-
this.
|
|
860
|
+
if (this._state !== FromBTCSwapState.CLAIM_CLAIMED) {
|
|
861
|
+
if (this._claimTxId == null)
|
|
862
|
+
this._claimTxId = await res.getClaimTxId();
|
|
674
863
|
const txId = buffer_1.Buffer.from(await res.getClaimResult(), "hex").reverse().toString("hex");
|
|
675
864
|
await this._setBitcoinTxId(txId);
|
|
676
865
|
await this._saveAndEmit(FromBTCSwapState.CLAIM_CLAIMED);
|
|
677
866
|
}
|
|
678
867
|
}
|
|
679
868
|
if (res?.type === base_1.SwapCommitStateType.NOT_COMMITED || res?.type === base_1.SwapCommitStateType.EXPIRED) {
|
|
680
|
-
if (this.
|
|
681
|
-
this.
|
|
869
|
+
if (this._state !== FromBTCSwapState.CLAIM_CLAIMED &&
|
|
870
|
+
this._state !== FromBTCSwapState.FAILED) {
|
|
682
871
|
if (res.getRefundTxId != null)
|
|
683
|
-
this.
|
|
872
|
+
this._refundTxId = await res.getRefundTxId();
|
|
684
873
|
await this._saveAndEmit(FromBTCSwapState.FAILED);
|
|
685
874
|
}
|
|
686
875
|
throw new Error("Swap expired while waiting for claim!");
|
|
@@ -689,11 +878,14 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
689
878
|
}
|
|
690
879
|
//////////////////////////////
|
|
691
880
|
//// Storage
|
|
881
|
+
/**
|
|
882
|
+
* @inheritDoc
|
|
883
|
+
*/
|
|
692
884
|
serialize() {
|
|
693
885
|
return {
|
|
694
886
|
...super.serialize(),
|
|
695
887
|
address: this.address,
|
|
696
|
-
amount: this.amount.toString(10),
|
|
888
|
+
amount: this.amount == null ? null : this.amount.toString(10),
|
|
697
889
|
requiredConfirmations: this.requiredConfirmations,
|
|
698
890
|
senderAddress: this.senderAddress,
|
|
699
891
|
txId: this.txId,
|
|
@@ -709,89 +901,114 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
709
901
|
* @private
|
|
710
902
|
*/
|
|
711
903
|
async syncStateFromChain(quoteDefinitelyExpired, commitStatus) {
|
|
712
|
-
if (this.
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
if (this.refundTxId == null && status.getRefundTxId)
|
|
721
|
-
this.refundTxId = await status.getRefundTxId();
|
|
722
|
-
this.state = FromBTCSwapState.QUOTE_EXPIRED;
|
|
723
|
-
return true;
|
|
724
|
-
case base_1.SwapCommitStateType.PAID:
|
|
725
|
-
if (this.claimTxId == null)
|
|
726
|
-
this.claimTxId = await status.getClaimTxId();
|
|
727
|
-
const txId = buffer_1.Buffer.from(await status.getClaimResult(), "hex").reverse().toString("hex");
|
|
728
|
-
await this._setBitcoinTxId(txId);
|
|
729
|
-
this.state = FromBTCSwapState.CLAIM_CLAIMED;
|
|
730
|
-
return true;
|
|
904
|
+
if (this._state === FromBTCSwapState.PR_CREATED ||
|
|
905
|
+
this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED ||
|
|
906
|
+
this._state === FromBTCSwapState.CLAIM_COMMITED ||
|
|
907
|
+
this._state === FromBTCSwapState.BTC_TX_CONFIRMED ||
|
|
908
|
+
this._state === FromBTCSwapState.EXPIRED) {
|
|
909
|
+
let quoteExpired = false;
|
|
910
|
+
if (this._state === FromBTCSwapState.PR_CREATED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
|
|
911
|
+
quoteExpired = quoteDefinitelyExpired ?? await this._verifyQuoteDefinitelyExpired(); //Make sure we check for expiry here, to prevent race conditions
|
|
731
912
|
}
|
|
732
|
-
|
|
733
|
-
|
|
913
|
+
const status = commitStatus ?? await this.wrapper._contract.getCommitStatus(this._getInitiator(), this._data);
|
|
914
|
+
if (status != null && await this._forciblySetOnchainState(status))
|
|
734
915
|
return true;
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
if (this.state === FromBTCSwapState.CLAIM_COMMITED || this.state === FromBTCSwapState.BTC_TX_CONFIRMED || this.state === FromBTCSwapState.EXPIRED) {
|
|
739
|
-
const status = commitStatus ?? await this.wrapper.contract.getCommitStatus(this._getInitiator(), this.data);
|
|
740
|
-
switch (status?.type) {
|
|
741
|
-
case base_1.SwapCommitStateType.PAID:
|
|
742
|
-
if (this.claimTxId == null)
|
|
743
|
-
this.claimTxId = await status.getClaimTxId();
|
|
744
|
-
const txId = buffer_1.Buffer.from(await status.getClaimResult(), "hex").reverse().toString("hex");
|
|
745
|
-
await this._setBitcoinTxId(txId);
|
|
746
|
-
this.state = FromBTCSwapState.CLAIM_CLAIMED;
|
|
747
|
-
return true;
|
|
748
|
-
case base_1.SwapCommitStateType.NOT_COMMITED:
|
|
749
|
-
case base_1.SwapCommitStateType.EXPIRED:
|
|
750
|
-
if (this.refundTxId == null && status.getRefundTxId)
|
|
751
|
-
this.refundTxId = await status.getRefundTxId();
|
|
752
|
-
this.state = FromBTCSwapState.FAILED;
|
|
916
|
+
if (this._state === FromBTCSwapState.PR_CREATED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
|
|
917
|
+
if (quoteExpired) {
|
|
918
|
+
this._state = FromBTCSwapState.QUOTE_EXPIRED;
|
|
753
919
|
return true;
|
|
754
|
-
|
|
755
|
-
const res = await this.getBitcoinPayment();
|
|
756
|
-
if (res != null) {
|
|
757
|
-
let save = false;
|
|
758
|
-
if (this.txId !== res.txId) {
|
|
759
|
-
if (res.inputAddresses != null)
|
|
760
|
-
this.senderAddress = res.inputAddresses[0];
|
|
761
|
-
this.txId = res.txId;
|
|
762
|
-
this.vout = res.vout;
|
|
763
|
-
save = true;
|
|
764
|
-
}
|
|
765
|
-
if (res.confirmations >= this.requiredConfirmations) {
|
|
766
|
-
this.state = FromBTCSwapState.BTC_TX_CONFIRMED;
|
|
767
|
-
save = true;
|
|
768
|
-
}
|
|
769
|
-
return save;
|
|
770
|
-
}
|
|
771
|
-
break;
|
|
920
|
+
}
|
|
772
921
|
}
|
|
773
922
|
}
|
|
774
923
|
return false;
|
|
775
924
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
925
|
+
/**
|
|
926
|
+
* @inheritDoc
|
|
927
|
+
* @internal
|
|
928
|
+
*/
|
|
929
|
+
_shouldFetchOnchainState() {
|
|
930
|
+
return this._state === FromBTCSwapState.PR_CREATED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED ||
|
|
931
|
+
this._state === FromBTCSwapState.CLAIM_COMMITED || this._state === FromBTCSwapState.BTC_TX_CONFIRMED ||
|
|
932
|
+
this._state === FromBTCSwapState.EXPIRED;
|
|
780
933
|
}
|
|
934
|
+
/**
|
|
935
|
+
* @inheritDoc
|
|
936
|
+
* @internal
|
|
937
|
+
*/
|
|
781
938
|
_shouldFetchExpiryStatus() {
|
|
782
|
-
return this.
|
|
939
|
+
return this._state === FromBTCSwapState.PR_CREATED || this._state === FromBTCSwapState.QUOTE_SOFT_EXPIRED;
|
|
783
940
|
}
|
|
941
|
+
/**
|
|
942
|
+
* @inheritDoc
|
|
943
|
+
* @internal
|
|
944
|
+
*/
|
|
784
945
|
async _sync(save, quoteDefinitelyExpired, commitStatus) {
|
|
785
946
|
const changed = await this.syncStateFromChain(quoteDefinitelyExpired, commitStatus);
|
|
786
947
|
if (changed && save)
|
|
787
948
|
await this._saveAndEmit();
|
|
788
949
|
return changed;
|
|
789
950
|
}
|
|
951
|
+
/**
|
|
952
|
+
* @inheritDoc
|
|
953
|
+
* @internal
|
|
954
|
+
*/
|
|
955
|
+
async _forciblySetOnchainState(status) {
|
|
956
|
+
switch (status.type) {
|
|
957
|
+
case base_1.SwapCommitStateType.PAID:
|
|
958
|
+
if (this._claimTxId == null)
|
|
959
|
+
this._claimTxId = await status.getClaimTxId();
|
|
960
|
+
const txId = buffer_1.Buffer.from(await status.getClaimResult(), "hex").reverse().toString("hex");
|
|
961
|
+
await this._setBitcoinTxId(txId);
|
|
962
|
+
this._state = FromBTCSwapState.CLAIM_CLAIMED;
|
|
963
|
+
return true;
|
|
964
|
+
case base_1.SwapCommitStateType.NOT_COMMITED:
|
|
965
|
+
if (this._refundTxId == null && status.getRefundTxId)
|
|
966
|
+
this._refundTxId = await status.getRefundTxId();
|
|
967
|
+
if (this._refundTxId != null) {
|
|
968
|
+
this._state = FromBTCSwapState.FAILED;
|
|
969
|
+
return true;
|
|
970
|
+
}
|
|
971
|
+
break;
|
|
972
|
+
case base_1.SwapCommitStateType.EXPIRED:
|
|
973
|
+
if (this._refundTxId == null && status.getRefundTxId)
|
|
974
|
+
this._refundTxId = await status.getRefundTxId();
|
|
975
|
+
this._state = this._refundTxId == null ? FromBTCSwapState.QUOTE_EXPIRED : FromBTCSwapState.FAILED;
|
|
976
|
+
return true;
|
|
977
|
+
case base_1.SwapCommitStateType.COMMITED:
|
|
978
|
+
let save = false;
|
|
979
|
+
if (this._state !== FromBTCSwapState.CLAIM_COMMITED && this._state !== FromBTCSwapState.BTC_TX_CONFIRMED && this._state !== FromBTCSwapState.EXPIRED) {
|
|
980
|
+
this._state = FromBTCSwapState.CLAIM_COMMITED;
|
|
981
|
+
save = true;
|
|
982
|
+
}
|
|
983
|
+
if (this.address == null)
|
|
984
|
+
return save;
|
|
985
|
+
const res = await this.getBitcoinPayment();
|
|
986
|
+
if (res != null) {
|
|
987
|
+
if (this.txId !== res.txId) {
|
|
988
|
+
if (res.inputAddresses != null)
|
|
989
|
+
this.senderAddress = res.inputAddresses[0];
|
|
990
|
+
this.txId = res.txId;
|
|
991
|
+
this.vout = res.vout;
|
|
992
|
+
save = true;
|
|
993
|
+
}
|
|
994
|
+
if (this.requiredConfirmations != null && res.confirmations >= this.requiredConfirmations) {
|
|
995
|
+
this._state = FromBTCSwapState.BTC_TX_CONFIRMED;
|
|
996
|
+
save = true;
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
return save;
|
|
1000
|
+
}
|
|
1001
|
+
return false;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* @inheritDoc
|
|
1005
|
+
* @internal
|
|
1006
|
+
*/
|
|
790
1007
|
async _tick(save) {
|
|
791
|
-
switch (this.
|
|
1008
|
+
switch (this._state) {
|
|
792
1009
|
case FromBTCSwapState.PR_CREATED:
|
|
793
1010
|
if (this.expiry < Date.now()) {
|
|
794
|
-
this.
|
|
1011
|
+
this._state = FromBTCSwapState.QUOTE_SOFT_EXPIRED;
|
|
795
1012
|
if (save)
|
|
796
1013
|
await this._saveAndEmit();
|
|
797
1014
|
return true;
|
|
@@ -799,7 +1016,7 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
799
1016
|
break;
|
|
800
1017
|
case FromBTCSwapState.CLAIM_COMMITED:
|
|
801
1018
|
if (this.getTimeoutTime() < Date.now()) {
|
|
802
|
-
this.
|
|
1019
|
+
this._state = FromBTCSwapState.EXPIRED;
|
|
803
1020
|
if (save)
|
|
804
1021
|
await this._saveAndEmit();
|
|
805
1022
|
return true;
|
|
@@ -807,31 +1024,32 @@ class FromBTCSwap extends IFromBTCSelfInitSwap_1.IFromBTCSelfInitSwap {
|
|
|
807
1024
|
case FromBTCSwapState.EXPIRED:
|
|
808
1025
|
//Check if bitcoin payment was received every 2 minutes
|
|
809
1026
|
if (Math.floor(Date.now() / 1000) % 120 === 0) {
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
this.txId
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
this.
|
|
823
|
-
|
|
1027
|
+
if (this.address != null)
|
|
1028
|
+
try {
|
|
1029
|
+
const res = await this.getBitcoinPayment();
|
|
1030
|
+
if (res != null) {
|
|
1031
|
+
let shouldSave = false;
|
|
1032
|
+
if (this.txId !== res.txId) {
|
|
1033
|
+
this.txId = res.txId;
|
|
1034
|
+
this.vout = res.vout;
|
|
1035
|
+
if (res.inputAddresses != null)
|
|
1036
|
+
this.senderAddress = res.inputAddresses[0];
|
|
1037
|
+
shouldSave = true;
|
|
1038
|
+
}
|
|
1039
|
+
if (this.requiredConfirmations != null && res.confirmations >= this.requiredConfirmations) {
|
|
1040
|
+
this._state = FromBTCSwapState.BTC_TX_CONFIRMED;
|
|
1041
|
+
if (save)
|
|
1042
|
+
await this._saveAndEmit();
|
|
1043
|
+
shouldSave = true;
|
|
1044
|
+
}
|
|
1045
|
+
if (shouldSave && save)
|
|
824
1046
|
await this._saveAndEmit();
|
|
825
|
-
shouldSave
|
|
1047
|
+
return shouldSave;
|
|
826
1048
|
}
|
|
827
|
-
if (shouldSave && save)
|
|
828
|
-
await this._saveAndEmit();
|
|
829
|
-
return shouldSave;
|
|
830
1049
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
}
|
|
1050
|
+
catch (e) {
|
|
1051
|
+
this.logger.warn("tickSwap(" + this.getIdentifierHashString() + "): ", e);
|
|
1052
|
+
}
|
|
835
1053
|
}
|
|
836
1054
|
break;
|
|
837
1055
|
}
|