@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,796 @@
|
|
|
1
|
+
import {ISwapWrapper, ISwapWrapperOptions, SwapTypeDefinition, WrapperCtorTokens} from "../ISwapWrapper";
|
|
2
|
+
import {
|
|
3
|
+
BtcRelay,
|
|
4
|
+
ChainEvent,
|
|
5
|
+
ChainType,
|
|
6
|
+
RelaySynchronizer,
|
|
7
|
+
SpvVaultClaimEvent,
|
|
8
|
+
SpvVaultCloseEvent,
|
|
9
|
+
SpvVaultFrontEvent,
|
|
10
|
+
SpvVaultTokenBalance,
|
|
11
|
+
SpvWithdrawalStateType
|
|
12
|
+
} from "@atomiqlabs/base";
|
|
13
|
+
import {SpvFromBTCSwap, SpvFromBTCSwapInit, SpvFromBTCSwapState} from "./SpvFromBTCSwap";
|
|
14
|
+
import {BTC_NETWORK, TEST_NETWORK} from "@scure/btc-signer/utils";
|
|
15
|
+
import {SwapType} from "../../enums/SwapType";
|
|
16
|
+
import {BitcoinRpcWithAddressIndex} from "../../bitcoin/BitcoinRpcWithAddressIndex";
|
|
17
|
+
import {UnifiedSwapStorage} from "../../storage/UnifiedSwapStorage";
|
|
18
|
+
import {UnifiedSwapEventListener} from "../../events/UnifiedSwapEventListener";
|
|
19
|
+
import {ISwapPrice} from "../../prices/abstract/ISwapPrice";
|
|
20
|
+
import {EventEmitter} from "events";
|
|
21
|
+
import {Intermediary} from "../../intermediaries/Intermediary";
|
|
22
|
+
import {extendAbortController, randomBytes, throwIfUndefined} from "../../utils/Utils";
|
|
23
|
+
import {toCoinselectAddressType, toOutputScript} from "../../utils/BitcoinUtils";
|
|
24
|
+
import {IntermediaryAPI, SpvFromBTCPrepareResponseType} from "../../intermediaries/apis/IntermediaryAPI";
|
|
25
|
+
import {RequestError} from "../../errors/RequestError";
|
|
26
|
+
import {IntermediaryError} from "../../errors/IntermediaryError";
|
|
27
|
+
import {CoinselectAddressTypes} from "../../bitcoin/coinselect2";
|
|
28
|
+
import {OutScript, Transaction} from "@scure/btc-signer";
|
|
29
|
+
import {ISwap} from "../ISwap";
|
|
30
|
+
import {IClaimableSwapWrapper} from "../IClaimableSwapWrapper";
|
|
31
|
+
import {AmountData} from "../../types/AmountData";
|
|
32
|
+
import {tryWithRetries} from "../../utils/RetryUtils";
|
|
33
|
+
import {AllOptional, AllRequired} from "../../utils/TypeUtils";
|
|
34
|
+
|
|
35
|
+
export type SpvFromBTCOptions = {
|
|
36
|
+
gasAmount?: bigint,
|
|
37
|
+
unsafeZeroWatchtowerFee?: boolean,
|
|
38
|
+
feeSafetyFactor?: number,
|
|
39
|
+
maxAllowedNetworkFeeRate?: number
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type SpvFromBTCWrapperOptions = ISwapWrapperOptions & {
|
|
43
|
+
maxConfirmations: number,
|
|
44
|
+
bitcoinNetwork: BTC_NETWORK,
|
|
45
|
+
bitcoinBlocktime: number,
|
|
46
|
+
maxTransactionsDelta: number, //Maximum accepted difference in state between SC state and bitcoin state, in terms of by how many transactions are they differing
|
|
47
|
+
maxRawAmountAdjustmentDifferencePPM: number,
|
|
48
|
+
maxBtcFeeMultiplier: number,
|
|
49
|
+
maxBtcFeeOffset: number
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type SpvFromBTCTypeDefinition<T extends ChainType> = SwapTypeDefinition<T, SpvFromBTCWrapper<T>, SpvFromBTCSwap<T>>;
|
|
53
|
+
|
|
54
|
+
export class SpvFromBTCWrapper<
|
|
55
|
+
T extends ChainType
|
|
56
|
+
> extends ISwapWrapper<T, SpvFromBTCTypeDefinition<T>, SpvFromBTCWrapperOptions> implements IClaimableSwapWrapper<SpvFromBTCSwap<T>> {
|
|
57
|
+
|
|
58
|
+
public readonly claimableSwapStates = [SpvFromBTCSwapState.BTC_TX_CONFIRMED];
|
|
59
|
+
public readonly TYPE = SwapType.SPV_VAULT_FROM_BTC;
|
|
60
|
+
public readonly swapDeserializer = SpvFromBTCSwap;
|
|
61
|
+
|
|
62
|
+
readonly synchronizer: RelaySynchronizer<any, T["TX"], any>;
|
|
63
|
+
readonly contract: T["SpvVaultContract"];
|
|
64
|
+
readonly btcRelay: T["BtcRelay"];
|
|
65
|
+
readonly btcRpc: BitcoinRpcWithAddressIndex<any>;
|
|
66
|
+
|
|
67
|
+
readonly spvWithdrawalDataDeserializer: new (data: any) => T["SpvVaultWithdrawalData"];
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param chainIdentifier
|
|
71
|
+
* @param unifiedStorage Storage interface for the current environment
|
|
72
|
+
* @param unifiedChainEvents On-chain event listener
|
|
73
|
+
* @param chain
|
|
74
|
+
* @param contract Underlying contract handling the swaps
|
|
75
|
+
* @param prices Pricing to use
|
|
76
|
+
* @param tokens
|
|
77
|
+
* @param spvWithdrawalDataDeserializer Deserializer for SpvVaultWithdrawalData
|
|
78
|
+
* @param btcRelay
|
|
79
|
+
* @param synchronizer Btc relay synchronizer
|
|
80
|
+
* @param btcRpc Bitcoin RPC which also supports getting transactions by txoHash
|
|
81
|
+
* @param options
|
|
82
|
+
* @param events Instance to use for emitting events
|
|
83
|
+
*/
|
|
84
|
+
constructor(
|
|
85
|
+
chainIdentifier: string,
|
|
86
|
+
unifiedStorage: UnifiedSwapStorage<T>,
|
|
87
|
+
unifiedChainEvents: UnifiedSwapEventListener<T>,
|
|
88
|
+
chain: T["ChainInterface"],
|
|
89
|
+
contract: T["SpvVaultContract"],
|
|
90
|
+
prices: ISwapPrice,
|
|
91
|
+
tokens: WrapperCtorTokens,
|
|
92
|
+
spvWithdrawalDataDeserializer: new (data: any) => T["SpvVaultWithdrawalData"],
|
|
93
|
+
btcRelay: BtcRelay<any, T["TX"], any>,
|
|
94
|
+
synchronizer: RelaySynchronizer<any, T["TX"], any>,
|
|
95
|
+
btcRpc: BitcoinRpcWithAddressIndex<any>,
|
|
96
|
+
options?: AllOptional<SpvFromBTCWrapperOptions>,
|
|
97
|
+
events?: EventEmitter<{swapState: [ISwap]}>
|
|
98
|
+
) {
|
|
99
|
+
if(options==null) options = {};
|
|
100
|
+
options.bitcoinNetwork ??= TEST_NETWORK;
|
|
101
|
+
options.maxConfirmations ??= 6;
|
|
102
|
+
options.bitcoinBlocktime ??= 10*60;
|
|
103
|
+
options.maxTransactionsDelta ??= 3;
|
|
104
|
+
options.maxRawAmountAdjustmentDifferencePPM ??= 100;
|
|
105
|
+
options.maxBtcFeeOffset ??= 5;
|
|
106
|
+
options.maxBtcFeeMultiplier ??= 1.5;
|
|
107
|
+
super(
|
|
108
|
+
chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens,
|
|
109
|
+
{
|
|
110
|
+
bitcoinNetwork: options.bitcoinNetwork ?? TEST_NETWORK,
|
|
111
|
+
maxConfirmations: options.maxConfirmations ?? 6,
|
|
112
|
+
bitcoinBlocktime: options.bitcoinBlocktime ?? 10*60,
|
|
113
|
+
maxTransactionsDelta: options.maxTransactionsDelta ?? 3,
|
|
114
|
+
maxRawAmountAdjustmentDifferencePPM: options.maxRawAmountAdjustmentDifferencePPM ?? 100,
|
|
115
|
+
maxBtcFeeOffset: options.maxBtcFeeOffset ?? 5,
|
|
116
|
+
maxBtcFeeMultiplier: options.maxBtcFeeMultiplier ?? 1.5
|
|
117
|
+
},
|
|
118
|
+
events
|
|
119
|
+
);
|
|
120
|
+
this.spvWithdrawalDataDeserializer = spvWithdrawalDataDeserializer;
|
|
121
|
+
this.contract = contract;
|
|
122
|
+
this.btcRelay = btcRelay;
|
|
123
|
+
this.synchronizer = synchronizer;
|
|
124
|
+
this.btcRpc = btcRpc;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
readonly pendingSwapStates: Array<SpvFromBTCSwap<T>["state"]> = [
|
|
128
|
+
SpvFromBTCSwapState.CREATED,
|
|
129
|
+
SpvFromBTCSwapState.SIGNED,
|
|
130
|
+
SpvFromBTCSwapState.POSTED,
|
|
131
|
+
SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED,
|
|
132
|
+
SpvFromBTCSwapState.BROADCASTED,
|
|
133
|
+
SpvFromBTCSwapState.DECLINED,
|
|
134
|
+
SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
135
|
+
];
|
|
136
|
+
readonly tickSwapState: Array<SpvFromBTCSwap<T>["state"]> = [
|
|
137
|
+
SpvFromBTCSwapState.CREATED,
|
|
138
|
+
SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED,
|
|
139
|
+
SpvFromBTCSwapState.SIGNED,
|
|
140
|
+
SpvFromBTCSwapState.POSTED,
|
|
141
|
+
SpvFromBTCSwapState.BROADCASTED
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
protected async processEventFront(event: SpvVaultFrontEvent, swap: SpvFromBTCSwap<T>): Promise<boolean> {
|
|
145
|
+
if(
|
|
146
|
+
swap.state===SpvFromBTCSwapState.SIGNED || swap.state===SpvFromBTCSwapState.POSTED ||
|
|
147
|
+
swap.state===SpvFromBTCSwapState.BROADCASTED || swap.state===SpvFromBTCSwapState.DECLINED ||
|
|
148
|
+
swap.state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED || swap.state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
149
|
+
) {
|
|
150
|
+
await swap._setBitcoinTxId(event.btcTxId).catch(e => {
|
|
151
|
+
this.logger.warn("processEventFront(): Failed to set bitcoin txId: ", e);
|
|
152
|
+
});
|
|
153
|
+
swap.state = SpvFromBTCSwapState.FRONTED;
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
protected async processEventClaim(event: SpvVaultClaimEvent, swap: SpvFromBTCSwap<T>): Promise<boolean> {
|
|
160
|
+
if(
|
|
161
|
+
swap.state===SpvFromBTCSwapState.SIGNED || swap.state===SpvFromBTCSwapState.POSTED ||
|
|
162
|
+
swap.state===SpvFromBTCSwapState.BROADCASTED || swap.state===SpvFromBTCSwapState.DECLINED ||
|
|
163
|
+
swap.state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED || swap.state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
164
|
+
) {
|
|
165
|
+
await swap._setBitcoinTxId(event.btcTxId).catch(e => {
|
|
166
|
+
this.logger.warn("processEventClaim(): Failed to set bitcoin txId: ", e);
|
|
167
|
+
});
|
|
168
|
+
swap.state = SpvFromBTCSwapState.CLAIMED;
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
protected processEventClose(event: SpvVaultCloseEvent, swap: SpvFromBTCSwap<T>): Promise<boolean> {
|
|
175
|
+
if(
|
|
176
|
+
swap.state===SpvFromBTCSwapState.SIGNED || swap.state===SpvFromBTCSwapState.POSTED ||
|
|
177
|
+
swap.state===SpvFromBTCSwapState.BROADCASTED || swap.state===SpvFromBTCSwapState.DECLINED ||
|
|
178
|
+
swap.state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED || swap.state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
179
|
+
) {
|
|
180
|
+
swap.state = SpvFromBTCSwapState.CLOSED;
|
|
181
|
+
return Promise.resolve(true);
|
|
182
|
+
}
|
|
183
|
+
return Promise.resolve(false);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
protected async processEvent(event: ChainEvent<T["Data"]>, swap: SpvFromBTCSwap<T>): Promise<void> {
|
|
187
|
+
if(swap==null) return;
|
|
188
|
+
|
|
189
|
+
let swapChanged: boolean = false;
|
|
190
|
+
if(event instanceof SpvVaultFrontEvent) {
|
|
191
|
+
swapChanged = await this.processEventFront(event, swap);
|
|
192
|
+
if(event.meta?.txId!=null && swap.frontTxId!==event.meta.txId) {
|
|
193
|
+
swap.frontTxId = event.meta.txId;
|
|
194
|
+
swapChanged ||= true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if(event instanceof SpvVaultClaimEvent) {
|
|
198
|
+
swapChanged = await this.processEventClaim(event, swap);
|
|
199
|
+
if(event.meta?.txId!=null && swap.claimTxId!==event.meta.txId) {
|
|
200
|
+
swap.claimTxId = event.meta.txId;
|
|
201
|
+
swapChanged ||= true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if(event instanceof SpvVaultCloseEvent) {
|
|
205
|
+
swapChanged = await this.processEventClose(event, swap);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
this.logger.info("processEvents(): "+event.constructor.name+" processed for "+swap.getId()+" swap: ", swap);
|
|
209
|
+
|
|
210
|
+
if(swapChanged) {
|
|
211
|
+
await swap._saveAndEmit();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Pre-fetches latest finalized block height of the smart chain
|
|
217
|
+
*
|
|
218
|
+
* @param abortController
|
|
219
|
+
* @private
|
|
220
|
+
*/
|
|
221
|
+
private async preFetchFinalizedBlockHeight(abortController: AbortController): Promise<number | undefined> {
|
|
222
|
+
try {
|
|
223
|
+
const block = await this.chain.getFinalizedBlock();
|
|
224
|
+
return block.height;
|
|
225
|
+
} catch (e) {
|
|
226
|
+
abortController.abort(e);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Pre-fetches caller (watchtower) bounty data for the swap. Doesn't throw, instead returns null and aborts the
|
|
232
|
+
* provided abortController
|
|
233
|
+
*
|
|
234
|
+
* @param amountData
|
|
235
|
+
* @param options Options as passed to the swap creation function
|
|
236
|
+
* @param pricePrefetch
|
|
237
|
+
* @param nativeTokenPricePrefetch
|
|
238
|
+
* @param abortController
|
|
239
|
+
* @private
|
|
240
|
+
*/
|
|
241
|
+
private async preFetchCallerFeeShare(
|
|
242
|
+
amountData: AmountData,
|
|
243
|
+
options: AllRequired<SpvFromBTCOptions>,
|
|
244
|
+
pricePrefetch: Promise<bigint | undefined>,
|
|
245
|
+
nativeTokenPricePrefetch: Promise<bigint | undefined> | undefined,
|
|
246
|
+
abortController: AbortController
|
|
247
|
+
): Promise<bigint | undefined> {
|
|
248
|
+
if(options.unsafeZeroWatchtowerFee) return 0n;
|
|
249
|
+
if(amountData.amount===0n) return 0n;
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const [
|
|
253
|
+
feePerBlock,
|
|
254
|
+
btcRelayData,
|
|
255
|
+
currentBtcBlock,
|
|
256
|
+
claimFeeRate,
|
|
257
|
+
nativeTokenPrice
|
|
258
|
+
] = await Promise.all([
|
|
259
|
+
this.btcRelay.getFeePerBlock(),
|
|
260
|
+
this.btcRelay.getTipData(),
|
|
261
|
+
this.btcRpc.getTipHeight(),
|
|
262
|
+
this.contract.getClaimFee(this.chain.randomAddress()),
|
|
263
|
+
nativeTokenPricePrefetch ?? (amountData.token===this.chain.getNativeCurrencyAddress() ?
|
|
264
|
+
pricePrefetch :
|
|
265
|
+
this.prices.preFetchPrice(this.chainIdentifier, this.chain.getNativeCurrencyAddress(), abortController.signal))
|
|
266
|
+
]);
|
|
267
|
+
|
|
268
|
+
if(btcRelayData==null) throw new Error("Btc relay doesn't seem to be initialized!");
|
|
269
|
+
|
|
270
|
+
const currentBtcRelayBlock = btcRelayData.blockheight;
|
|
271
|
+
const blockDelta = Math.max(currentBtcBlock-currentBtcRelayBlock+this.options.maxConfirmations, 0);
|
|
272
|
+
|
|
273
|
+
const totalFeeInNativeToken = (
|
|
274
|
+
(BigInt(blockDelta) * feePerBlock) +
|
|
275
|
+
(claimFeeRate * BigInt(this.options.maxTransactionsDelta))
|
|
276
|
+
) * BigInt(Math.floor(options.feeSafetyFactor*1000000)) / 1_000_000n;
|
|
277
|
+
|
|
278
|
+
let payoutAmount: bigint;
|
|
279
|
+
if(amountData.exactIn) {
|
|
280
|
+
//Convert input amount in BTC to
|
|
281
|
+
const amountInNativeToken = await this.prices.getFromBtcSwapAmount(this.chainIdentifier, amountData.amount, this.chain.getNativeCurrencyAddress(), abortController.signal, nativeTokenPrice);
|
|
282
|
+
payoutAmount = amountInNativeToken - totalFeeInNativeToken;
|
|
283
|
+
} else {
|
|
284
|
+
if(amountData.token===this.chain.getNativeCurrencyAddress()) {
|
|
285
|
+
//Both amounts in same currency
|
|
286
|
+
payoutAmount = amountData.amount;
|
|
287
|
+
} else {
|
|
288
|
+
//Need to convert both to native currency
|
|
289
|
+
const btcAmount = await this.prices.getToBtcSwapAmount(this.chainIdentifier, amountData.amount, amountData.token, abortController.signal, await pricePrefetch);
|
|
290
|
+
payoutAmount = await this.prices.getFromBtcSwapAmount(this.chainIdentifier, btcAmount, this.chain.getNativeCurrencyAddress(), abortController.signal, nativeTokenPrice);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
this.logger.debug("preFetchCallerFeeShare(): Caller fee in native token: "+totalFeeInNativeToken.toString(10)+" total payout in native token: "+payoutAmount.toString(10));
|
|
295
|
+
|
|
296
|
+
const callerFeeShare = ((totalFeeInNativeToken * 100_000n) + payoutAmount - 1n) / payoutAmount; //Make sure to round up here
|
|
297
|
+
if(callerFeeShare < 0n) return 0n;
|
|
298
|
+
if(callerFeeShare >= 2n**20n) return 2n**20n - 1n;
|
|
299
|
+
return callerFeeShare;
|
|
300
|
+
} catch (e) {
|
|
301
|
+
abortController.abort(e);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Verifies response returned from intermediary
|
|
308
|
+
*
|
|
309
|
+
* @param resp Response as returned by the intermediary
|
|
310
|
+
* @param amountData
|
|
311
|
+
* @param lp Intermediary
|
|
312
|
+
* @param options Options as passed to the swap creation function
|
|
313
|
+
* @param callerFeeShare
|
|
314
|
+
* @param bitcoinFeeRatePromise Maximum accepted fee rate from the LPs
|
|
315
|
+
* @param abortSignal
|
|
316
|
+
* @private
|
|
317
|
+
* @throws {IntermediaryError} in case the response is invalid
|
|
318
|
+
*/
|
|
319
|
+
private async verifyReturnedData(
|
|
320
|
+
resp: SpvFromBTCPrepareResponseType,
|
|
321
|
+
amountData: AmountData,
|
|
322
|
+
lp: Intermediary,
|
|
323
|
+
options: SpvFromBTCOptions,
|
|
324
|
+
callerFeeShare: bigint,
|
|
325
|
+
bitcoinFeeRatePromise: Promise<number | undefined>,
|
|
326
|
+
abortSignal: AbortSignal
|
|
327
|
+
): Promise<{
|
|
328
|
+
vault: T["SpvVaultData"],
|
|
329
|
+
vaultUtxoValue: number
|
|
330
|
+
}> {
|
|
331
|
+
const btcFeeRate = await throwIfUndefined(bitcoinFeeRatePromise, "Bitcoin fee rate promise failed!");
|
|
332
|
+
abortSignal.throwIfAborted();
|
|
333
|
+
if(btcFeeRate!=null && resp.btcFeeRate > btcFeeRate) throw new IntermediaryError("Bitcoin fee rate returned too high!");
|
|
334
|
+
|
|
335
|
+
//Vault related
|
|
336
|
+
let vaultScript: Uint8Array;
|
|
337
|
+
let vaultAddressType: CoinselectAddressTypes;
|
|
338
|
+
let btcAddressScript: Uint8Array;
|
|
339
|
+
//Ensure valid btc addresses returned
|
|
340
|
+
try {
|
|
341
|
+
vaultScript = toOutputScript(this.options.bitcoinNetwork, resp.vaultBtcAddress);
|
|
342
|
+
vaultAddressType = toCoinselectAddressType(vaultScript);
|
|
343
|
+
btcAddressScript = toOutputScript(this.options.bitcoinNetwork, resp.btcAddress);
|
|
344
|
+
} catch (e) {
|
|
345
|
+
throw new IntermediaryError("Invalid btc address data returned", e);
|
|
346
|
+
}
|
|
347
|
+
const decodedUtxo = resp.btcUtxo.split(":");
|
|
348
|
+
if(
|
|
349
|
+
resp.address!==lp.getAddress(this.chainIdentifier) || //Ensure the LP is indeed the vault owner
|
|
350
|
+
resp.vaultId < 0n || //Ensure vaultId is not negative
|
|
351
|
+
vaultScript==null || //Make sure vault script is parsable and of known type
|
|
352
|
+
btcAddressScript==null || //Make sure btc address script is parsable and of known type
|
|
353
|
+
vaultAddressType==="p2pkh" || vaultAddressType==="p2sh-p2wpkh" || //Constrain the vault script type to witness types
|
|
354
|
+
decodedUtxo.length!==2 || decodedUtxo[0].length!==64 || isNaN(parseInt(decodedUtxo[1])) || //Check valid UTXO
|
|
355
|
+
resp.btcFeeRate < 1 || resp.btcFeeRate > 10000 //Sanity check on the returned BTC fee rate
|
|
356
|
+
) throw new IntermediaryError("Invalid vault data returned!");
|
|
357
|
+
|
|
358
|
+
//Amounts sanity
|
|
359
|
+
if(resp.btcAmountSwap + resp.btcAmountGas !==resp.btcAmount) throw new Error("Btc amount mismatch");
|
|
360
|
+
if(resp.swapFeeBtc + resp.gasSwapFeeBtc !==resp.totalFeeBtc) throw new Error("Btc fee mismatch");
|
|
361
|
+
|
|
362
|
+
//TODO: For now ensure fees are at 0
|
|
363
|
+
if(
|
|
364
|
+
resp.callerFeeShare!==callerFeeShare ||
|
|
365
|
+
resp.frontingFeeShare!==0n ||
|
|
366
|
+
resp.executionFeeShare!==0n
|
|
367
|
+
) throw new IntermediaryError("Invalid caller/fronting/execution fee returned");
|
|
368
|
+
|
|
369
|
+
//Check expiry
|
|
370
|
+
const timeNowSeconds = Math.floor(Date.now()/1000);
|
|
371
|
+
if(resp.expiry < timeNowSeconds) throw new IntermediaryError(`Quote already expired, expiry: ${resp.expiry}, systemTime: ${timeNowSeconds}, clockAdjusted: ${(Date as any)._now!=null}`);
|
|
372
|
+
|
|
373
|
+
let utxo = resp.btcUtxo.toLowerCase();
|
|
374
|
+
const [txId, voutStr] = utxo.split(":");
|
|
375
|
+
|
|
376
|
+
const abortController = extendAbortController(abortSignal);
|
|
377
|
+
let [vault, {vaultUtxoValue, btcTx}] = await Promise.all([
|
|
378
|
+
(async() => {
|
|
379
|
+
//Fetch vault data
|
|
380
|
+
let vault: T["SpvVaultData"] | null;
|
|
381
|
+
try {
|
|
382
|
+
vault = await this.contract.getVaultData(resp.address, resp.vaultId);
|
|
383
|
+
} catch (e) {
|
|
384
|
+
this.logger.error("Error getting spv vault (owner: "+resp.address+" vaultId: "+resp.vaultId.toString(10)+"): ", e);
|
|
385
|
+
throw new IntermediaryError("Spv swap vault not found", e);
|
|
386
|
+
}
|
|
387
|
+
abortController.signal.throwIfAborted();
|
|
388
|
+
|
|
389
|
+
//Make sure vault is opened
|
|
390
|
+
if(vault==null || !vault.isOpened()) throw new IntermediaryError("Returned spv swap vault is not opened!");
|
|
391
|
+
//Make sure the vault doesn't require insane amount of confirmations
|
|
392
|
+
if(vault.getConfirmations()>this.options.maxConfirmations) throw new IntermediaryError("SPV swap vault needs too many confirmations: "+vault.getConfirmations());
|
|
393
|
+
const tokenData = vault.getTokenData();
|
|
394
|
+
|
|
395
|
+
//Amounts - make sure the amounts match
|
|
396
|
+
if(amountData.exactIn) {
|
|
397
|
+
if(resp.btcAmount !== amountData.amount) throw new IntermediaryError("Invalid amount returned");
|
|
398
|
+
} else {
|
|
399
|
+
//Check the difference between amount adjusted due to scaling to raw amount
|
|
400
|
+
const adjustedAmount = amountData.amount / tokenData[0].multiplier * tokenData[0].multiplier;
|
|
401
|
+
const adjustmentPPM = (amountData.amount - adjustedAmount)*1_000_000n / amountData.amount;
|
|
402
|
+
if(adjustmentPPM > this.options.maxRawAmountAdjustmentDifferencePPM)
|
|
403
|
+
throw new IntermediaryError("Invalid amount0 multiplier used, rawAmount diff too high");
|
|
404
|
+
if(resp.total !== adjustedAmount) throw new IntermediaryError("Invalid total returned");
|
|
405
|
+
}
|
|
406
|
+
if(options.gasAmount==null || options.gasAmount===0n) {
|
|
407
|
+
if(resp.totalGas !== 0n) throw new IntermediaryError("Invalid gas total returned");
|
|
408
|
+
} else {
|
|
409
|
+
//Check the difference between amount adjusted due to scaling to raw amount
|
|
410
|
+
const adjustedGasAmount = options.gasAmount / tokenData[0].multiplier * tokenData[0].multiplier;
|
|
411
|
+
const adjustmentPPM = (options.gasAmount - adjustedGasAmount)*1_000_000n / options.gasAmount;
|
|
412
|
+
if(adjustmentPPM > this.options.maxRawAmountAdjustmentDifferencePPM)
|
|
413
|
+
throw new IntermediaryError("Invalid amount1 multiplier used, rawAmount diff too high");
|
|
414
|
+
if(resp.totalGas !== adjustedGasAmount) throw new IntermediaryError("Invalid gas total returned");
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return vault;
|
|
418
|
+
})(),
|
|
419
|
+
(async() => {
|
|
420
|
+
//Require the vault UTXO to have at least 1 confirmation
|
|
421
|
+
let btcTx = await this.btcRpc.getTransaction(txId);
|
|
422
|
+
if(btcTx==null) throw new IntermediaryError("Invalid UTXO, doesn't exist (txId)");
|
|
423
|
+
abortController.signal.throwIfAborted();
|
|
424
|
+
if(btcTx.confirmations==null || btcTx.confirmations<1) throw new IntermediaryError("SPV vault UTXO not confirmed");
|
|
425
|
+
const vout = parseInt(voutStr);
|
|
426
|
+
if(btcTx.outs[vout]==null) throw new IntermediaryError("Invalid UTXO, doesn't exist");
|
|
427
|
+
const vaultUtxoValue = btcTx.outs[vout].value;
|
|
428
|
+
return {btcTx, vaultUtxoValue};
|
|
429
|
+
})(),
|
|
430
|
+
(async() => {
|
|
431
|
+
//Require vault UTXO is unspent
|
|
432
|
+
if(await this.btcRpc.isSpent(utxo)) throw new IntermediaryError("Returned spv vault UTXO is already spent", null, true);
|
|
433
|
+
abortController.signal.throwIfAborted();
|
|
434
|
+
})()
|
|
435
|
+
]).catch(e => {
|
|
436
|
+
abortController.abort(e);
|
|
437
|
+
throw e;
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
this.logger.debug("verifyReturnedData(): Vault UTXO: "+vault.getUtxo()+" current utxo: "+utxo);
|
|
441
|
+
|
|
442
|
+
//Trace returned utxo back to what's saved on-chain
|
|
443
|
+
let pendingWithdrawals: T["SpvVaultWithdrawalData"][] = [];
|
|
444
|
+
while(vault.getUtxo()!==utxo) {
|
|
445
|
+
const [txId, voutStr] = utxo.split(":");
|
|
446
|
+
//Such that 1st tx isn't fetched twice
|
|
447
|
+
if(btcTx.txid!==txId) {
|
|
448
|
+
const _btcTx = await this.btcRpc.getTransaction(txId);
|
|
449
|
+
if(_btcTx==null) throw new IntermediaryError("Invalid ancestor transaction (not found)");
|
|
450
|
+
btcTx = _btcTx;
|
|
451
|
+
}
|
|
452
|
+
const withdrawalData = await this.contract.getWithdrawalData(btcTx);
|
|
453
|
+
abortSignal.throwIfAborted();
|
|
454
|
+
pendingWithdrawals.unshift(withdrawalData);
|
|
455
|
+
utxo = pendingWithdrawals[0].getSpentVaultUtxo();
|
|
456
|
+
this.logger.debug("verifyReturnedData(): Vault UTXO: "+vault.getUtxo()+" current utxo: "+utxo);
|
|
457
|
+
if(pendingWithdrawals.length>=this.options.maxTransactionsDelta)
|
|
458
|
+
throw new IntermediaryError("BTC <> SC state difference too deep, maximum: "+this.options.maxTransactionsDelta);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
//Verify that the vault has enough balance after processing all pending withdrawals
|
|
462
|
+
let vaultBalances: {balances: SpvVaultTokenBalance[]};
|
|
463
|
+
try {
|
|
464
|
+
vaultBalances = vault.calculateStateAfter(pendingWithdrawals);
|
|
465
|
+
} catch (e) {
|
|
466
|
+
this.logger.error("Error calculating spv vault balance (owner: "+resp.address+" vaultId: "+resp.vaultId.toString(10)+"): ", e);
|
|
467
|
+
throw new IntermediaryError("Spv swap vault balance prediction failed", e);
|
|
468
|
+
}
|
|
469
|
+
if(vaultBalances.balances[0].scaledAmount < resp.total)
|
|
470
|
+
throw new IntermediaryError("SPV swap vault, insufficient balance, required: "+resp.total.toString(10)+
|
|
471
|
+
" has: "+vaultBalances.balances[0].scaledAmount.toString(10));
|
|
472
|
+
if(vaultBalances.balances[1].scaledAmount < resp.totalGas)
|
|
473
|
+
throw new IntermediaryError("SPV swap vault, insufficient balance, required: "+resp.totalGas.toString(10)+
|
|
474
|
+
" has: "+vaultBalances.balances[1].scaledAmount.toString(10));
|
|
475
|
+
|
|
476
|
+
//Also verify that all the withdrawal txns are valid, this is an extra sanity check
|
|
477
|
+
try {
|
|
478
|
+
for(let withdrawal of pendingWithdrawals) {
|
|
479
|
+
await this.contract.checkWithdrawalTx(withdrawal);
|
|
480
|
+
}
|
|
481
|
+
} catch (e) {
|
|
482
|
+
this.logger.error("Error calculating spv vault balance (owner: "+resp.address+" vaultId: "+resp.vaultId.toString(10)+"): ", e);
|
|
483
|
+
throw new IntermediaryError("Spv swap vault balance prediction failed", e);
|
|
484
|
+
}
|
|
485
|
+
abortSignal.throwIfAborted();
|
|
486
|
+
|
|
487
|
+
return {
|
|
488
|
+
vault,
|
|
489
|
+
vaultUtxoValue
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Returns a newly created swap, receiving 'amount' on chain
|
|
495
|
+
*
|
|
496
|
+
* @param signer Smartchain signer's address intiating the swap
|
|
497
|
+
* @param amountData Amount of token & amount to swap
|
|
498
|
+
* @param lps LPs (liquidity providers) to get the quotes from
|
|
499
|
+
* @param options Quote options
|
|
500
|
+
* @param additionalParams Additional parameters sent to the LP when creating the swap
|
|
501
|
+
* @param abortSignal Abort signal for aborting the process
|
|
502
|
+
*/
|
|
503
|
+
create(
|
|
504
|
+
signer: string,
|
|
505
|
+
amountData: AmountData,
|
|
506
|
+
lps: Intermediary[],
|
|
507
|
+
options?: SpvFromBTCOptions,
|
|
508
|
+
additionalParams?: Record<string, any>,
|
|
509
|
+
abortSignal?: AbortSignal
|
|
510
|
+
): {
|
|
511
|
+
quote: Promise<SpvFromBTCSwap<T>>,
|
|
512
|
+
intermediary: Intermediary
|
|
513
|
+
}[] {
|
|
514
|
+
const _options: AllRequired<SpvFromBTCOptions> = {
|
|
515
|
+
gasAmount: options?.gasAmount ?? 0n,
|
|
516
|
+
unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
|
|
517
|
+
feeSafetyFactor: options?.feeSafetyFactor ?? 1.25,
|
|
518
|
+
maxAllowedNetworkFeeRate: options?.maxAllowedNetworkFeeRate ?? Infinity
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
const _abortController = extendAbortController(abortSignal);
|
|
522
|
+
const pricePrefetchPromise: Promise<bigint | undefined> = this.preFetchPrice(amountData, _abortController.signal);
|
|
523
|
+
const usdPricePrefetchPromise: Promise<number | undefined> = this.preFetchUsdPrice(_abortController.signal);
|
|
524
|
+
const finalizedBlockHeightPrefetchPromise: Promise<number | undefined> = this.preFetchFinalizedBlockHeight(_abortController);
|
|
525
|
+
const nativeTokenAddress = this.chain.getNativeCurrencyAddress();
|
|
526
|
+
const gasTokenPricePrefetchPromise: Promise<bigint | undefined> | undefined = _options.gasAmount===0n ?
|
|
527
|
+
undefined :
|
|
528
|
+
this.preFetchPrice({token: nativeTokenAddress}, _abortController.signal);
|
|
529
|
+
const callerFeePrefetchPromise = this.preFetchCallerFeeShare(amountData, _options, pricePrefetchPromise, gasTokenPricePrefetchPromise, _abortController);
|
|
530
|
+
const bitcoinFeeRatePromise: Promise<number | undefined> = _options.maxAllowedNetworkFeeRate!=Infinity ?
|
|
531
|
+
Promise.resolve(_options.maxAllowedNetworkFeeRate) :
|
|
532
|
+
this.btcRpc.getFeeRate().then(x => this.options.maxBtcFeeOffset + (x*this.options.maxBtcFeeMultiplier)).catch(e => {
|
|
533
|
+
_abortController.abort(e);
|
|
534
|
+
return undefined;
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
return lps.map(lp => {
|
|
538
|
+
return {
|
|
539
|
+
intermediary: lp,
|
|
540
|
+
quote: tryWithRetries(async () => {
|
|
541
|
+
if(lp.services[SwapType.SPV_VAULT_FROM_BTC]==null) throw new Error("LP service for processing spv vault swaps not found!");
|
|
542
|
+
|
|
543
|
+
const abortController = extendAbortController(_abortController.signal);
|
|
544
|
+
|
|
545
|
+
try {
|
|
546
|
+
const resp = await tryWithRetries(async(retryCount: number) => {
|
|
547
|
+
return await IntermediaryAPI.prepareSpvFromBTC(
|
|
548
|
+
this.chainIdentifier, lp.url,
|
|
549
|
+
{
|
|
550
|
+
address: signer,
|
|
551
|
+
amount: amountData.amount,
|
|
552
|
+
token: amountData.token.toString(),
|
|
553
|
+
exactOut: !amountData.exactIn,
|
|
554
|
+
gasToken: nativeTokenAddress,
|
|
555
|
+
gasAmount: _options.gasAmount,
|
|
556
|
+
callerFeeRate: throwIfUndefined(callerFeePrefetchPromise, "Caller fee prefetch failed!"),
|
|
557
|
+
frontingFeeRate: 0n,
|
|
558
|
+
additionalParams
|
|
559
|
+
},
|
|
560
|
+
this.options.postRequestTimeout, abortController.signal, retryCount>0 ? false : undefined
|
|
561
|
+
);
|
|
562
|
+
}, undefined, e => e instanceof RequestError, abortController.signal);
|
|
563
|
+
|
|
564
|
+
this.logger.debug("create("+lp.url+"): LP response: ", resp)
|
|
565
|
+
|
|
566
|
+
const callerFeeShare = (await callerFeePrefetchPromise)!;
|
|
567
|
+
|
|
568
|
+
const [
|
|
569
|
+
pricingInfo,
|
|
570
|
+
gasPricingInfo,
|
|
571
|
+
{vault, vaultUtxoValue}
|
|
572
|
+
] = await Promise.all([
|
|
573
|
+
this.verifyReturnedPrice(
|
|
574
|
+
lp.services[SwapType.SPV_VAULT_FROM_BTC],
|
|
575
|
+
false, resp.btcAmountSwap,
|
|
576
|
+
resp.total * (100_000n + callerFeeShare) / 100_000n,
|
|
577
|
+
amountData.token, {}, pricePrefetchPromise, usdPricePrefetchPromise, abortController.signal
|
|
578
|
+
),
|
|
579
|
+
_options.gasAmount===0n ? Promise.resolve(undefined) : this.verifyReturnedPrice(
|
|
580
|
+
{...lp.services[SwapType.SPV_VAULT_FROM_BTC], swapBaseFee: 0}, //Base fee should be charged only on the amount, not on gas
|
|
581
|
+
false, resp.btcAmountGas,
|
|
582
|
+
resp.totalGas * (100_000n + callerFeeShare) / 100_000n,
|
|
583
|
+
nativeTokenAddress, {}, gasTokenPricePrefetchPromise, usdPricePrefetchPromise, abortController.signal
|
|
584
|
+
),
|
|
585
|
+
this.verifyReturnedData(resp, amountData, lp, _options, callerFeeShare, bitcoinFeeRatePromise, abortController.signal)
|
|
586
|
+
]);
|
|
587
|
+
|
|
588
|
+
const swapInit: SpvFromBTCSwapInit = {
|
|
589
|
+
pricingInfo,
|
|
590
|
+
url: lp.url,
|
|
591
|
+
expiry: resp.expiry * 1000,
|
|
592
|
+
swapFee: resp.swapFee,
|
|
593
|
+
swapFeeBtc: resp.swapFeeBtc,
|
|
594
|
+
exactIn: amountData.exactIn ?? true,
|
|
595
|
+
|
|
596
|
+
quoteId: resp.quoteId,
|
|
597
|
+
|
|
598
|
+
recipient: signer,
|
|
599
|
+
|
|
600
|
+
vaultOwner: resp.address,
|
|
601
|
+
vaultId: resp.vaultId,
|
|
602
|
+
vaultRequiredConfirmations: vault.getConfirmations(),
|
|
603
|
+
vaultTokenMultipliers: vault.getTokenData().map(val => val.multiplier),
|
|
604
|
+
vaultBtcAddress: resp.vaultBtcAddress,
|
|
605
|
+
vaultUtxo: resp.btcUtxo,
|
|
606
|
+
vaultUtxoValue: BigInt(vaultUtxoValue),
|
|
607
|
+
|
|
608
|
+
btcDestinationAddress: resp.btcAddress,
|
|
609
|
+
btcAmount: resp.btcAmount,
|
|
610
|
+
btcAmountSwap: resp.btcAmountSwap,
|
|
611
|
+
btcAmountGas: resp.btcAmountGas,
|
|
612
|
+
minimumBtcFeeRate: resp.btcFeeRate,
|
|
613
|
+
|
|
614
|
+
outputTotalSwap: resp.total,
|
|
615
|
+
outputSwapToken: amountData.token,
|
|
616
|
+
outputTotalGas: resp.totalGas,
|
|
617
|
+
outputGasToken: nativeTokenAddress,
|
|
618
|
+
gasSwapFeeBtc: resp.gasSwapFeeBtc,
|
|
619
|
+
gasSwapFee: resp.gasSwapFee,
|
|
620
|
+
gasPricingInfo,
|
|
621
|
+
|
|
622
|
+
callerFeeShare: resp.callerFeeShare,
|
|
623
|
+
frontingFeeShare: resp.frontingFeeShare,
|
|
624
|
+
executionFeeShare: resp.executionFeeShare,
|
|
625
|
+
|
|
626
|
+
genesisSmartChainBlockHeight: await throwIfUndefined(
|
|
627
|
+
finalizedBlockHeightPrefetchPromise,
|
|
628
|
+
"Finalize block height promise failed!"
|
|
629
|
+
)
|
|
630
|
+
};
|
|
631
|
+
const quote = new SpvFromBTCSwap<T>(this, swapInit);
|
|
632
|
+
await quote._save();
|
|
633
|
+
return quote;
|
|
634
|
+
} catch (e) {
|
|
635
|
+
abortController.abort(e);
|
|
636
|
+
throw e;
|
|
637
|
+
}
|
|
638
|
+
}, undefined, err => !(err instanceof IntermediaryError && err.recoverable), _abortController.signal)
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Returns a random dummy PSBT that can be used for fee estimation, the last output (the LP output) is omitted
|
|
645
|
+
* to allow for coinselection algorithm to determine maximum sendable amount there
|
|
646
|
+
*
|
|
647
|
+
* @param includeGasToken Whether to return the PSBT also with the gas token amount (increases the vSize by 8)
|
|
648
|
+
*/
|
|
649
|
+
public getDummySwapPsbt(includeGasToken = false): Transaction {
|
|
650
|
+
//Construct dummy swap psbt
|
|
651
|
+
const psbt = new Transaction({
|
|
652
|
+
allowUnknownInputs: true,
|
|
653
|
+
allowLegacyWitnessUtxo: true,
|
|
654
|
+
allowUnknownOutputs: true
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
const randomVaultOutScript = OutScript.encode({type: "tr", pubkey: Buffer.from("0101010101010101010101010101010101010101010101010101010101010101", "hex")});
|
|
658
|
+
|
|
659
|
+
psbt.addInput({
|
|
660
|
+
txid: randomBytes(32),
|
|
661
|
+
index: 0,
|
|
662
|
+
witnessUtxo: {
|
|
663
|
+
script: randomVaultOutScript,
|
|
664
|
+
amount: 600n
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
psbt.addOutput({
|
|
669
|
+
script: randomVaultOutScript,
|
|
670
|
+
amount: 600n
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
const opReturnData = this.contract.toOpReturnData(
|
|
674
|
+
this.chain.randomAddress(),
|
|
675
|
+
includeGasToken ? [0xFFFFFFFFFFFFFFFFn, 0xFFFFFFFFFFFFFFFFn] : [0xFFFFFFFFFFFFFFFFn]
|
|
676
|
+
);
|
|
677
|
+
|
|
678
|
+
psbt.addOutput({
|
|
679
|
+
script: Buffer.concat([
|
|
680
|
+
opReturnData.length <= 75 ? Buffer.from([0x6a, opReturnData.length]) : Buffer.from([0x6a, 0x4c, opReturnData.length]),
|
|
681
|
+
opReturnData
|
|
682
|
+
]),
|
|
683
|
+
amount: 0n
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
return psbt;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
protected async _checkPastSwaps(pastSwaps: SpvFromBTCSwap<T>[]): Promise<{
|
|
690
|
+
changedSwaps: SpvFromBTCSwap<T>[];
|
|
691
|
+
removeSwaps: SpvFromBTCSwap<T>[]
|
|
692
|
+
}> {
|
|
693
|
+
const changedSwaps: Set<SpvFromBTCSwap<T>> = new Set();
|
|
694
|
+
const removeSwaps: SpvFromBTCSwap<T>[] = [];
|
|
695
|
+
|
|
696
|
+
const broadcastedOrConfirmedSwaps: (SpvFromBTCSwap<T> & {data: T["SpvVaultWithdrawalData"]})[] = [];
|
|
697
|
+
|
|
698
|
+
for(let pastSwap of pastSwaps) {
|
|
699
|
+
let changed: boolean = false;
|
|
700
|
+
|
|
701
|
+
if(
|
|
702
|
+
pastSwap.state===SpvFromBTCSwapState.SIGNED ||
|
|
703
|
+
pastSwap.state===SpvFromBTCSwapState.POSTED ||
|
|
704
|
+
pastSwap.state===SpvFromBTCSwapState.BROADCASTED ||
|
|
705
|
+
pastSwap.state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED ||
|
|
706
|
+
pastSwap.state===SpvFromBTCSwapState.DECLINED ||
|
|
707
|
+
pastSwap.state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
708
|
+
) {
|
|
709
|
+
//Check BTC transaction
|
|
710
|
+
if(await pastSwap._syncStateFromBitcoin(false)) changed ||= true;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
if(
|
|
714
|
+
pastSwap.state===SpvFromBTCSwapState.CREATED ||
|
|
715
|
+
pastSwap.state===SpvFromBTCSwapState.SIGNED ||
|
|
716
|
+
pastSwap.state===SpvFromBTCSwapState.POSTED
|
|
717
|
+
) {
|
|
718
|
+
if(pastSwap.expiry<Date.now()) {
|
|
719
|
+
if(pastSwap.state===SpvFromBTCSwapState.CREATED) {
|
|
720
|
+
pastSwap.state = SpvFromBTCSwapState.QUOTE_EXPIRED;
|
|
721
|
+
} else {
|
|
722
|
+
pastSwap.state = SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED;
|
|
723
|
+
}
|
|
724
|
+
changed ||= true;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if(pastSwap.isQuoteExpired()) {
|
|
729
|
+
removeSwaps.push(pastSwap);
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
if(changed) changedSwaps.add(pastSwap);
|
|
733
|
+
|
|
734
|
+
if(pastSwap.state===SpvFromBTCSwapState.BROADCASTED || pastSwap.state===SpvFromBTCSwapState.BTC_TX_CONFIRMED) {
|
|
735
|
+
if(pastSwap.data!=null) broadcastedOrConfirmedSwaps.push(pastSwap as (SpvFromBTCSwap<T> & {data: T["SpvVaultWithdrawalData"]}));
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
const checkWithdrawalStateSwaps: (SpvFromBTCSwap<T> & {data: T["SpvVaultWithdrawalData"]})[] = [];
|
|
740
|
+
const _fronts = await this.contract.getFronterAddresses(broadcastedOrConfirmedSwaps.map(val => ({
|
|
741
|
+
owner: val.vaultOwner,
|
|
742
|
+
vaultId: val.vaultId,
|
|
743
|
+
withdrawal: val.data!
|
|
744
|
+
})));
|
|
745
|
+
const _vaultUtxos = await this.contract.getVaultLatestUtxos(broadcastedOrConfirmedSwaps.map(val => ({
|
|
746
|
+
owner: val.vaultOwner,
|
|
747
|
+
vaultId: val.vaultId
|
|
748
|
+
})));
|
|
749
|
+
for(const pastSwap of broadcastedOrConfirmedSwaps) {
|
|
750
|
+
const fronterAddress = _fronts[pastSwap.data.getTxId()];
|
|
751
|
+
const latestVaultUtxo = _vaultUtxos[pastSwap.vaultOwner]?.[pastSwap.vaultId.toString(10)];
|
|
752
|
+
if(fronterAddress===undefined) this.logger.warn(`_checkPastSwaps(): No fronter address returned for ${pastSwap.data.getTxId()}`);
|
|
753
|
+
if(latestVaultUtxo===undefined) this.logger.warn(`_checkPastSwaps(): No last vault utxo returned for ${pastSwap.data.getTxId()}`);
|
|
754
|
+
if(await pastSwap._shouldCheckWithdrawalState(fronterAddress, latestVaultUtxo)) checkWithdrawalStateSwaps.push(pastSwap);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
const withdrawalStates = await this.contract.getWithdrawalStates(
|
|
758
|
+
checkWithdrawalStateSwaps.map(val => ({
|
|
759
|
+
withdrawal: val.data,
|
|
760
|
+
scStartBlockheight: val.genesisSmartChainBlockHeight
|
|
761
|
+
}))
|
|
762
|
+
);
|
|
763
|
+
for(const pastSwap of checkWithdrawalStateSwaps) {
|
|
764
|
+
const status = withdrawalStates[pastSwap.data.getTxId()];
|
|
765
|
+
if(status==null) {
|
|
766
|
+
this.logger.warn(`_checkPastSwaps(): No withdrawal state returned for ${pastSwap.data.getTxId()}`);
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
this.logger.debug("syncStateFromChain(): status of "+pastSwap.data.btcTx.txid, status?.type);
|
|
770
|
+
let changed = false;
|
|
771
|
+
switch(status.type) {
|
|
772
|
+
case SpvWithdrawalStateType.FRONTED:
|
|
773
|
+
pastSwap.frontTxId = status.txId;
|
|
774
|
+
pastSwap.state = SpvFromBTCSwapState.FRONTED;
|
|
775
|
+
changed ||= true;
|
|
776
|
+
break;
|
|
777
|
+
case SpvWithdrawalStateType.CLAIMED:
|
|
778
|
+
pastSwap.claimTxId = status.txId;
|
|
779
|
+
pastSwap.state = SpvFromBTCSwapState.CLAIMED;
|
|
780
|
+
changed ||= true;
|
|
781
|
+
break;
|
|
782
|
+
case SpvWithdrawalStateType.CLOSED:
|
|
783
|
+
pastSwap.state = SpvFromBTCSwapState.CLOSED;
|
|
784
|
+
changed ||= true;
|
|
785
|
+
break;
|
|
786
|
+
}
|
|
787
|
+
if(changed) changedSwaps.add(pastSwap);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
return {
|
|
791
|
+
changedSwaps: Array.from(changedSwaps),
|
|
792
|
+
removeSwaps
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
}
|