@atomiqlabs/sdk 7.0.12 → 8.0.7
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/README.md +45 -29
- package/dist/SmartChainAssets.d.ts +11 -3
- package/dist/SmartChainAssets.js +7 -3
- package/dist/bitcoin/BitcoinRpcWithAddressIndex.d.ts +68 -0
- package/dist/bitcoin/BitcoinRpcWithAddressIndex.js +2 -0
- package/dist/bitcoin/LightningNetworkApi.d.ts +12 -0
- package/dist/bitcoin/LightningNetworkApi.js +2 -0
- package/dist/bitcoin/coinselect2/accumulative.d.ts +6 -0
- package/dist/bitcoin/coinselect2/accumulative.js +52 -0
- package/dist/bitcoin/coinselect2/blackjack.d.ts +6 -0
- package/dist/bitcoin/coinselect2/blackjack.js +38 -0
- package/dist/bitcoin/coinselect2/index.d.ts +19 -0
- package/dist/bitcoin/coinselect2/index.js +69 -0
- package/dist/bitcoin/coinselect2/utils.d.ts +71 -0
- package/dist/bitcoin/coinselect2/utils.js +123 -0
- package/dist/bitcoin/mempool/MempoolApi.d.ts +350 -0
- package/dist/bitcoin/mempool/MempoolApi.js +311 -0
- package/dist/bitcoin/mempool/MempoolBitcoinBlock.d.ts +44 -0
- package/dist/bitcoin/mempool/MempoolBitcoinBlock.js +48 -0
- package/dist/bitcoin/mempool/MempoolBitcoinRpc.d.ts +119 -0
- package/dist/bitcoin/mempool/MempoolBitcoinRpc.js +361 -0
- package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.d.ts +22 -0
- package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.js +105 -0
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +93 -0
- package/dist/bitcoin/wallet/BitcoinWallet.js +273 -0
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +28 -0
- package/dist/bitcoin/wallet/IBitcoinWallet.js +20 -0
- package/dist/bitcoin/wallet/MinimalBitcoinWalletInterface.d.ts +21 -0
- package/dist/bitcoin/wallet/MinimalBitcoinWalletInterface.js +2 -0
- package/dist/bitcoin/wallet/MinimalLightningNetworkWalletInterface.d.ts +7 -0
- package/dist/bitcoin/wallet/MinimalLightningNetworkWalletInterface.js +2 -0
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +40 -0
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +86 -0
- package/dist/enums/FeeType.d.ts +8 -0
- package/dist/enums/FeeType.js +12 -0
- package/dist/enums/SwapAmountType.d.ts +8 -0
- package/dist/enums/SwapAmountType.js +12 -0
- package/dist/enums/SwapDirection.d.ts +8 -0
- package/dist/enums/SwapDirection.js +12 -0
- package/dist/enums/SwapType.d.ts +14 -0
- package/dist/enums/SwapType.js +18 -0
- package/dist/errors/IntermediaryError.d.ts +9 -0
- package/dist/errors/IntermediaryError.js +26 -0
- package/dist/errors/PaymentAuthError.d.ts +11 -0
- package/dist/errors/PaymentAuthError.js +23 -0
- package/dist/errors/RequestError.d.ts +18 -0
- package/dist/errors/RequestError.js +46 -0
- package/dist/errors/UserError.d.ts +7 -0
- package/dist/errors/UserError.js +15 -0
- package/dist/events/UnifiedSwapEventListener.d.ts +23 -0
- package/dist/events/UnifiedSwapEventListener.js +130 -0
- package/dist/http/HttpUtils.d.ts +27 -0
- package/dist/http/HttpUtils.js +91 -0
- package/dist/http/paramcoders/IParamReader.d.ts +8 -0
- package/dist/http/paramcoders/IParamReader.js +2 -0
- package/dist/http/paramcoders/ParamDecoder.d.ts +44 -0
- package/dist/http/paramcoders/ParamDecoder.js +132 -0
- package/dist/http/paramcoders/ParamEncoder.d.ts +20 -0
- package/dist/http/paramcoders/ParamEncoder.js +31 -0
- package/dist/http/paramcoders/SchemaVerifier.d.ts +26 -0
- package/dist/http/paramcoders/SchemaVerifier.js +145 -0
- package/dist/http/paramcoders/client/ResponseParamDecoder.d.ts +11 -0
- package/dist/http/paramcoders/client/ResponseParamDecoder.js +57 -0
- package/dist/http/paramcoders/client/StreamParamEncoder.d.ts +13 -0
- package/dist/http/paramcoders/client/StreamParamEncoder.js +26 -0
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +16 -0
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +174 -0
- package/dist/index.d.ts +82 -4
- package/dist/index.js +128 -4
- package/dist/intermediaries/Intermediary.d.ts +111 -0
- package/dist/intermediaries/Intermediary.js +115 -0
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +166 -0
- package/dist/intermediaries/IntermediaryDiscovery.js +390 -0
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +436 -0
- package/dist/intermediaries/apis/IntermediaryAPI.js +600 -0
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.d.ts +154 -0
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.js +136 -0
- package/dist/lnurl/LNURL.d.ts +102 -0
- package/dist/lnurl/LNURL.js +321 -0
- package/dist/prices/RedundantSwapPrice.d.ts +89 -0
- package/dist/prices/RedundantSwapPrice.js +202 -0
- package/dist/prices/SingleSwapPrice.d.ts +31 -0
- package/dist/prices/SingleSwapPrice.js +41 -0
- package/dist/prices/SwapPriceWithChain.d.ts +70 -0
- package/dist/prices/SwapPriceWithChain.js +91 -0
- package/dist/prices/abstract/ICachedSwapPrice.d.ts +28 -0
- package/dist/prices/abstract/ICachedSwapPrice.js +62 -0
- package/dist/prices/abstract/IPriceProvider.d.ts +81 -0
- package/dist/prices/abstract/IPriceProvider.js +74 -0
- package/dist/prices/abstract/ISwapPrice.d.ts +117 -0
- package/dist/prices/abstract/ISwapPrice.js +219 -0
- package/dist/prices/providers/BinancePriceProvider.d.ts +16 -0
- package/dist/prices/providers/BinancePriceProvider.js +23 -0
- package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +17 -0
- package/dist/prices/providers/CoinGeckoPriceProvider.js +23 -0
- package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +19 -0
- package/dist/prices/providers/CoinPaprikaPriceProvider.js +23 -0
- package/dist/prices/providers/CustomPriceProvider.d.ts +13 -0
- package/dist/prices/providers/CustomPriceProvider.js +24 -0
- package/dist/prices/providers/KrakenPriceProvider.d.ts +29 -0
- package/dist/prices/providers/KrakenPriceProvider.js +36 -0
- package/dist/prices/providers/OKXPriceProvider.d.ts +28 -0
- package/dist/prices/providers/OKXPriceProvider.js +23 -0
- package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +14 -0
- package/dist/prices/providers/abstract/ExchangePriceProvider.js +18 -0
- package/dist/prices/providers/abstract/HttpPriceProvider.d.ts +7 -0
- package/dist/prices/providers/abstract/HttpPriceProvider.js +12 -0
- package/dist/storage/IUnifiedStorage.d.ts +73 -0
- package/dist/storage/IUnifiedStorage.js +2 -0
- package/dist/storage/UnifiedSwapStorage.d.ts +82 -0
- package/dist/storage/UnifiedSwapStorage.js +83 -0
- package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +39 -0
- package/dist/storage-browser/IndexedDBUnifiedStorage.js +275 -0
- package/dist/{storage → storage-browser}/LocalStorageManager.d.ts +1 -0
- package/dist/{storage → storage-browser}/LocalStorageManager.js +2 -1
- package/dist/swapper/Swapper.d.ts +533 -0
- package/dist/swapper/Swapper.js +1566 -0
- package/dist/swapper/SwapperFactory.d.ts +87 -0
- package/dist/{SwapperFactory.js → swapper/SwapperFactory.js} +37 -19
- package/dist/swapper/SwapperUtils.d.ts +153 -0
- package/dist/swapper/SwapperUtils.js +420 -0
- package/dist/swapper/SwapperWithChain.d.ts +214 -0
- package/dist/swapper/SwapperWithChain.js +315 -0
- package/dist/swapper/SwapperWithSigner.d.ts +178 -0
- package/dist/swapper/SwapperWithSigner.js +172 -0
- package/dist/swaps/IAddressSwap.d.ts +13 -0
- package/dist/swaps/IAddressSwap.js +13 -0
- package/dist/swaps/IBTCWalletSwap.d.ts +55 -0
- package/dist/swaps/IBTCWalletSwap.js +17 -0
- package/dist/swaps/IClaimableSwap.d.ts +17 -0
- package/dist/swaps/IClaimableSwap.js +14 -0
- package/dist/swaps/IClaimableSwapWrapper.d.ts +5 -0
- package/dist/swaps/IClaimableSwapWrapper.js +2 -0
- package/dist/swaps/IRefundableSwap.d.ts +17 -0
- package/dist/swaps/IRefundableSwap.js +13 -0
- package/dist/swaps/ISwap.d.ts +207 -0
- package/dist/swaps/ISwap.js +264 -0
- package/dist/swaps/ISwapWithGasDrop.d.ts +15 -0
- package/dist/swaps/ISwapWithGasDrop.js +11 -0
- package/dist/swaps/ISwapWrapper.d.ts +153 -0
- package/dist/swaps/ISwapWrapper.js +227 -0
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +53 -0
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +116 -0
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +70 -0
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +132 -0
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +85 -0
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +122 -0
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +86 -0
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +115 -0
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +93 -0
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +121 -0
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +45 -0
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +65 -0
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +263 -0
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +933 -0
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +110 -0
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +307 -0
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +236 -0
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +898 -0
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +125 -0
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +393 -0
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +245 -0
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +841 -0
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +120 -0
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +294 -0
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +228 -0
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +721 -0
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +37 -0
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +93 -0
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +86 -0
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +213 -0
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +170 -0
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +520 -0
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +50 -0
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +109 -0
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +93 -0
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +217 -0
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +315 -0
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +1098 -0
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +125 -0
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +631 -0
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +107 -0
- package/dist/swaps/trusted/ln/LnForGasSwap.js +343 -0
- package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +21 -0
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +62 -0
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +164 -0
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +520 -0
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +48 -0
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +74 -0
- package/dist/types/AmountData.d.ts +9 -0
- package/dist/types/AmountData.js +2 -0
- package/dist/types/CustomPriceFunction.d.ts +5 -0
- package/dist/types/CustomPriceFunction.js +2 -0
- package/dist/types/PriceInfoType.d.ts +28 -0
- package/dist/types/PriceInfoType.js +57 -0
- package/dist/types/SwapExecutionAction.d.ts +7 -0
- package/dist/types/SwapExecutionAction.js +2 -0
- package/dist/types/SwapWithSigner.d.ts +14 -0
- package/dist/types/SwapWithSigner.js +40 -0
- package/dist/types/Token.d.ts +53 -0
- package/dist/types/Token.js +58 -0
- package/dist/types/TokenAmount.d.ts +57 -0
- package/dist/types/TokenAmount.js +47 -0
- package/dist/types/fees/Fee.d.ts +49 -0
- package/dist/types/fees/Fee.js +2 -0
- package/dist/types/fees/FeeBreakdown.d.ts +10 -0
- package/dist/types/fees/FeeBreakdown.js +2 -0
- package/dist/types/fees/PercentagePPM.d.ts +15 -0
- package/dist/types/fees/PercentagePPM.js +17 -0
- package/dist/types/lnurl/LNURLPay.d.ts +54 -0
- package/dist/types/lnurl/LNURLPay.js +28 -0
- package/dist/types/lnurl/LNURLWithdraw.d.ts +42 -0
- package/dist/types/lnurl/LNURLWithdraw.js +24 -0
- package/dist/utils/AutomaticClockDriftCorrection.d.ts +1 -0
- package/dist/utils/AutomaticClockDriftCorrection.js +70 -0
- package/dist/utils/BitcoinUtils.d.ts +13 -0
- package/dist/utils/BitcoinUtils.js +98 -0
- package/dist/utils/BitcoinWalletUtils.d.ts +7 -0
- package/dist/utils/BitcoinWalletUtils.js +14 -0
- package/dist/utils/Logger.d.ts +7 -0
- package/dist/utils/Logger.js +12 -0
- package/dist/utils/RetryUtils.d.ts +21 -0
- package/dist/utils/RetryUtils.js +66 -0
- package/dist/utils/SwapUtils.d.ts +31 -0
- package/dist/utils/SwapUtils.js +18 -0
- package/dist/{Utils.d.ts → utils/TimeoutUtils.d.ts} +9 -3
- package/dist/utils/TimeoutUtils.js +55 -0
- package/dist/utils/TokenUtils.d.ts +11 -0
- package/dist/utils/TokenUtils.js +29 -0
- package/dist/utils/TypeUtils.d.ts +7 -0
- package/dist/utils/TypeUtils.js +2 -0
- package/dist/utils/Utils.d.ts +57 -0
- package/dist/utils/Utils.js +178 -0
- package/package.json +14 -6
- package/src/SmartChainAssets.ts +11 -3
- package/src/bitcoin/BitcoinRpcWithAddressIndex.ts +87 -0
- package/src/bitcoin/LightningNetworkApi.ts +16 -0
- package/src/bitcoin/coinselect2/accumulative.ts +68 -0
- package/src/bitcoin/coinselect2/blackjack.ts +49 -0
- package/src/bitcoin/coinselect2/index.ts +92 -0
- package/src/bitcoin/coinselect2/utils.ts +189 -0
- package/src/bitcoin/mempool/MempoolApi.ts +554 -0
- package/src/bitcoin/mempool/MempoolBitcoinBlock.ts +88 -0
- package/src/bitcoin/mempool/MempoolBitcoinRpc.ts +437 -0
- package/src/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.ts +134 -0
- package/src/bitcoin/wallet/BitcoinWallet.ts +375 -0
- package/src/bitcoin/wallet/IBitcoinWallet.ts +44 -0
- package/src/bitcoin/wallet/MinimalBitcoinWalletInterface.ts +19 -0
- package/src/bitcoin/wallet/MinimalLightningNetworkWalletInterface.ts +7 -0
- package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +108 -0
- package/src/enums/FeeType.ts +9 -0
- package/src/enums/SwapAmountType.ts +9 -0
- package/src/enums/SwapDirection.ts +9 -0
- package/src/enums/SwapType.ts +15 -0
- package/src/errors/IntermediaryError.ts +24 -0
- package/src/errors/PaymentAuthError.ts +26 -0
- package/src/errors/RequestError.ts +51 -0
- package/src/errors/UserError.ts +14 -0
- package/src/events/UnifiedSwapEventListener.ts +171 -0
- package/src/http/HttpUtils.ts +92 -0
- package/src/http/paramcoders/IParamReader.ts +10 -0
- package/src/http/paramcoders/ParamDecoder.ts +142 -0
- package/src/http/paramcoders/ParamEncoder.ts +37 -0
- package/src/http/paramcoders/SchemaVerifier.ts +153 -0
- package/src/http/paramcoders/client/ResponseParamDecoder.ts +58 -0
- package/src/http/paramcoders/client/StreamParamEncoder.ts +29 -0
- package/src/http/paramcoders/client/StreamingFetchPromise.ts +193 -0
- package/src/index.ts +102 -4
- package/src/intermediaries/Intermediary.ts +204 -0
- package/src/intermediaries/IntermediaryDiscovery.ts +485 -0
- package/src/intermediaries/apis/IntermediaryAPI.ts +940 -0
- package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +257 -0
- package/src/lnurl/LNURL.ts +403 -0
- package/src/prices/RedundantSwapPrice.ts +245 -0
- package/src/prices/SingleSwapPrice.ts +47 -0
- package/src/prices/SwapPriceWithChain.ts +157 -0
- package/src/prices/abstract/ICachedSwapPrice.ts +86 -0
- package/src/prices/abstract/IPriceProvider.ts +128 -0
- package/src/prices/abstract/ISwapPrice.ts +328 -0
- package/src/prices/providers/BinancePriceProvider.ts +41 -0
- package/src/prices/providers/CoinGeckoPriceProvider.ts +40 -0
- package/src/prices/providers/CoinPaprikaPriceProvider.ts +44 -0
- package/src/prices/providers/CustomPriceProvider.ts +29 -0
- package/src/prices/providers/KrakenPriceProvider.ts +74 -0
- package/src/prices/providers/OKXPriceProvider.ts +53 -0
- package/src/prices/providers/abstract/ExchangePriceProvider.ts +29 -0
- package/src/prices/providers/abstract/HttpPriceProvider.ts +15 -0
- package/src/storage/IUnifiedStorage.ts +83 -0
- package/src/storage/UnifiedSwapStorage.ts +104 -0
- package/src/storage-browser/IndexedDBUnifiedStorage.ts +328 -0
- package/src/{storage → storage-browser}/LocalStorageManager.ts +2 -1
- package/src/swapper/Swapper.ts +2107 -0
- package/src/{SwapperFactory.ts → swapper/SwapperFactory.ts} +113 -72
- package/src/swapper/SwapperUtils.ts +510 -0
- package/src/swapper/SwapperWithChain.ts +464 -0
- package/src/swapper/SwapperWithSigner.ts +300 -0
- package/src/swaps/IAddressSwap.ts +20 -0
- package/src/swaps/IBTCWalletSwap.ts +77 -0
- package/src/swaps/IClaimableSwap.ts +30 -0
- package/src/swaps/IClaimableSwapWrapper.ts +9 -0
- package/src/swaps/IRefundableSwap.ts +29 -0
- package/src/swaps/ISwap.ts +490 -0
- package/src/swaps/ISwapWithGasDrop.ts +19 -0
- package/src/swaps/ISwapWrapper.ts +344 -0
- package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +168 -0
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +197 -0
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +210 -0
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +150 -0
- package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +219 -0
- package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +84 -0
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +1082 -0
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +429 -0
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +1078 -0
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +549 -0
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +974 -0
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +443 -0
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +860 -0
- package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +104 -0
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +256 -0
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +716 -0
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +151 -0
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +299 -0
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +1394 -0
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +796 -0
- package/src/swaps/trusted/ln/LnForGasSwap.ts +402 -0
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +70 -0
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +633 -0
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +110 -0
- package/src/types/AmountData.ts +9 -0
- package/src/types/CustomPriceFunction.ts +5 -0
- package/src/types/PriceInfoType.ts +67 -0
- package/src/types/SwapExecutionAction.ts +8 -0
- package/src/types/SwapWithSigner.ts +57 -0
- package/src/types/Token.ts +90 -0
- package/src/types/TokenAmount.ts +110 -0
- package/src/types/fees/Fee.ts +55 -0
- package/src/types/fees/FeeBreakdown.ts +11 -0
- package/src/types/fees/PercentagePPM.ts +24 -0
- package/src/types/lnurl/LNURLPay.ts +72 -0
- package/src/types/lnurl/LNURLWithdraw.ts +55 -0
- package/src/utils/AutomaticClockDriftCorrection.ts +71 -0
- package/src/utils/BitcoinUtils.ts +86 -0
- package/src/utils/BitcoinWalletUtils.ts +16 -0
- package/src/utils/Logger.ts +15 -0
- package/src/utils/RetryUtils.ts +71 -0
- package/src/utils/SwapUtils.ts +38 -0
- package/src/utils/TimeoutUtils.ts +50 -0
- package/src/utils/TokenUtils.ts +25 -0
- package/src/utils/TypeUtils.ts +9 -0
- package/src/utils/Utils.ts +182 -0
- package/dist/SwapperFactory.d.ts +0 -52
- package/dist/Utils.js +0 -37
- package/dist/fs-storage/FileSystemStorageManager.d.ts +0 -15
- package/dist/fs-storage/FileSystemStorageManager.js +0 -60
- package/dist/fs-storage/index.d.ts +0 -1
- package/dist/fs-storage/index.js +0 -17
- package/src/SmartChainAssets.js +0 -75
- package/src/SwapperFactory.js +0 -120
- package/src/Utils.js +0 -37
- package/src/Utils.ts +0 -31
- package/src/fs-storage/FileSystemStorageManager.ts +0 -71
- package/src/fs-storage/index.ts +0 -1
- package/src/index.js +0 -21
- package/src/storage/LocalStorageManager.js +0 -72
|
@@ -0,0 +1,898 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FromBTCLNAutoSwap = exports.isFromBTCLNAutoSwapInit = exports.FromBTCLNAutoSwapState = void 0;
|
|
4
|
+
const bolt11_1 = require("@atomiqlabs/bolt11");
|
|
5
|
+
const SwapType_1 = require("../../../../enums/SwapType");
|
|
6
|
+
const base_1 = require("@atomiqlabs/base");
|
|
7
|
+
const buffer_1 = require("buffer");
|
|
8
|
+
const LNURL_1 = require("../../../../lnurl/LNURL");
|
|
9
|
+
const UserError_1 = require("../../../../errors/UserError");
|
|
10
|
+
const IntermediaryAPI_1 = require("../../../../intermediaries/apis/IntermediaryAPI");
|
|
11
|
+
const IntermediaryError_1 = require("../../../../errors/IntermediaryError");
|
|
12
|
+
const Utils_1 = require("../../../../utils/Utils");
|
|
13
|
+
const IEscrowSwap_1 = require("../../IEscrowSwap");
|
|
14
|
+
const FeeType_1 = require("../../../../enums/FeeType");
|
|
15
|
+
const PercentagePPM_1 = require("../../../../types/fees/PercentagePPM");
|
|
16
|
+
const TokenAmount_1 = require("../../../../types/TokenAmount");
|
|
17
|
+
const Token_1 = require("../../../../types/Token");
|
|
18
|
+
const Logger_1 = require("../../../../utils/Logger");
|
|
19
|
+
const TimeoutUtils_1 = require("../../../../utils/TimeoutUtils");
|
|
20
|
+
const LNURLWithdraw_1 = require("../../../../types/lnurl/LNURLWithdraw");
|
|
21
|
+
const PriceInfoType_1 = require("../../../../types/PriceInfoType");
|
|
22
|
+
/**
|
|
23
|
+
* State enum for FromBTCLNAuto swaps
|
|
24
|
+
* @category Swaps
|
|
25
|
+
*/
|
|
26
|
+
var FromBTCLNAutoSwapState;
|
|
27
|
+
(function (FromBTCLNAutoSwapState) {
|
|
28
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["FAILED"] = -4] = "FAILED";
|
|
29
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["QUOTE_EXPIRED"] = -3] = "QUOTE_EXPIRED";
|
|
30
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["QUOTE_SOFT_EXPIRED"] = -2] = "QUOTE_SOFT_EXPIRED";
|
|
31
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["EXPIRED"] = -1] = "EXPIRED";
|
|
32
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["PR_CREATED"] = 0] = "PR_CREATED";
|
|
33
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["PR_PAID"] = 1] = "PR_PAID";
|
|
34
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["CLAIM_COMMITED"] = 2] = "CLAIM_COMMITED";
|
|
35
|
+
FromBTCLNAutoSwapState[FromBTCLNAutoSwapState["CLAIM_CLAIMED"] = 3] = "CLAIM_CLAIMED";
|
|
36
|
+
})(FromBTCLNAutoSwapState = exports.FromBTCLNAutoSwapState || (exports.FromBTCLNAutoSwapState = {}));
|
|
37
|
+
function isFromBTCLNAutoSwapInit(obj) {
|
|
38
|
+
return typeof obj.pr === "string" &&
|
|
39
|
+
typeof obj.secret === "string" &&
|
|
40
|
+
typeof obj.btcAmountSwap === "bigint" &&
|
|
41
|
+
typeof obj.btcAmountGas === "bigint" &&
|
|
42
|
+
typeof obj.gasSwapFeeBtc === "bigint" &&
|
|
43
|
+
typeof obj.gasSwapFee === "bigint" &&
|
|
44
|
+
(obj.gasPricingInfo == null || (0, PriceInfoType_1.isPriceInfoType)(obj.gasPricingInfo)) &&
|
|
45
|
+
(obj.lnurl == null || typeof (obj.lnurl) === "string") &&
|
|
46
|
+
(obj.lnurlK1 == null || typeof (obj.lnurlK1) === "string") &&
|
|
47
|
+
(obj.lnurlCallback == null || typeof (obj.lnurlCallback) === "string") &&
|
|
48
|
+
(0, IEscrowSwap_1.isIEscrowSwapInit)(obj);
|
|
49
|
+
}
|
|
50
|
+
exports.isFromBTCLNAutoSwapInit = isFromBTCLNAutoSwapInit;
|
|
51
|
+
class FromBTCLNAutoSwap extends IEscrowSwap_1.IEscrowSwap {
|
|
52
|
+
getSwapData() {
|
|
53
|
+
return this.data ?? this.initialSwapData;
|
|
54
|
+
}
|
|
55
|
+
constructor(wrapper, initOrObject) {
|
|
56
|
+
if (isFromBTCLNAutoSwapInit(initOrObject) && initOrObject.url != null)
|
|
57
|
+
initOrObject.url += "/frombtcln_auto";
|
|
58
|
+
super(wrapper, initOrObject);
|
|
59
|
+
this.inputToken = Token_1.BitcoinTokens.BTCLN;
|
|
60
|
+
this.TYPE = SwapType_1.SwapType.FROM_BTCLN_AUTO;
|
|
61
|
+
this.lnurlFailSignal = new AbortController();
|
|
62
|
+
this.prPosted = false;
|
|
63
|
+
this.broadcastTickCounter = 0;
|
|
64
|
+
if (isFromBTCLNAutoSwapInit(initOrObject)) {
|
|
65
|
+
this.state = FromBTCLNAutoSwapState.PR_CREATED;
|
|
66
|
+
this.pr = initOrObject.pr;
|
|
67
|
+
this.secret = initOrObject.secret;
|
|
68
|
+
this.initialSwapData = initOrObject.initialSwapData;
|
|
69
|
+
this.btcAmountSwap = initOrObject.btcAmountSwap;
|
|
70
|
+
this.btcAmountGas = initOrObject.btcAmountGas;
|
|
71
|
+
this.gasSwapFeeBtc = initOrObject.gasSwapFeeBtc;
|
|
72
|
+
this.gasSwapFee = initOrObject.gasSwapFee;
|
|
73
|
+
this.gasPricingInfo = initOrObject.gasPricingInfo;
|
|
74
|
+
this.lnurl = initOrObject.lnurl;
|
|
75
|
+
this.lnurlK1 = initOrObject.lnurlK1;
|
|
76
|
+
this.lnurlCallback = initOrObject.lnurlCallback;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.pr = initOrObject.pr;
|
|
80
|
+
this.secret = initOrObject.secret;
|
|
81
|
+
if (initOrObject.initialSwapData == null) {
|
|
82
|
+
this.initialSwapData = this.data;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.initialSwapData = base_1.SwapData.deserialize(initOrObject.initialSwapData);
|
|
86
|
+
}
|
|
87
|
+
this.btcAmountSwap = (0, Utils_1.toBigInt)(initOrObject.btcAmountSwap);
|
|
88
|
+
this.btcAmountGas = (0, Utils_1.toBigInt)(initOrObject.btcAmountGas);
|
|
89
|
+
this.gasSwapFeeBtc = (0, Utils_1.toBigInt)(initOrObject.gasSwapFeeBtc);
|
|
90
|
+
this.gasSwapFee = (0, Utils_1.toBigInt)(initOrObject.gasSwapFee);
|
|
91
|
+
this.gasPricingInfo = (0, PriceInfoType_1.deserializePriceInfoType)(initOrObject.gasPricingInfo);
|
|
92
|
+
this.commitTxId = initOrObject.commitTxId;
|
|
93
|
+
this.claimTxId = initOrObject.claimTxId;
|
|
94
|
+
this.lnurl = initOrObject.lnurl;
|
|
95
|
+
this.lnurlK1 = initOrObject.lnurlK1;
|
|
96
|
+
this.lnurlCallback = initOrObject.lnurlCallback;
|
|
97
|
+
this.prPosted = initOrObject.prPosted;
|
|
98
|
+
}
|
|
99
|
+
this.tryRecomputeSwapPrice();
|
|
100
|
+
this.logger = (0, Logger_1.getLogger)("FromBTCLNAuto(" + this.getIdentifierHashString() + "): ");
|
|
101
|
+
}
|
|
102
|
+
upgradeVersion() { }
|
|
103
|
+
/**
|
|
104
|
+
* In case swapFee in BTC is not supplied it recalculates it based on swap price
|
|
105
|
+
* @protected
|
|
106
|
+
*/
|
|
107
|
+
tryRecomputeSwapPrice() {
|
|
108
|
+
if (this.pricingInfo == null)
|
|
109
|
+
return;
|
|
110
|
+
if (this.pricingInfo.swapPriceUSatPerToken == null) {
|
|
111
|
+
const priceUsdPerBtc = this.pricingInfo.realPriceUsdPerBitcoin;
|
|
112
|
+
this.pricingInfo = this.wrapper.prices.recomputePriceInfoReceive(this.chainIdentifier, this.btcAmountSwap, this.pricingInfo.satsBaseFee, this.pricingInfo.feePPM, this.getOutputAmountWithoutFee(), this.getSwapData().getToken());
|
|
113
|
+
this.pricingInfo.realPriceUsdPerBitcoin = priceUsdPerBtc;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//////////////////////////////
|
|
117
|
+
//// Pricing
|
|
118
|
+
async refreshPriceData() {
|
|
119
|
+
if (this.pricingInfo == null)
|
|
120
|
+
return;
|
|
121
|
+
const usdPricePerBtc = this.pricingInfo.realPriceUsdPerBitcoin;
|
|
122
|
+
this.pricingInfo = await this.wrapper.prices.isValidAmountReceive(this.chainIdentifier, this.btcAmountSwap, this.pricingInfo.satsBaseFee, this.pricingInfo.feePPM, this.getOutputAmountWithoutFee(), this.getSwapData().getToken());
|
|
123
|
+
this.pricingInfo.realPriceUsdPerBitcoin = usdPricePerBtc;
|
|
124
|
+
}
|
|
125
|
+
//////////////////////////////
|
|
126
|
+
//// Getters & utils
|
|
127
|
+
_getEscrowHash() {
|
|
128
|
+
//Use claim hash in case the data is not yet known
|
|
129
|
+
return this.data == null ? this.initialSwapData?.getClaimHash() : this.data?.getEscrowHash();
|
|
130
|
+
}
|
|
131
|
+
_getInitiator() {
|
|
132
|
+
return this.getSwapData().getClaimer();
|
|
133
|
+
}
|
|
134
|
+
getId() {
|
|
135
|
+
return this.getIdentifierHashString();
|
|
136
|
+
}
|
|
137
|
+
getOutputAddress() {
|
|
138
|
+
return this._getInitiator();
|
|
139
|
+
}
|
|
140
|
+
getOutputTxId() {
|
|
141
|
+
return this.claimTxId ?? null;
|
|
142
|
+
}
|
|
143
|
+
requiresAction() {
|
|
144
|
+
return this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
145
|
+
}
|
|
146
|
+
getIdentifierHashString() {
|
|
147
|
+
const paymentHashBuffer = this.getPaymentHash();
|
|
148
|
+
if (this.randomNonce == null)
|
|
149
|
+
return paymentHashBuffer?.toString("hex");
|
|
150
|
+
return paymentHashBuffer.toString("hex") + this.randomNonce;
|
|
151
|
+
}
|
|
152
|
+
getPaymentHash() {
|
|
153
|
+
const decodedPR = (0, bolt11_1.decode)(this.pr);
|
|
154
|
+
if (decodedPR.tagsObject.payment_hash == null)
|
|
155
|
+
throw new Error("Swap invoice doesn't contain payment hash field!");
|
|
156
|
+
return buffer_1.Buffer.from(decodedPR.tagsObject.payment_hash, "hex");
|
|
157
|
+
}
|
|
158
|
+
getInputAddress() {
|
|
159
|
+
return this.lnurl ?? this.pr;
|
|
160
|
+
}
|
|
161
|
+
getInputTxId() {
|
|
162
|
+
return this.getPaymentHash().toString("hex");
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Returns the lightning network BOLT11 invoice that needs to be paid as an input to the swap
|
|
166
|
+
*/
|
|
167
|
+
getAddress() {
|
|
168
|
+
return this.pr;
|
|
169
|
+
}
|
|
170
|
+
getHyperlink() {
|
|
171
|
+
return "lightning:" + this.pr.toUpperCase();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Returns the timeout time (in UNIX milliseconds) when the swap will definitelly be considered as expired
|
|
175
|
+
* if the LP doesn't make it expired sooner
|
|
176
|
+
*/
|
|
177
|
+
getDefinitiveExpiryTime() {
|
|
178
|
+
const decoded = (0, bolt11_1.decode)(this.pr);
|
|
179
|
+
if (decoded.tagsObject.min_final_cltv_expiry == null)
|
|
180
|
+
throw new Error("Swap invoice doesn't contain final ctlv delta field!");
|
|
181
|
+
if (decoded.timeExpireDate == null)
|
|
182
|
+
throw new Error("Swap invoice doesn't contain expiry date field!");
|
|
183
|
+
const finalCltvExpiryDelta = decoded.tagsObject.min_final_cltv_expiry ?? 144;
|
|
184
|
+
const finalCltvExpiryDelay = finalCltvExpiryDelta * this.wrapper.options.bitcoinBlocktime * this.wrapper.options.safetyFactor;
|
|
185
|
+
return (decoded.timeExpireDate + finalCltvExpiryDelay) * 1000;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Returns timeout time (in UNIX milliseconds) when the swap htlc will expire
|
|
189
|
+
*/
|
|
190
|
+
getHtlcTimeoutTime() {
|
|
191
|
+
return this.data == null ? null : Number(this.wrapper.getHtlcTimeout(this.data)) * 1000;
|
|
192
|
+
}
|
|
193
|
+
isFinished() {
|
|
194
|
+
return this.state === FromBTCLNAutoSwapState.CLAIM_CLAIMED || this.state === FromBTCLNAutoSwapState.QUOTE_EXPIRED || this.state === FromBTCLNAutoSwapState.FAILED;
|
|
195
|
+
}
|
|
196
|
+
isClaimable() {
|
|
197
|
+
return this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
198
|
+
}
|
|
199
|
+
isSuccessful() {
|
|
200
|
+
return this.state === FromBTCLNAutoSwapState.CLAIM_CLAIMED;
|
|
201
|
+
}
|
|
202
|
+
isFailed() {
|
|
203
|
+
return this.state === FromBTCLNAutoSwapState.FAILED || this.state === FromBTCLNAutoSwapState.EXPIRED;
|
|
204
|
+
}
|
|
205
|
+
isQuoteExpired() {
|
|
206
|
+
return this.state === FromBTCLNAutoSwapState.QUOTE_EXPIRED;
|
|
207
|
+
}
|
|
208
|
+
isQuoteSoftExpired() {
|
|
209
|
+
return this.state === FromBTCLNAutoSwapState.QUOTE_EXPIRED;
|
|
210
|
+
}
|
|
211
|
+
_verifyQuoteDefinitelyExpired() {
|
|
212
|
+
return Promise.resolve(this.getDefinitiveExpiryTime() < Date.now());
|
|
213
|
+
}
|
|
214
|
+
verifyQuoteValid() {
|
|
215
|
+
return Promise.resolve(this.getQuoteExpiry() > Date.now());
|
|
216
|
+
}
|
|
217
|
+
//////////////////////////////
|
|
218
|
+
//// Amounts & fees
|
|
219
|
+
getLightningInvoiceSats() {
|
|
220
|
+
const parsed = (0, bolt11_1.decode)(this.pr);
|
|
221
|
+
if (parsed.millisatoshis == null)
|
|
222
|
+
throw new Error("Swap invoice doesn't contain msat amount field!");
|
|
223
|
+
return (BigInt(parsed.millisatoshis) + 999n) / 1000n;
|
|
224
|
+
}
|
|
225
|
+
getWatchtowerFeeAmountBtc() {
|
|
226
|
+
return (this.btcAmountGas - this.gasSwapFeeBtc) * this.getSwapData().getClaimerBounty() / this.getSwapData().getTotalDeposit();
|
|
227
|
+
}
|
|
228
|
+
getInputSwapAmountWithoutFee() {
|
|
229
|
+
return this.btcAmountSwap - this.swapFeeBtc;
|
|
230
|
+
}
|
|
231
|
+
getInputGasAmountWithoutFee() {
|
|
232
|
+
return this.btcAmountGas - this.gasSwapFeeBtc;
|
|
233
|
+
}
|
|
234
|
+
getInputAmountWithoutFee() {
|
|
235
|
+
return this.getInputSwapAmountWithoutFee() + this.getInputGasAmountWithoutFee() - this.getWatchtowerFeeAmountBtc();
|
|
236
|
+
}
|
|
237
|
+
getOutputAmountWithoutFee() {
|
|
238
|
+
return this.getSwapData().getAmount() + this.swapFee;
|
|
239
|
+
}
|
|
240
|
+
getInputToken() {
|
|
241
|
+
return Token_1.BitcoinTokens.BTCLN;
|
|
242
|
+
}
|
|
243
|
+
getInput() {
|
|
244
|
+
return (0, TokenAmount_1.toTokenAmount)(this.getLightningInvoiceSats(), this.inputToken, this.wrapper.prices, this.pricingInfo);
|
|
245
|
+
}
|
|
246
|
+
getInputWithoutFee() {
|
|
247
|
+
return (0, TokenAmount_1.toTokenAmount)(this.getInputAmountWithoutFee(), this.inputToken, this.wrapper.prices, this.pricingInfo);
|
|
248
|
+
}
|
|
249
|
+
getOutputToken() {
|
|
250
|
+
return this.wrapper.tokens[this.getSwapData().getToken()];
|
|
251
|
+
}
|
|
252
|
+
getOutput() {
|
|
253
|
+
return (0, TokenAmount_1.toTokenAmount)(this.getSwapData().getAmount(), this.wrapper.tokens[this.getSwapData().getToken()], this.wrapper.prices, this.pricingInfo);
|
|
254
|
+
}
|
|
255
|
+
getGasDropOutput() {
|
|
256
|
+
return (0, TokenAmount_1.toTokenAmount)(this.getSwapData().getSecurityDeposit() - this.getSwapData().getClaimerBounty(), this.wrapper.tokens[this.getSwapData().getDepositToken()], this.wrapper.prices, this.gasPricingInfo);
|
|
257
|
+
}
|
|
258
|
+
getSwapFee() {
|
|
259
|
+
if (this.pricingInfo == null)
|
|
260
|
+
throw new Error("No pricing info known, cannot estimate fee!");
|
|
261
|
+
const outputToken = this.wrapper.tokens[this.getSwapData().getToken()];
|
|
262
|
+
const gasSwapFeeInOutputToken = this.gasSwapFeeBtc
|
|
263
|
+
* (10n ** BigInt(outputToken.decimals))
|
|
264
|
+
* 1000000n
|
|
265
|
+
/ this.pricingInfo.swapPriceUSatPerToken;
|
|
266
|
+
const feeWithoutBaseFee = this.gasSwapFeeBtc + this.swapFeeBtc - this.pricingInfo.satsBaseFee;
|
|
267
|
+
const swapFeePPM = feeWithoutBaseFee * 1000000n / (this.getLightningInvoiceSats() - this.swapFeeBtc - this.gasSwapFeeBtc);
|
|
268
|
+
const amountInSrcToken = (0, TokenAmount_1.toTokenAmount)(this.swapFeeBtc + this.gasSwapFeeBtc, Token_1.BitcoinTokens.BTCLN, this.wrapper.prices, this.pricingInfo);
|
|
269
|
+
return {
|
|
270
|
+
amountInSrcToken,
|
|
271
|
+
amountInDstToken: (0, TokenAmount_1.toTokenAmount)(this.swapFee + gasSwapFeeInOutputToken, outputToken, this.wrapper.prices, this.pricingInfo),
|
|
272
|
+
currentUsdValue: amountInSrcToken.currentUsdValue,
|
|
273
|
+
pastUsdValue: amountInSrcToken.pastUsdValue,
|
|
274
|
+
usdValue: amountInSrcToken.usdValue,
|
|
275
|
+
composition: {
|
|
276
|
+
base: (0, TokenAmount_1.toTokenAmount)(this.pricingInfo.satsBaseFee, Token_1.BitcoinTokens.BTCLN, this.wrapper.prices, this.pricingInfo),
|
|
277
|
+
percentage: (0, PercentagePPM_1.ppmToPercentage)(swapFeePPM)
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
getWatchtowerFee() {
|
|
282
|
+
if (this.pricingInfo == null)
|
|
283
|
+
throw new Error("No pricing info known, cannot estimate fee!");
|
|
284
|
+
const btcWatchtowerFee = this.getWatchtowerFeeAmountBtc();
|
|
285
|
+
const outputToken = this.wrapper.tokens[this.getSwapData().getToken()];
|
|
286
|
+
const watchtowerFeeInOutputToken = btcWatchtowerFee
|
|
287
|
+
* (10n ** BigInt(outputToken.decimals))
|
|
288
|
+
* 1000000n
|
|
289
|
+
/ this.pricingInfo.swapPriceUSatPerToken;
|
|
290
|
+
const amountInSrcToken = (0, TokenAmount_1.toTokenAmount)(btcWatchtowerFee, Token_1.BitcoinTokens.BTCLN, this.wrapper.prices, this.pricingInfo);
|
|
291
|
+
return {
|
|
292
|
+
amountInSrcToken,
|
|
293
|
+
amountInDstToken: (0, TokenAmount_1.toTokenAmount)(watchtowerFeeInOutputToken, outputToken, this.wrapper.prices, this.pricingInfo),
|
|
294
|
+
currentUsdValue: amountInSrcToken.currentUsdValue,
|
|
295
|
+
usdValue: amountInSrcToken.usdValue,
|
|
296
|
+
pastUsdValue: amountInSrcToken.pastUsdValue
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
getFee() {
|
|
300
|
+
const swapFee = this.getSwapFee();
|
|
301
|
+
const watchtowerFee = this.getWatchtowerFee();
|
|
302
|
+
const amountInSrcToken = (0, TokenAmount_1.toTokenAmount)(swapFee.amountInSrcToken.rawAmount + watchtowerFee.amountInSrcToken.rawAmount, Token_1.BitcoinTokens.BTCLN, this.wrapper.prices, this.pricingInfo);
|
|
303
|
+
return {
|
|
304
|
+
amountInSrcToken,
|
|
305
|
+
amountInDstToken: (0, TokenAmount_1.toTokenAmount)(swapFee.amountInDstToken.rawAmount + watchtowerFee.amountInDstToken.rawAmount, this.wrapper.tokens[this.getSwapData().getToken()], this.wrapper.prices, this.pricingInfo),
|
|
306
|
+
currentUsdValue: amountInSrcToken.currentUsdValue,
|
|
307
|
+
usdValue: amountInSrcToken.usdValue,
|
|
308
|
+
pastUsdValue: amountInSrcToken.pastUsdValue
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
getFeeBreakdown() {
|
|
312
|
+
return [
|
|
313
|
+
{
|
|
314
|
+
type: FeeType_1.FeeType.SWAP,
|
|
315
|
+
fee: this.getSwapFee()
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
type: FeeType_1.FeeType.NETWORK_OUTPUT,
|
|
319
|
+
fee: this.getWatchtowerFee()
|
|
320
|
+
}
|
|
321
|
+
];
|
|
322
|
+
}
|
|
323
|
+
//////////////////////////////
|
|
324
|
+
//// Execution
|
|
325
|
+
/**
|
|
326
|
+
* Executes the swap with the provided bitcoin lightning network wallet or LNURL
|
|
327
|
+
*
|
|
328
|
+
* @param walletOrLnurlWithdraw Bitcoin lightning wallet to use to pay the lightning network invoice, or an LNURL-withdraw
|
|
329
|
+
* link, wallet is not required and the LN invoice can be paid externally as well (just pass null or undefined here)
|
|
330
|
+
* @param callbacks Callbacks to track the progress of the swap
|
|
331
|
+
* @param options Optional options for the swap like feeRate, AbortSignal, and timeouts/intervals
|
|
332
|
+
*
|
|
333
|
+
* @returns {boolean} Whether a swap was settled automatically by swap watchtowers or requires manual claim by the
|
|
334
|
+
* user, in case `false` is returned the user should call `swap.claim()` to settle the swap on the destination manually
|
|
335
|
+
*/
|
|
336
|
+
async execute(walletOrLnurlWithdraw, callbacks, options) {
|
|
337
|
+
if (this.state === FromBTCLNAutoSwapState.FAILED)
|
|
338
|
+
throw new Error("Swap failed!");
|
|
339
|
+
if (this.state === FromBTCLNAutoSwapState.EXPIRED)
|
|
340
|
+
throw new Error("Swap HTLC expired!");
|
|
341
|
+
if (this.state === FromBTCLNAutoSwapState.QUOTE_EXPIRED || this.state === FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED)
|
|
342
|
+
throw new Error("Swap quote expired!");
|
|
343
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_CLAIMED)
|
|
344
|
+
throw new Error("Swap already settled!");
|
|
345
|
+
let abortSignal = options?.abortSignal;
|
|
346
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED) {
|
|
347
|
+
if (walletOrLnurlWithdraw != null && this.lnurl == null) {
|
|
348
|
+
if (typeof (walletOrLnurlWithdraw) === "string" || (0, LNURLWithdraw_1.isLNURLWithdraw)(walletOrLnurlWithdraw)) {
|
|
349
|
+
await this.settleWithLNURLWithdraw(walletOrLnurlWithdraw);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
const paymentPromise = walletOrLnurlWithdraw.payInvoice(this.pr);
|
|
353
|
+
const abortController = new AbortController();
|
|
354
|
+
paymentPromise.catch(e => abortController.abort(e));
|
|
355
|
+
if (options?.abortSignal != null)
|
|
356
|
+
options.abortSignal.addEventListener("abort", () => abortController.abort(options?.abortSignal?.reason));
|
|
357
|
+
abortSignal = abortController.signal;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED || this.state === FromBTCLNAutoSwapState.PR_PAID) {
|
|
362
|
+
const paymentSuccess = await this.waitForPayment(callbacks?.onSourceTransactionReceived, options?.lightningTxCheckIntervalSeconds, abortSignal);
|
|
363
|
+
if (!paymentSuccess)
|
|
364
|
+
throw new Error("Failed to receive lightning network payment");
|
|
365
|
+
}
|
|
366
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_CLAIMED)
|
|
367
|
+
return true;
|
|
368
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED) {
|
|
369
|
+
const success = await this.waitTillClaimed(options?.maxWaitTillAutomaticSettlementSeconds ?? 60, options?.abortSignal);
|
|
370
|
+
if (success && callbacks?.onSwapSettled != null)
|
|
371
|
+
callbacks.onSwapSettled(this.getOutputTxId());
|
|
372
|
+
return success;
|
|
373
|
+
}
|
|
374
|
+
throw new Error("Invalid state reached!");
|
|
375
|
+
}
|
|
376
|
+
async txsExecute() {
|
|
377
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED) {
|
|
378
|
+
if (!await this.verifyQuoteValid())
|
|
379
|
+
throw new Error("Quote already expired or close to expiry!");
|
|
380
|
+
return [
|
|
381
|
+
{
|
|
382
|
+
name: "Payment",
|
|
383
|
+
description: "Initiates the swap by paying up the lightning network invoice",
|
|
384
|
+
chain: "LIGHTNING",
|
|
385
|
+
txs: [
|
|
386
|
+
{
|
|
387
|
+
address: this.pr,
|
|
388
|
+
hyperlink: this.getHyperlink()
|
|
389
|
+
}
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
];
|
|
393
|
+
}
|
|
394
|
+
throw new Error("Invalid swap state to obtain execution txns, required PR_CREATED");
|
|
395
|
+
}
|
|
396
|
+
//////////////////////////////
|
|
397
|
+
//// Payment
|
|
398
|
+
/**
|
|
399
|
+
* Checks whether the LP received the LN payment and we can continue by committing & claiming the HTLC on-chain
|
|
400
|
+
*
|
|
401
|
+
* @param save If the new swap state should be saved
|
|
402
|
+
*/
|
|
403
|
+
async _checkIntermediaryPaymentReceived(save = true) {
|
|
404
|
+
if (this.state === FromBTCLNAutoSwapState.PR_PAID ||
|
|
405
|
+
this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED ||
|
|
406
|
+
this.state === FromBTCLNAutoSwapState.CLAIM_CLAIMED ||
|
|
407
|
+
this.state === FromBTCLNAutoSwapState.FAILED)
|
|
408
|
+
return true;
|
|
409
|
+
if (this.state === FromBTCLNAutoSwapState.QUOTE_EXPIRED)
|
|
410
|
+
return false;
|
|
411
|
+
if (this.url == null)
|
|
412
|
+
return false;
|
|
413
|
+
const resp = await IntermediaryAPI_1.IntermediaryAPI.getInvoiceStatus(this.url, this.getPaymentHash().toString("hex"));
|
|
414
|
+
switch (resp.code) {
|
|
415
|
+
case IntermediaryAPI_1.InvoiceStatusResponseCodes.PAID:
|
|
416
|
+
const data = new this.wrapper.swapDataDeserializer(resp.data.data);
|
|
417
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED || this.state === FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED)
|
|
418
|
+
try {
|
|
419
|
+
await this._saveRealSwapData(data, save);
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
catch (e) { }
|
|
423
|
+
return null;
|
|
424
|
+
case IntermediaryAPI_1.InvoiceStatusResponseCodes.EXPIRED:
|
|
425
|
+
this.state = FromBTCLNAutoSwapState.QUOTE_EXPIRED;
|
|
426
|
+
this.initiated = true;
|
|
427
|
+
if (save)
|
|
428
|
+
await this._saveAndEmit();
|
|
429
|
+
return false;
|
|
430
|
+
default:
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async _saveRealSwapData(data, save) {
|
|
435
|
+
await this.checkIntermediaryReturnedData(data);
|
|
436
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED || this.state === FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED) {
|
|
437
|
+
this.state = FromBTCLNAutoSwapState.PR_PAID;
|
|
438
|
+
this.data = data;
|
|
439
|
+
this.initiated = true;
|
|
440
|
+
if (save)
|
|
441
|
+
await this._saveAndEmit();
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Checks the data returned by the intermediary in the payment auth request
|
|
448
|
+
*
|
|
449
|
+
* @param data Parsed swap data as returned by the intermediary
|
|
450
|
+
* @protected
|
|
451
|
+
* @throws {IntermediaryError} If the returned are not valid
|
|
452
|
+
* @throws {Error} If the swap is already committed on-chain
|
|
453
|
+
*/
|
|
454
|
+
async checkIntermediaryReturnedData(data) {
|
|
455
|
+
if (!data.isPayOut())
|
|
456
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid not pay out");
|
|
457
|
+
if (data.getType() !== base_1.ChainSwapType.HTLC)
|
|
458
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid swap type");
|
|
459
|
+
if (!data.isOfferer(this.getSwapData().getOfferer()))
|
|
460
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid offerer used");
|
|
461
|
+
if (!data.isClaimer(this._getInitiator()))
|
|
462
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid claimer used");
|
|
463
|
+
if (!data.isToken(this.getSwapData().getToken()))
|
|
464
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid token used");
|
|
465
|
+
if (data.getSecurityDeposit() !== this.getSwapData().getSecurityDeposit())
|
|
466
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid security deposit!");
|
|
467
|
+
if (data.getClaimerBounty() !== this.getSwapData().getClaimerBounty())
|
|
468
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid security deposit!");
|
|
469
|
+
if (data.getAmount() < this.getSwapData().getAmount())
|
|
470
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid amount received!");
|
|
471
|
+
if (data.getClaimHash() !== this.getSwapData().getClaimHash())
|
|
472
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid payment hash used!");
|
|
473
|
+
if (!data.isDepositToken(this.getSwapData().getDepositToken()))
|
|
474
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid deposit token used!");
|
|
475
|
+
if (data.hasSuccessAction())
|
|
476
|
+
throw new IntermediaryError_1.IntermediaryError("Invalid has success action");
|
|
477
|
+
if (await this.wrapper.contract.isExpired(this._getInitiator(), data))
|
|
478
|
+
throw new IntermediaryError_1.IntermediaryError("Not enough time to claim!");
|
|
479
|
+
if (this.wrapper.getHtlcTimeout(data) <= (Date.now() / 1000))
|
|
480
|
+
throw new IntermediaryError_1.IntermediaryError("HTLC expires too soon!");
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Waits till an LN payment is received by the intermediary and client can continue commiting & claiming the HTLC
|
|
484
|
+
*
|
|
485
|
+
* @param onPaymentReceived Callback as for when the LP reports having received the ln payment
|
|
486
|
+
* @param checkIntervalSeconds How often to poll the intermediary for answer (default 5 seconds)
|
|
487
|
+
* @param abortSignal Abort signal to stop waiting for payment
|
|
488
|
+
*/
|
|
489
|
+
async waitForPayment(onPaymentReceived, checkIntervalSeconds, abortSignal) {
|
|
490
|
+
checkIntervalSeconds ??= 5;
|
|
491
|
+
if (this.state === FromBTCLNAutoSwapState.PR_PAID) {
|
|
492
|
+
await this.waitTillCommited(checkIntervalSeconds, abortSignal);
|
|
493
|
+
}
|
|
494
|
+
if (this.state >= FromBTCLNAutoSwapState.CLAIM_COMMITED)
|
|
495
|
+
return true;
|
|
496
|
+
if (this.state !== FromBTCLNAutoSwapState.PR_CREATED)
|
|
497
|
+
throw new Error("Must be in PR_CREATED state!");
|
|
498
|
+
const abortController = new AbortController();
|
|
499
|
+
if (abortSignal != null)
|
|
500
|
+
abortSignal.addEventListener("abort", () => abortController.abort(abortSignal.reason));
|
|
501
|
+
let save = false;
|
|
502
|
+
if (this.lnurl != null && this.lnurlK1 != null && this.lnurlCallback != null && !this.prPosted) {
|
|
503
|
+
LNURL_1.LNURL.postInvoiceToLNURLWithdraw({ k1: this.lnurlK1, callback: this.lnurlCallback }, this.pr).catch(e => {
|
|
504
|
+
this.lnurlFailSignal.abort(e);
|
|
505
|
+
});
|
|
506
|
+
this.prPosted = true;
|
|
507
|
+
save ||= true;
|
|
508
|
+
}
|
|
509
|
+
if (!this.initiated) {
|
|
510
|
+
this.initiated = true;
|
|
511
|
+
save ||= true;
|
|
512
|
+
}
|
|
513
|
+
if (save)
|
|
514
|
+
await this._saveAndEmit();
|
|
515
|
+
let lnurlFailListener = () => abortController.abort(this.lnurlFailSignal.signal.reason);
|
|
516
|
+
this.lnurlFailSignal.signal.addEventListener("abort", lnurlFailListener);
|
|
517
|
+
this.lnurlFailSignal.signal.throwIfAborted();
|
|
518
|
+
if (this.wrapper.messenger.warmup != null)
|
|
519
|
+
await this.wrapper.messenger.warmup().catch(e => {
|
|
520
|
+
this.logger.warn("waitForPayment(): Failed to warmup messenger: ", e);
|
|
521
|
+
});
|
|
522
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED) {
|
|
523
|
+
const promises = [
|
|
524
|
+
this.waitTillState(FromBTCLNAutoSwapState.PR_PAID, "gte", abortController.signal).then(() => true)
|
|
525
|
+
];
|
|
526
|
+
if (this.url != null)
|
|
527
|
+
promises.push((async () => {
|
|
528
|
+
let resp = { code: IntermediaryAPI_1.InvoiceStatusResponseCodes.PENDING, msg: "" };
|
|
529
|
+
while (!abortController.signal.aborted && resp.code === IntermediaryAPI_1.InvoiceStatusResponseCodes.PENDING) {
|
|
530
|
+
resp = await IntermediaryAPI_1.IntermediaryAPI.getInvoiceStatus(this.url, this.getPaymentHash().toString("hex"));
|
|
531
|
+
if (resp.code === IntermediaryAPI_1.InvoiceStatusResponseCodes.PENDING)
|
|
532
|
+
await (0, TimeoutUtils_1.timeoutPromise)(checkIntervalSeconds * 1000, abortController.signal);
|
|
533
|
+
}
|
|
534
|
+
this.lnurlFailSignal.signal.removeEventListener("abort", lnurlFailListener);
|
|
535
|
+
abortController.signal.throwIfAborted();
|
|
536
|
+
if (resp.code === IntermediaryAPI_1.InvoiceStatusResponseCodes.PAID) {
|
|
537
|
+
const swapData = new this.wrapper.swapDataDeserializer(resp.data.data);
|
|
538
|
+
return await this._saveRealSwapData(swapData, true);
|
|
539
|
+
}
|
|
540
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED || this.state === FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED) {
|
|
541
|
+
if (resp.code === IntermediaryAPI_1.InvoiceStatusResponseCodes.EXPIRED) {
|
|
542
|
+
await this._saveAndEmit(FromBTCLNAutoSwapState.QUOTE_EXPIRED);
|
|
543
|
+
}
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
})());
|
|
547
|
+
const paymentResult = await Promise.race(promises);
|
|
548
|
+
abortController.abort();
|
|
549
|
+
if (!paymentResult)
|
|
550
|
+
return false;
|
|
551
|
+
if (onPaymentReceived != null)
|
|
552
|
+
onPaymentReceived(this.getInputTxId());
|
|
553
|
+
}
|
|
554
|
+
if (this.state === FromBTCLNAutoSwapState.PR_PAID) {
|
|
555
|
+
await this.waitTillCommited(checkIntervalSeconds, abortSignal);
|
|
556
|
+
}
|
|
557
|
+
return this.state >= FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
558
|
+
}
|
|
559
|
+
//////////////////////////////
|
|
560
|
+
//// Commit
|
|
561
|
+
async waitTillCommited(checkIntervalSeconds, abortSignal) {
|
|
562
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED || this.state === FromBTCLNAutoSwapState.CLAIM_CLAIMED)
|
|
563
|
+
return Promise.resolve();
|
|
564
|
+
if (this.state !== FromBTCLNAutoSwapState.PR_PAID)
|
|
565
|
+
throw new Error("Invalid state");
|
|
566
|
+
const abortController = (0, Utils_1.extendAbortController)(abortSignal);
|
|
567
|
+
let result;
|
|
568
|
+
try {
|
|
569
|
+
result = await Promise.race([
|
|
570
|
+
this.watchdogWaitTillCommited(checkIntervalSeconds, abortController.signal),
|
|
571
|
+
this.waitTillState(FromBTCLNAutoSwapState.CLAIM_COMMITED, "gte", abortController.signal).then(() => 0)
|
|
572
|
+
]);
|
|
573
|
+
abortController.abort();
|
|
574
|
+
}
|
|
575
|
+
catch (e) {
|
|
576
|
+
abortController.abort();
|
|
577
|
+
throw e;
|
|
578
|
+
}
|
|
579
|
+
if (result === false) {
|
|
580
|
+
this.logger.debug("waitTillCommited(): Resolved from watchdog - HTLC expired");
|
|
581
|
+
if (this.state === FromBTCLNAutoSwapState.PR_PAID) {
|
|
582
|
+
await this._saveAndEmit(FromBTCLNAutoSwapState.EXPIRED);
|
|
583
|
+
}
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
if (this.state === FromBTCLNAutoSwapState.PR_PAID) {
|
|
587
|
+
await this._saveAndEmit(FromBTCLNAutoSwapState.CLAIM_COMMITED);
|
|
588
|
+
}
|
|
589
|
+
if (result === 0)
|
|
590
|
+
this.logger.debug("waitTillCommited(): Resolved from state changed");
|
|
591
|
+
if (result === true) {
|
|
592
|
+
this.logger.debug("waitTillCommited(): Resolved from watchdog - commited");
|
|
593
|
+
await this._broadcastSecret().catch(e => {
|
|
594
|
+
this.logger.error("waitTillCommited(): Error broadcasting swap secret: ", e);
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
//////////////////////////////
|
|
599
|
+
//// Claim
|
|
600
|
+
/**
|
|
601
|
+
* Returns transactions required for claiming the HTLC and finishing the swap by revealing the HTLC secret
|
|
602
|
+
* (hash preimage)
|
|
603
|
+
*
|
|
604
|
+
* @param _signer Optional signer address to use for claiming the swap, can also be different from the initializer
|
|
605
|
+
* @throws {Error} If in invalid state (must be CLAIM_COMMITED)
|
|
606
|
+
*/
|
|
607
|
+
async txsClaim(_signer) {
|
|
608
|
+
if (this.state !== FromBTCLNAutoSwapState.CLAIM_COMMITED)
|
|
609
|
+
throw new Error("Must be in CLAIM_COMMITED state!");
|
|
610
|
+
if (this.data == null)
|
|
611
|
+
throw new Error("Unknown data, wrong state?");
|
|
612
|
+
return await this.wrapper.contract.txsClaimWithSecret(_signer == null ?
|
|
613
|
+
this._getInitiator() :
|
|
614
|
+
((0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper.chain.wrapSigner(_signer)), this.data, this.secret, true, true);
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Claims and finishes the swap
|
|
618
|
+
*
|
|
619
|
+
* @param _signer Signer to sign the transactions with, can also be different to the initializer
|
|
620
|
+
* @param abortSignal Abort signal to stop waiting for transaction confirmation
|
|
621
|
+
*/
|
|
622
|
+
async claim(_signer, abortSignal) {
|
|
623
|
+
const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper.chain.wrapSigner(_signer);
|
|
624
|
+
const result = await this.wrapper.chain.sendAndConfirm(signer, await this.txsClaim(), true, abortSignal);
|
|
625
|
+
this.claimTxId = result[0];
|
|
626
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED || this.state === FromBTCLNAutoSwapState.EXPIRED || this.state === FromBTCLNAutoSwapState.FAILED) {
|
|
627
|
+
await this._saveAndEmit(FromBTCLNAutoSwapState.CLAIM_CLAIMED);
|
|
628
|
+
}
|
|
629
|
+
return result[0];
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Waits till the swap is successfully claimed
|
|
633
|
+
*
|
|
634
|
+
* @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled
|
|
635
|
+
* @param abortSignal AbortSignal
|
|
636
|
+
* @throws {Error} If swap is in invalid state (must be BTC_TX_CONFIRMED)
|
|
637
|
+
* @throws {Error} If the LP refunded sooner than we were able to claim
|
|
638
|
+
* @returns {boolean} whether the swap was claimed in time or not
|
|
639
|
+
*/
|
|
640
|
+
async waitTillClaimed(maxWaitTimeSeconds, abortSignal) {
|
|
641
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_CLAIMED)
|
|
642
|
+
return Promise.resolve(true);
|
|
643
|
+
if (this.state !== FromBTCLNAutoSwapState.CLAIM_COMMITED)
|
|
644
|
+
throw new Error("Invalid state (not CLAIM_COMMITED)");
|
|
645
|
+
const abortController = new AbortController();
|
|
646
|
+
if (abortSignal != null)
|
|
647
|
+
abortSignal.addEventListener("abort", () => abortController.abort(abortSignal.reason));
|
|
648
|
+
let timedOut = false;
|
|
649
|
+
if (maxWaitTimeSeconds != null) {
|
|
650
|
+
const timeout = setTimeout(() => {
|
|
651
|
+
timedOut = true;
|
|
652
|
+
abortController.abort();
|
|
653
|
+
}, maxWaitTimeSeconds * 1000);
|
|
654
|
+
abortController.signal.addEventListener("abort", () => clearTimeout(timeout));
|
|
655
|
+
}
|
|
656
|
+
let res;
|
|
657
|
+
try {
|
|
658
|
+
res = await Promise.race([
|
|
659
|
+
this.watchdogWaitTillResult(undefined, abortController.signal),
|
|
660
|
+
this.waitTillState(FromBTCLNAutoSwapState.CLAIM_CLAIMED, "eq", abortController.signal).then(() => 0),
|
|
661
|
+
this.waitTillState(FromBTCLNAutoSwapState.EXPIRED, "eq", abortController.signal).then(() => 1),
|
|
662
|
+
]);
|
|
663
|
+
abortController.abort();
|
|
664
|
+
}
|
|
665
|
+
catch (e) {
|
|
666
|
+
abortController.abort();
|
|
667
|
+
if (timedOut)
|
|
668
|
+
return false;
|
|
669
|
+
throw e;
|
|
670
|
+
}
|
|
671
|
+
if (res === 0) {
|
|
672
|
+
this.logger.debug("waitTillClaimed(): Resolved from state change (CLAIM_CLAIMED)");
|
|
673
|
+
return true;
|
|
674
|
+
}
|
|
675
|
+
if (res === 1) {
|
|
676
|
+
this.logger.debug("waitTillClaimed(): Resolved from state change (EXPIRED)");
|
|
677
|
+
throw new Error("Swap expired during claiming");
|
|
678
|
+
}
|
|
679
|
+
this.logger.debug("waitTillClaimed(): Resolved from watchdog");
|
|
680
|
+
if (res?.type === base_1.SwapCommitStateType.PAID) {
|
|
681
|
+
if (this.state !== FromBTCLNAutoSwapState.CLAIM_CLAIMED) {
|
|
682
|
+
this.claimTxId = await res.getClaimTxId();
|
|
683
|
+
await this._saveAndEmit(FromBTCLNAutoSwapState.CLAIM_CLAIMED);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
if (res?.type === base_1.SwapCommitStateType.NOT_COMMITED || res?.type === base_1.SwapCommitStateType.EXPIRED) {
|
|
687
|
+
if (this.state !== FromBTCLNAutoSwapState.CLAIM_CLAIMED &&
|
|
688
|
+
this.state !== FromBTCLNAutoSwapState.FAILED) {
|
|
689
|
+
await this._saveAndEmit(FromBTCLNAutoSwapState.FAILED);
|
|
690
|
+
}
|
|
691
|
+
throw new Error("Swap expired during claiming");
|
|
692
|
+
}
|
|
693
|
+
return true;
|
|
694
|
+
}
|
|
695
|
+
//////////////////////////////
|
|
696
|
+
//// LNURL
|
|
697
|
+
/**
|
|
698
|
+
* Is this an LNURL-withdraw swap?
|
|
699
|
+
*/
|
|
700
|
+
isLNURL() {
|
|
701
|
+
return this.lnurl != null;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Gets the used LNURL or null if this is not an LNURL-withdraw swap
|
|
705
|
+
*/
|
|
706
|
+
getLNURL() {
|
|
707
|
+
return this.lnurl ?? null;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Pay the generated lightning network invoice with LNURL-withdraw
|
|
711
|
+
*/
|
|
712
|
+
async settleWithLNURLWithdraw(lnurl) {
|
|
713
|
+
if (this.lnurl != null)
|
|
714
|
+
throw new Error("Cannot settle LNURL-withdraw swap with different LNURL");
|
|
715
|
+
let lnurlParams;
|
|
716
|
+
if (typeof (lnurl) === "string") {
|
|
717
|
+
const parsedLNURL = await LNURL_1.LNURL.getLNURL(lnurl);
|
|
718
|
+
if (parsedLNURL == null || parsedLNURL.tag !== "withdrawRequest")
|
|
719
|
+
throw new UserError_1.UserError("Invalid LNURL-withdraw to settle the swap");
|
|
720
|
+
lnurlParams = parsedLNURL;
|
|
721
|
+
}
|
|
722
|
+
else {
|
|
723
|
+
lnurlParams = lnurl.params;
|
|
724
|
+
}
|
|
725
|
+
LNURL_1.LNURL.useLNURLWithdraw(lnurlParams, this.pr).catch(e => this.lnurlFailSignal.abort(e));
|
|
726
|
+
this.lnurl = lnurlParams.url;
|
|
727
|
+
this.lnurlCallback = lnurlParams.callback;
|
|
728
|
+
this.lnurlK1 = lnurlParams.k1;
|
|
729
|
+
this.prPosted = true;
|
|
730
|
+
await this._saveAndEmit();
|
|
731
|
+
}
|
|
732
|
+
//////////////////////////////
|
|
733
|
+
//// Storage
|
|
734
|
+
serialize() {
|
|
735
|
+
return {
|
|
736
|
+
...super.serialize(),
|
|
737
|
+
data: this.data == null ? null : this.data.serialize(),
|
|
738
|
+
commitTxId: this.commitTxId,
|
|
739
|
+
claimTxId: this.claimTxId,
|
|
740
|
+
btcAmountSwap: this.btcAmountSwap == null ? null : this.btcAmountSwap.toString(10),
|
|
741
|
+
btcAmountGas: this.btcAmountGas == null ? null : this.btcAmountGas.toString(10),
|
|
742
|
+
gasSwapFeeBtc: this.gasSwapFeeBtc == null ? null : this.gasSwapFeeBtc.toString(10),
|
|
743
|
+
gasSwapFee: this.gasSwapFee == null ? null : this.gasSwapFee.toString(10),
|
|
744
|
+
gasPricingInfo: (0, PriceInfoType_1.serializePriceInfoType)(this.gasPricingInfo),
|
|
745
|
+
pr: this.pr,
|
|
746
|
+
secret: this.secret,
|
|
747
|
+
lnurl: this.lnurl,
|
|
748
|
+
lnurlK1: this.lnurlK1,
|
|
749
|
+
lnurlCallback: this.lnurlCallback,
|
|
750
|
+
prPosted: this.prPosted,
|
|
751
|
+
initialSwapData: this.initialSwapData.serialize()
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
//////////////////////////////
|
|
755
|
+
//// Swap ticks & sync
|
|
756
|
+
/**
|
|
757
|
+
* Checks the swap's state on-chain and compares it to its internal state, updates/changes it according to on-chain
|
|
758
|
+
* data
|
|
759
|
+
*
|
|
760
|
+
* @private
|
|
761
|
+
*/
|
|
762
|
+
async syncStateFromChain(quoteDefinitelyExpired, commitStatus) {
|
|
763
|
+
//Check for expiry before the getCommitStatus to prevent race conditions
|
|
764
|
+
let quoteExpired = false;
|
|
765
|
+
if (this.state === FromBTCLNAutoSwapState.PR_PAID) {
|
|
766
|
+
quoteExpired = quoteDefinitelyExpired ?? await this._verifyQuoteDefinitelyExpired();
|
|
767
|
+
}
|
|
768
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED || this.state === FromBTCLNAutoSwapState.EXPIRED) {
|
|
769
|
+
//Check if it's already successfully paid
|
|
770
|
+
commitStatus ??= await this.wrapper.contract.getCommitStatus(this._getInitiator(), this.data);
|
|
771
|
+
if (commitStatus?.type === base_1.SwapCommitStateType.PAID) {
|
|
772
|
+
if (this.claimTxId == null)
|
|
773
|
+
this.claimTxId = await commitStatus.getClaimTxId();
|
|
774
|
+
this.state = FromBTCLNAutoSwapState.CLAIM_CLAIMED;
|
|
775
|
+
return true;
|
|
776
|
+
}
|
|
777
|
+
if (commitStatus?.type === base_1.SwapCommitStateType.NOT_COMMITED || commitStatus?.type === base_1.SwapCommitStateType.EXPIRED) {
|
|
778
|
+
this.state = FromBTCLNAutoSwapState.FAILED;
|
|
779
|
+
return true;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
if (this.state === FromBTCLNAutoSwapState.PR_PAID) {
|
|
783
|
+
//Check if it's already committed
|
|
784
|
+
commitStatus ??= await this.wrapper.contract.getCommitStatus(this._getInitiator(), this.data);
|
|
785
|
+
switch (commitStatus?.type) {
|
|
786
|
+
case base_1.SwapCommitStateType.COMMITED:
|
|
787
|
+
this.state = FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
788
|
+
return true;
|
|
789
|
+
case base_1.SwapCommitStateType.EXPIRED:
|
|
790
|
+
this.state = FromBTCLNAutoSwapState.EXPIRED;
|
|
791
|
+
return true;
|
|
792
|
+
case base_1.SwapCommitStateType.PAID:
|
|
793
|
+
if (this.claimTxId == null)
|
|
794
|
+
this.claimTxId = await commitStatus.getClaimTxId();
|
|
795
|
+
this.state = FromBTCLNAutoSwapState.CLAIM_CLAIMED;
|
|
796
|
+
return true;
|
|
797
|
+
}
|
|
798
|
+
if (quoteExpired) {
|
|
799
|
+
this.state = FromBTCLNAutoSwapState.QUOTE_EXPIRED;
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return false;
|
|
804
|
+
}
|
|
805
|
+
_shouldFetchCommitStatus() {
|
|
806
|
+
return this.state === FromBTCLNAutoSwapState.PR_PAID || this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED || this.state === FromBTCLNAutoSwapState.EXPIRED;
|
|
807
|
+
}
|
|
808
|
+
_shouldFetchExpiryStatus() {
|
|
809
|
+
return this.state === FromBTCLNAutoSwapState.PR_PAID;
|
|
810
|
+
}
|
|
811
|
+
_shouldCheckIntermediary() {
|
|
812
|
+
return this.state === FromBTCLNAutoSwapState.PR_CREATED || this.state === FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED;
|
|
813
|
+
}
|
|
814
|
+
async _sync(save, quoteDefinitelyExpired, commitStatus, skipLpCheck) {
|
|
815
|
+
let changed = false;
|
|
816
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED || this.state === FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED) {
|
|
817
|
+
if (this.state !== FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED && this.getQuoteExpiry() < Date.now()) {
|
|
818
|
+
this.state = FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED;
|
|
819
|
+
changed ||= true;
|
|
820
|
+
}
|
|
821
|
+
if (!skipLpCheck)
|
|
822
|
+
try {
|
|
823
|
+
const result = await this._checkIntermediaryPaymentReceived(false);
|
|
824
|
+
if (result !== null)
|
|
825
|
+
changed ||= true;
|
|
826
|
+
}
|
|
827
|
+
catch (e) {
|
|
828
|
+
this.logger.error("_sync(): Failed to synchronize swap, error: ", e);
|
|
829
|
+
}
|
|
830
|
+
if (this.state === FromBTCLNAutoSwapState.PR_CREATED || this.state === FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED) {
|
|
831
|
+
if (await this._verifyQuoteDefinitelyExpired()) {
|
|
832
|
+
this.state = FromBTCLNAutoSwapState.QUOTE_EXPIRED;
|
|
833
|
+
changed ||= true;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
if (await this.syncStateFromChain(quoteDefinitelyExpired, commitStatus))
|
|
838
|
+
changed = true;
|
|
839
|
+
if (save && changed)
|
|
840
|
+
await this._saveAndEmit();
|
|
841
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED)
|
|
842
|
+
await this._broadcastSecret().catch(e => {
|
|
843
|
+
this.logger.error("_sync(): Error when broadcasting swap secret: ", e);
|
|
844
|
+
});
|
|
845
|
+
return changed;
|
|
846
|
+
}
|
|
847
|
+
async _broadcastSecret(noCheckExpiry) {
|
|
848
|
+
if (this.state !== FromBTCLNAutoSwapState.CLAIM_COMMITED)
|
|
849
|
+
throw new Error("Must be in CLAIM_COMMITED state to broadcast swap secret!");
|
|
850
|
+
if (this.data == null)
|
|
851
|
+
throw new Error("Unknown data, wrong state?");
|
|
852
|
+
if (!noCheckExpiry) {
|
|
853
|
+
if (await this.wrapper.contract.isExpired(this._getInitiator(), this.data))
|
|
854
|
+
throw new Error("On-chain HTLC already expired!");
|
|
855
|
+
}
|
|
856
|
+
await this.wrapper.messenger.broadcast(new base_1.SwapClaimWitnessMessage(this.data, this.secret));
|
|
857
|
+
}
|
|
858
|
+
async _tick(save) {
|
|
859
|
+
switch (this.state) {
|
|
860
|
+
case FromBTCLNAutoSwapState.PR_CREATED:
|
|
861
|
+
if (this.getQuoteExpiry() < Date.now()) {
|
|
862
|
+
this.state = FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED;
|
|
863
|
+
if (save)
|
|
864
|
+
await this._saveAndEmit();
|
|
865
|
+
return true;
|
|
866
|
+
}
|
|
867
|
+
break;
|
|
868
|
+
case FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED:
|
|
869
|
+
if (this.getDefinitiveExpiryTime() < Date.now()) {
|
|
870
|
+
this.state = FromBTCLNAutoSwapState.QUOTE_EXPIRED;
|
|
871
|
+
if (save)
|
|
872
|
+
await this._saveAndEmit();
|
|
873
|
+
return true;
|
|
874
|
+
}
|
|
875
|
+
break;
|
|
876
|
+
case FromBTCLNAutoSwapState.PR_PAID:
|
|
877
|
+
case FromBTCLNAutoSwapState.CLAIM_COMMITED:
|
|
878
|
+
const expired = await this.wrapper.contract.isExpired(this._getInitiator(), this.data);
|
|
879
|
+
if (expired) {
|
|
880
|
+
this.state = FromBTCLNAutoSwapState.EXPIRED;
|
|
881
|
+
if (save)
|
|
882
|
+
await this._saveAndEmit();
|
|
883
|
+
return true;
|
|
884
|
+
}
|
|
885
|
+
if (this.state === FromBTCLNAutoSwapState.CLAIM_COMMITED) {
|
|
886
|
+
//Broadcast the secret over the provided messenger channel
|
|
887
|
+
if (this.broadcastTickCounter === 0)
|
|
888
|
+
await this._broadcastSecret(true).catch(e => {
|
|
889
|
+
this.logger.warn("_tick(): Error when broadcasting swap secret: ", e);
|
|
890
|
+
});
|
|
891
|
+
this.broadcastTickCounter = (this.broadcastTickCounter + 1) % 3; //Broadcast every 3rd tick
|
|
892
|
+
}
|
|
893
|
+
break;
|
|
894
|
+
}
|
|
895
|
+
return false;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
exports.FromBTCLNAutoSwap = FromBTCLNAutoSwap;
|