@atomiqlabs/sdk 8.9.0 → 8.9.2
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/LICENSE +201 -201
- package/README.md +1760 -1760
- package/api/index.d.ts +1 -1
- package/api/index.js +3 -3
- package/dist/ApiList.d.ts +37 -37
- package/dist/ApiList.js +30 -30
- package/dist/SmartChainAssets.d.ts +181 -181
- package/dist/SmartChainAssets.js +181 -181
- package/dist/api/ApiEndpoints.d.ts +393 -393
- package/dist/api/ApiEndpoints.js +2 -2
- package/dist/api/ApiParser.d.ts +10 -10
- package/dist/api/ApiParser.js +134 -134
- package/dist/api/ApiTypes.d.ts +157 -157
- package/dist/api/ApiTypes.js +75 -75
- package/dist/api/SerializedAction.d.ts +40 -40
- package/dist/api/SerializedAction.js +59 -59
- package/dist/api/SwapperApi.d.ts +50 -50
- package/dist/api/SwapperApi.js +431 -431
- package/dist/api/index.d.ts +5 -5
- package/dist/api/index.js +24 -24
- package/dist/bitcoin/coinselect2/accumulative.d.ts +7 -7
- package/dist/bitcoin/coinselect2/accumulative.js +52 -52
- package/dist/bitcoin/coinselect2/blackjack.d.ts +7 -7
- package/dist/bitcoin/coinselect2/blackjack.js +38 -38
- package/dist/bitcoin/coinselect2/index.d.ts +20 -20
- package/dist/bitcoin/coinselect2/index.js +69 -69
- package/dist/bitcoin/coinselect2/utils.d.ts +82 -82
- package/dist/bitcoin/coinselect2/utils.js +158 -158
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +113 -113
- package/dist/bitcoin/wallet/BitcoinWallet.js +335 -335
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +116 -116
- package/dist/bitcoin/wallet/IBitcoinWallet.js +21 -21
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +106 -106
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +196 -196
- package/dist/enums/FeeType.d.ts +15 -15
- package/dist/enums/FeeType.js +19 -19
- package/dist/enums/SwapAmountType.d.ts +15 -15
- package/dist/enums/SwapAmountType.js +19 -19
- package/dist/enums/SwapDirection.d.ts +15 -15
- package/dist/enums/SwapDirection.js +19 -19
- package/dist/enums/SwapSide.d.ts +15 -15
- package/dist/enums/SwapSide.js +19 -19
- package/dist/enums/SwapType.d.ts +75 -75
- package/dist/enums/SwapType.js +79 -79
- package/dist/errors/IntermediaryError.d.ts +13 -13
- package/dist/errors/IntermediaryError.js +27 -27
- package/dist/errors/RequestError.d.ts +32 -32
- package/dist/errors/RequestError.js +54 -54
- package/dist/errors/UserError.d.ts +8 -8
- package/dist/errors/UserError.js +16 -16
- package/dist/events/UnifiedSwapEventListener.d.ts +24 -24
- package/dist/events/UnifiedSwapEventListener.js +138 -138
- package/dist/http/HttpUtils.d.ts +29 -29
- package/dist/http/HttpUtils.js +97 -97
- package/dist/http/paramcoders/IParamReader.d.ts +8 -8
- package/dist/http/paramcoders/IParamReader.js +2 -2
- package/dist/http/paramcoders/ParamDecoder.d.ts +44 -44
- package/dist/http/paramcoders/ParamDecoder.js +137 -137
- package/dist/http/paramcoders/ParamEncoder.d.ts +20 -20
- package/dist/http/paramcoders/ParamEncoder.js +36 -36
- package/dist/http/paramcoders/SchemaVerifier.d.ts +26 -26
- package/dist/http/paramcoders/SchemaVerifier.js +145 -145
- package/dist/http/paramcoders/client/ResponseParamDecoder.d.ts +11 -11
- package/dist/http/paramcoders/client/ResponseParamDecoder.js +57 -57
- package/dist/http/paramcoders/client/StreamParamEncoder.d.ts +13 -13
- package/dist/http/paramcoders/client/StreamParamEncoder.js +26 -26
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +17 -17
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +175 -175
- package/dist/index.d.ts +86 -86
- package/dist/index.js +159 -159
- package/dist/intermediaries/Intermediary.d.ts +178 -178
- package/dist/intermediaries/Intermediary.js +166 -166
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +216 -216
- package/dist/intermediaries/IntermediaryDiscovery.js +424 -424
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +607 -607
- package/dist/intermediaries/apis/IntermediaryAPI.js +764 -764
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.d.ts +155 -155
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.js +137 -137
- package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -14
- package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -68
- package/dist/lnurl/LNURL.d.ts +102 -102
- package/dist/lnurl/LNURL.js +321 -321
- package/dist/prices/RedundantSwapPrice.d.ts +110 -110
- package/dist/prices/RedundantSwapPrice.js +222 -222
- package/dist/prices/SingleSwapPrice.d.ts +34 -34
- package/dist/prices/SingleSwapPrice.js +44 -44
- package/dist/prices/SwapPriceWithChain.d.ts +107 -107
- package/dist/prices/SwapPriceWithChain.js +128 -128
- package/dist/prices/abstract/ICachedSwapPrice.d.ts +28 -28
- package/dist/prices/abstract/ICachedSwapPrice.js +62 -62
- package/dist/prices/abstract/IPriceProvider.d.ts +81 -81
- package/dist/prices/abstract/IPriceProvider.js +74 -74
- package/dist/prices/abstract/ISwapPrice.d.ts +168 -168
- package/dist/prices/abstract/ISwapPrice.js +279 -279
- package/dist/prices/providers/BinancePriceProvider.d.ts +23 -23
- package/dist/prices/providers/BinancePriceProvider.js +30 -30
- package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +23 -23
- package/dist/prices/providers/CoinGeckoPriceProvider.js +29 -29
- package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +25 -25
- package/dist/prices/providers/CoinPaprikaPriceProvider.js +29 -29
- package/dist/prices/providers/CustomPriceProvider.d.ts +24 -24
- package/dist/prices/providers/CustomPriceProvider.js +35 -35
- package/dist/prices/providers/KrakenPriceProvider.d.ts +38 -38
- package/dist/prices/providers/KrakenPriceProvider.js +45 -45
- package/dist/prices/providers/OKXPriceProvider.d.ts +34 -34
- package/dist/prices/providers/OKXPriceProvider.js +29 -29
- package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +17 -17
- package/dist/prices/providers/abstract/ExchangePriceProvider.js +21 -21
- package/dist/prices/providers/abstract/HttpPriceProvider.d.ts +7 -7
- package/dist/prices/providers/abstract/HttpPriceProvider.js +12 -12
- package/dist/storage/IUnifiedStorage.d.ts +127 -127
- package/dist/storage/IUnifiedStorage.js +2 -2
- package/dist/storage/UnifiedSwapStorage.d.ts +120 -120
- package/dist/storage/UnifiedSwapStorage.js +154 -154
- package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +63 -63
- package/dist/storage-browser/IndexedDBUnifiedStorage.js +298 -298
- package/dist/storage-browser/LocalStorageManager.d.ts +49 -49
- package/dist/storage-browser/LocalStorageManager.js +93 -93
- package/dist/swapper/Swapper.d.ts +765 -765
- package/dist/swapper/Swapper.js +1749 -1749
- package/dist/swapper/SwapperFactory.d.ts +135 -135
- package/dist/swapper/SwapperFactory.js +162 -162
- package/dist/swapper/SwapperUtils.d.ts +222 -222
- package/dist/swapper/SwapperUtils.js +519 -519
- package/dist/swapper/SwapperWithChain.d.ts +404 -404
- package/dist/swapper/SwapperWithChain.js +469 -469
- package/dist/swapper/SwapperWithSigner.d.ts +322 -322
- package/dist/swapper/SwapperWithSigner.js +318 -318
- package/dist/swaps/IAddressSwap.d.ts +22 -22
- package/dist/swaps/IAddressSwap.js +14 -14
- package/dist/swaps/IBTCWalletSwap.d.ts +73 -73
- package/dist/swaps/IBTCWalletSwap.js +18 -18
- package/dist/swaps/IClaimableSwap.d.ts +49 -49
- package/dist/swaps/IClaimableSwap.js +15 -15
- package/dist/swaps/IClaimableSwapWrapper.d.ts +15 -15
- package/dist/swaps/IClaimableSwapWrapper.js +2 -2
- package/dist/swaps/IRefundableSwap.d.ts +43 -43
- package/dist/swaps/IRefundableSwap.js +14 -14
- package/dist/swaps/ISwap.d.ts +453 -453
- package/dist/swaps/ISwap.js +371 -371
- package/dist/swaps/ISwapWithGasDrop.d.ts +21 -21
- package/dist/swaps/ISwapWithGasDrop.js +12 -12
- package/dist/swaps/ISwapWrapper.d.ts +295 -295
- package/dist/swaps/ISwapWrapper.js +373 -373
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +98 -98
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +126 -126
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +139 -139
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +172 -172
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +129 -129
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +167 -167
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +107 -107
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +130 -130
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +162 -162
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +190 -190
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +64 -64
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +82 -82
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +547 -547
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +1419 -1419
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +192 -192
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +432 -432
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +650 -650
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +1577 -1577
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +237 -237
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +525 -525
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +491 -491
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +1463 -1463
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +204 -204
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +406 -406
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +446 -446
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +1097 -1097
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +68 -68
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +117 -117
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +127 -127
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +256 -256
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +252 -252
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +535 -535
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +73 -73
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +155 -155
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +134 -134
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +286 -286
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +694 -694
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +1687 -1687
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +259 -259
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +947 -947
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +302 -302
- package/dist/swaps/trusted/ln/LnForGasSwap.js +625 -625
- package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +40 -40
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +82 -82
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +343 -343
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +698 -698
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +71 -71
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +93 -93
- package/dist/types/AmountData.d.ts +10 -10
- package/dist/types/AmountData.js +2 -2
- package/dist/types/CustomPriceFunction.d.ts +11 -11
- package/dist/types/CustomPriceFunction.js +2 -2
- package/dist/types/PriceInfoType.d.ts +28 -28
- package/dist/types/PriceInfoType.js +57 -57
- package/dist/types/SwapExecutionAction.d.ts +195 -195
- package/dist/types/SwapExecutionAction.js +106 -106
- package/dist/types/SwapExecutionStep.d.ts +144 -144
- package/dist/types/SwapExecutionStep.js +87 -87
- package/dist/types/SwapStateInfo.d.ts +5 -5
- package/dist/types/SwapStateInfo.js +2 -2
- package/dist/types/SwapWithSigner.d.ts +17 -17
- package/dist/types/SwapWithSigner.js +43 -43
- package/dist/types/Token.d.ts +99 -99
- package/dist/types/Token.js +76 -76
- package/dist/types/TokenAmount.d.ts +75 -75
- package/dist/types/TokenAmount.js +85 -85
- package/dist/types/fees/Fee.d.ts +50 -50
- package/dist/types/fees/Fee.js +2 -2
- package/dist/types/fees/FeeBreakdown.d.ts +11 -11
- package/dist/types/fees/FeeBreakdown.js +2 -2
- package/dist/types/fees/PercentagePPM.d.ts +17 -17
- package/dist/types/fees/PercentagePPM.js +18 -18
- package/dist/types/lnurl/LNURLPay.d.ts +61 -61
- package/dist/types/lnurl/LNURLPay.js +31 -31
- package/dist/types/lnurl/LNURLWithdraw.d.ts +48 -48
- package/dist/types/lnurl/LNURLWithdraw.js +27 -27
- package/dist/types/wallets/LightningInvoiceCreateService.d.ts +24 -24
- package/dist/types/wallets/LightningInvoiceCreateService.js +15 -15
- package/dist/types/wallets/MinimalBitcoinWalletInterface.d.ts +23 -23
- package/dist/types/wallets/MinimalBitcoinWalletInterface.js +2 -2
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.d.ts +9 -9
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.js +2 -2
- package/dist/utils/AutomaticClockDriftCorrection.d.ts +1 -1
- package/dist/utils/AutomaticClockDriftCorrection.js +70 -70
- package/dist/utils/BitcoinUtils.d.ts +18 -18
- package/dist/utils/BitcoinUtils.js +174 -174
- package/dist/utils/BitcoinWalletUtils.d.ts +7 -7
- package/dist/utils/BitcoinWalletUtils.js +14 -14
- package/dist/utils/Logger.d.ts +7 -7
- package/dist/utils/Logger.js +12 -12
- package/dist/utils/RetryUtils.d.ts +22 -22
- package/dist/utils/RetryUtils.js +67 -67
- package/dist/utils/SwapUtils.d.ts +88 -88
- package/dist/utils/SwapUtils.js +72 -72
- package/dist/utils/TimeoutUtils.d.ts +17 -17
- package/dist/utils/TimeoutUtils.js +55 -55
- package/dist/utils/TokenUtils.d.ts +19 -19
- package/dist/utils/TokenUtils.js +37 -37
- package/dist/utils/TypeUtils.d.ts +7 -7
- package/dist/utils/TypeUtils.js +2 -2
- package/dist/utils/Utils.d.ts +69 -69
- package/dist/utils/Utils.js +214 -214
- package/package.json +46 -46
- package/src/SmartChainAssets.ts +186 -186
- package/src/api/ApiEndpoints.ts +427 -427
- package/src/api/ApiParser.ts +138 -138
- package/src/api/ApiTypes.ts +229 -229
- package/src/api/SerializedAction.ts +97 -97
- package/src/api/SwapperApi.ts +545 -545
- package/src/api/index.ts +5 -5
- package/src/bitcoin/coinselect2/accumulative.ts +69 -69
- package/src/bitcoin/coinselect2/blackjack.ts +50 -50
- package/src/bitcoin/coinselect2/index.ts +93 -93
- package/src/bitcoin/coinselect2/utils.ts +236 -236
- package/src/bitcoin/wallet/BitcoinWallet.ts +439 -439
- package/src/bitcoin/wallet/IBitcoinWallet.ts +140 -140
- package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +225 -225
- package/src/enums/FeeType.ts +15 -15
- package/src/enums/SwapAmountType.ts +16 -16
- package/src/enums/SwapDirection.ts +15 -15
- package/src/enums/SwapSide.ts +16 -16
- package/src/enums/SwapType.ts +75 -75
- package/src/errors/IntermediaryError.ts +28 -28
- package/src/errors/RequestError.ts +64 -64
- package/src/errors/UserError.ts +15 -15
- package/src/events/UnifiedSwapEventListener.ts +181 -181
- package/src/http/HttpUtils.ts +97 -97
- package/src/http/paramcoders/IParamReader.ts +9 -9
- package/src/http/paramcoders/ParamDecoder.ts +145 -145
- package/src/http/paramcoders/ParamEncoder.ts +40 -40
- package/src/http/paramcoders/SchemaVerifier.ts +153 -153
- package/src/http/paramcoders/client/ResponseParamDecoder.ts +57 -57
- package/src/http/paramcoders/client/StreamParamEncoder.ts +28 -28
- package/src/http/paramcoders/client/StreamingFetchPromise.ts +194 -194
- package/src/index.ts +141 -141
- package/src/intermediaries/Intermediary.ts +280 -280
- package/src/intermediaries/IntermediaryDiscovery.ts +548 -548
- package/src/intermediaries/apis/IntermediaryAPI.ts +1247 -1247
- package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -69
- package/src/lnurl/LNURL.ts +402 -402
- package/src/prices/RedundantSwapPrice.ts +264 -264
- package/src/prices/SingleSwapPrice.ts +50 -50
- package/src/prices/SwapPriceWithChain.ts +194 -194
- package/src/prices/abstract/ICachedSwapPrice.ts +85 -85
- package/src/prices/abstract/IPriceProvider.ts +127 -127
- package/src/prices/abstract/ISwapPrice.ts +390 -390
- package/src/prices/providers/BinancePriceProvider.ts +48 -48
- package/src/prices/providers/CoinGeckoPriceProvider.ts +46 -46
- package/src/prices/providers/CoinPaprikaPriceProvider.ts +49 -49
- package/src/prices/providers/CustomPriceProvider.ts +40 -40
- package/src/prices/providers/KrakenPriceProvider.ts +83 -83
- package/src/prices/providers/OKXPriceProvider.ts +59 -59
- package/src/prices/providers/abstract/ExchangePriceProvider.ts +31 -31
- package/src/prices/providers/abstract/HttpPriceProvider.ts +14 -14
- package/src/storage/IUnifiedStorage.ts +136 -136
- package/src/storage/UnifiedSwapStorage.ts +175 -175
- package/src/storage-browser/IndexedDBUnifiedStorage.ts +350 -350
- package/src/storage-browser/LocalStorageManager.ts +106 -106
- package/src/swapper/Swapper.ts +2557 -2557
- package/src/swapper/SwapperFactory.ts +307 -307
- package/src/swapper/SwapperUtils.ts +610 -610
- package/src/swapper/SwapperWithChain.ts +707 -707
- package/src/swapper/SwapperWithSigner.ts +511 -511
- package/src/swaps/IAddressSwap.ts +30 -30
- package/src/swaps/IBTCWalletSwap.ts +92 -92
- package/src/swaps/IClaimableSwap.ts +65 -65
- package/src/swaps/IClaimableSwapWrapper.ts +17 -17
- package/src/swaps/IRefundableSwap.ts +58 -58
- package/src/swaps/ISwap.ts +775 -775
- package/src/swaps/ISwapWithGasDrop.ts +25 -25
- package/src/swaps/ISwapWrapper.ts +564 -564
- package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +217 -217
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +271 -271
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +284 -284
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +172 -172
- package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +300 -300
- package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +107 -107
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +1670 -1671
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +603 -603
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +1883 -1883
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +752 -752
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +1753 -1753
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +612 -612
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +1327 -1327
- package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +138 -138
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +304 -304
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +787 -787
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +206 -206
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +403 -403
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +2148 -2148
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +1238 -1238
- package/src/swaps/trusted/ln/LnForGasSwap.ts +753 -753
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +90 -90
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +843 -843
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +133 -133
- package/src/types/AmountData.ts +9 -9
- package/src/types/CustomPriceFunction.ts +11 -11
- package/src/types/PriceInfoType.ts +66 -66
- package/src/types/SwapExecutionAction.ts +323 -323
- package/src/types/SwapExecutionStep.ts +224 -224
- package/src/types/SwapStateInfo.ts +6 -6
- package/src/types/SwapWithSigner.ts +61 -61
- package/src/types/Token.ts +163 -163
- package/src/types/TokenAmount.ts +167 -167
- package/src/types/fees/Fee.ts +56 -56
- package/src/types/fees/FeeBreakdown.ts +11 -11
- package/src/types/fees/PercentagePPM.ts +26 -26
- package/src/types/lnurl/LNURLPay.ts +79 -79
- package/src/types/lnurl/LNURLWithdraw.ts +61 -61
- package/src/types/wallets/LightningInvoiceCreateService.ts +30 -30
- package/src/types/wallets/MinimalBitcoinWalletInterface.ts +21 -21
- package/src/types/wallets/MinimalLightningNetworkWalletInterface.ts +9 -9
- package/src/utils/AutomaticClockDriftCorrection.ts +71 -71
- package/src/utils/BitcoinUtils.ts +164 -164
- package/src/utils/BitcoinWalletUtils.ts +15 -15
- package/src/utils/Logger.ts +14 -14
- package/src/utils/RetryUtils.ts +78 -78
- package/src/utils/SwapUtils.ts +99 -99
- package/src/utils/TimeoutUtils.ts +49 -49
- package/src/utils/TokenUtils.ts +33 -33
- package/src/utils/TypeUtils.ts +8 -8
- package/src/utils/Utils.ts +221 -221
|
@@ -1,752 +1,752 @@
|
|
|
1
|
-
import {decode as bolt11Decode, PaymentRequestObject, TagsObject} from "@atomiqlabs/bolt11";
|
|
2
|
-
import {
|
|
3
|
-
ChainSwapType,
|
|
4
|
-
ChainType,
|
|
5
|
-
ClaimEvent,
|
|
6
|
-
InitializeEvent, LightningNetworkApi, LNNodeLiquidity, Messenger,
|
|
7
|
-
RefundEvent, SwapCommitState, SwapCommitStateType
|
|
8
|
-
} from "@atomiqlabs/base";
|
|
9
|
-
import {Intermediary} from "../../../../intermediaries/Intermediary";
|
|
10
|
-
import {Buffer} from "buffer";
|
|
11
|
-
import {UserError} from "../../../../errors/UserError";
|
|
12
|
-
import {IntermediaryError} from "../../../../errors/IntermediaryError";
|
|
13
|
-
import {SwapType} from "../../../../enums/SwapType";
|
|
14
|
-
import {
|
|
15
|
-
extendAbortController, mapArrayToObject, parseHashValueExact32Bytes,
|
|
16
|
-
randomBytes,
|
|
17
|
-
throwIfUndefined
|
|
18
|
-
} from "../../../../utils/Utils";
|
|
19
|
-
import {
|
|
20
|
-
FromBTCLNAutoResponseType,
|
|
21
|
-
IntermediaryAPI
|
|
22
|
-
} from "../../../../intermediaries/apis/IntermediaryAPI";
|
|
23
|
-
import {RequestError} from "../../../../errors/RequestError";
|
|
24
|
-
import {ISwapPrice} from "../../../../prices/abstract/ISwapPrice";
|
|
25
|
-
import {EventEmitter} from "events";
|
|
26
|
-
import {ISwapWrapperOptions, WrapperCtorTokens} from "../../../ISwapWrapper";
|
|
27
|
-
import {UnifiedSwapEventListener} from "../../../../events/UnifiedSwapEventListener";
|
|
28
|
-
import {UnifiedSwapStorage} from "../../../../storage/UnifiedSwapStorage";
|
|
29
|
-
import {ISwap} from "../../../ISwap";
|
|
30
|
-
import {FromBTCLNAutoSwap, FromBTCLNAutoSwapInit, FromBTCLNAutoSwapState} from "./FromBTCLNAutoSwap";
|
|
31
|
-
import {IFromBTCLNDefinition, IFromBTCLNWrapper} from "../IFromBTCLNWrapper";
|
|
32
|
-
import {IClaimableSwapWrapper} from "../../../IClaimableSwapWrapper";
|
|
33
|
-
import {AmountData} from "../../../../types/AmountData";
|
|
34
|
-
import {LNURLWithdrawParamsWithUrl} from "../../../../types/lnurl/LNURLWithdraw";
|
|
35
|
-
import {tryWithRetries} from "../../../../utils/RetryUtils";
|
|
36
|
-
import {AllOptional} from "../../../../utils/TypeUtils";
|
|
37
|
-
import {sha256} from "@noble/hashes/sha2";
|
|
38
|
-
import {fromHumanReadableString} from "../../../../utils/TokenUtils";
|
|
39
|
-
|
|
40
|
-
export type FromBTCLNAutoOptions = {
|
|
41
|
-
/**
|
|
42
|
-
* Instead of letting the SDK generate the preimage/paymentHash pair internally you can pass your computed
|
|
43
|
-
* paymentHash here, this will create the swap with the provided payment hash. Note that swaps created this way
|
|
44
|
-
* won't settle automatically (as the SDK is missing the preimage). Once the HTLC towards the user is created in
|
|
45
|
-
* the {@link FromBTCLNAutoSwapState.CLAIM_COMMITED} state, you should pass the secret preimage manually in the
|
|
46
|
-
* {@link FromBTCLNAutoSwap.waitTillClaimed}, {@link FromBTCLNAutoSwap.claim} or {@link FromBTCLNAutoSwap.txsClaim}
|
|
47
|
-
* functions.
|
|
48
|
-
*
|
|
49
|
-
* Accepts both, a {@link Buffer} and a hexadecimal `string`
|
|
50
|
-
*/
|
|
51
|
-
paymentHash?: Buffer | string,
|
|
52
|
-
/**
|
|
53
|
-
* Optional description to use for the swap lightning network invoice, keep the invoice length below 500 characters
|
|
54
|
-
*/
|
|
55
|
-
description?: string,
|
|
56
|
-
/**
|
|
57
|
-
* Optional description hash to use for the lightning network invoice, useful when returning the invoice as part of
|
|
58
|
-
* an LNURL-pay service endpoint.
|
|
59
|
-
*
|
|
60
|
-
* Accepts both, a {@link Buffer} and a hexadecimal `string`
|
|
61
|
-
*/
|
|
62
|
-
descriptionHash?: Buffer | string,
|
|
63
|
-
/**
|
|
64
|
-
* Optional additional native token to receive as an output of the swap (e.g. STRK on Starknet or cBTC on Citrea).
|
|
65
|
-
* When passed as a `bigint` it is specified in base units of the token and in `string` it is the human readable
|
|
66
|
-
* decimal format.
|
|
67
|
-
*/
|
|
68
|
-
gasAmount?: bigint | string,
|
|
69
|
-
/**
|
|
70
|
-
* A flag to skip checking whether the lightning network node of the LP has enough channel liquidity to facilitate
|
|
71
|
-
* the swap.
|
|
72
|
-
*/
|
|
73
|
-
unsafeSkipLnNodeCheck?: boolean,
|
|
74
|
-
/**
|
|
75
|
-
* A flag to attach 0 watchtower fee to the swap, this would make the settlement unattractive for the watchtowers
|
|
76
|
-
* and therefore automatic settlement for such swaps will not be possible, you will have to settle manually
|
|
77
|
-
* with {@link FromBTCLNSwap.claim} or {@link FromBTCLNSwap.txsClaim} functions.
|
|
78
|
-
*/
|
|
79
|
-
unsafeZeroWatchtowerFee?: boolean,
|
|
80
|
-
/**
|
|
81
|
-
* A safety factor to use when estimating the watchtower fee to attach to the swap (this has to cover the gas fee
|
|
82
|
-
* of watchtowers settling the swap). A higher multiple here would mean that a swap is more attractive for
|
|
83
|
-
* watchtowers to settle automatically.
|
|
84
|
-
*
|
|
85
|
-
* Uses a `1.25` multiple by default (i.e. the current network fee is multiplied by 1.25 and then used to estimate
|
|
86
|
-
* the settlement gas fee cost)
|
|
87
|
-
*/
|
|
88
|
-
feeSafetyFactor?: number
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
export type FromBTCLNAutoWrapperOptions = ISwapWrapperOptions & {
|
|
92
|
-
safetyFactor: number,
|
|
93
|
-
bitcoinBlocktime: number,
|
|
94
|
-
unsafeSkipLnNodeCheck: boolean
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
export type FromBTCLNAutoDefinition<T extends ChainType> = IFromBTCLNDefinition<T, FromBTCLNAutoWrapper<T>, FromBTCLNAutoSwap<T>>;
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* New escrow based (HTLC) swaps for Bitcoin Lightning -> Smart chain swaps not requiring manual settlement on
|
|
101
|
-
* the destination by the user, and instead letting the LP initiate the escrow. Permissionless watchtower network
|
|
102
|
-
* handles the claiming of HTLC, with the swap secret broadcasted over Nostr. Also adds a possibility for the user
|
|
103
|
-
* to receive a native token on the destination chain as part of the swap (a "gas drop" feature).
|
|
104
|
-
*
|
|
105
|
-
* @category Swaps/Lightning → Smart chain
|
|
106
|
-
*/
|
|
107
|
-
export class FromBTCLNAutoWrapper<
|
|
108
|
-
T extends ChainType
|
|
109
|
-
> extends IFromBTCLNWrapper<T, FromBTCLNAutoDefinition<T>, FromBTCLNAutoWrapperOptions> implements IClaimableSwapWrapper<FromBTCLNAutoSwap<T>> {
|
|
110
|
-
|
|
111
|
-
public readonly TYPE: SwapType.FROM_BTCLN_AUTO = SwapType.FROM_BTCLN_AUTO;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* @internal
|
|
115
|
-
*/
|
|
116
|
-
protected readonly tickSwapState = [
|
|
117
|
-
FromBTCLNAutoSwapState.PR_CREATED,
|
|
118
|
-
FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED,
|
|
119
|
-
FromBTCLNAutoSwapState.PR_PAID,
|
|
120
|
-
FromBTCLNAutoSwapState.CLAIM_COMMITED
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* @internal
|
|
125
|
-
*/
|
|
126
|
-
readonly _pendingSwapStates = [
|
|
127
|
-
FromBTCLNAutoSwapState.PR_CREATED,
|
|
128
|
-
FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED,
|
|
129
|
-
FromBTCLNAutoSwapState.PR_PAID,
|
|
130
|
-
FromBTCLNAutoSwapState.CLAIM_COMMITED,
|
|
131
|
-
FromBTCLNAutoSwapState.EXPIRED
|
|
132
|
-
];
|
|
133
|
-
/**
|
|
134
|
-
* @internal
|
|
135
|
-
*/
|
|
136
|
-
readonly _claimableSwapStates = [FromBTCLNAutoSwapState.CLAIM_COMMITED];
|
|
137
|
-
/**
|
|
138
|
-
* @internal
|
|
139
|
-
*/
|
|
140
|
-
readonly _swapDeserializer = FromBTCLNAutoSwap;
|
|
141
|
-
/**
|
|
142
|
-
* @internal
|
|
143
|
-
*/
|
|
144
|
-
readonly _messenger: Messenger;
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* @param chainIdentifier
|
|
148
|
-
* @param unifiedStorage Storage interface for the current environment
|
|
149
|
-
* @param unifiedChainEvents On-chain event listener
|
|
150
|
-
* @param chain
|
|
151
|
-
* @param prices Swap pricing handler
|
|
152
|
-
* @param tokens
|
|
153
|
-
* @param versionedContracts
|
|
154
|
-
* @param lnApi
|
|
155
|
-
* @param messenger
|
|
156
|
-
* @param lpApi
|
|
157
|
-
* @param options
|
|
158
|
-
* @param events Instance to use for emitting events
|
|
159
|
-
*/
|
|
160
|
-
constructor(
|
|
161
|
-
chainIdentifier: string,
|
|
162
|
-
unifiedStorage: UnifiedSwapStorage<T>,
|
|
163
|
-
unifiedChainEvents: UnifiedSwapEventListener<T>,
|
|
164
|
-
chain: T["ChainInterface"],
|
|
165
|
-
prices: ISwapPrice,
|
|
166
|
-
tokens: WrapperCtorTokens,
|
|
167
|
-
versionedContracts: {
|
|
168
|
-
[version: string]: {
|
|
169
|
-
swapContract: T["Contract"],
|
|
170
|
-
swapDataConstructor: new (data: any) => T["Data"]
|
|
171
|
-
}
|
|
172
|
-
},
|
|
173
|
-
lnApi: LightningNetworkApi,
|
|
174
|
-
messenger: Messenger,
|
|
175
|
-
lpApi: IntermediaryAPI,
|
|
176
|
-
options?: AllOptional<FromBTCLNAutoWrapperOptions>,
|
|
177
|
-
events?: EventEmitter<{swapState: [ISwap]}>
|
|
178
|
-
) {
|
|
179
|
-
super(
|
|
180
|
-
chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lnApi, lpApi,
|
|
181
|
-
{
|
|
182
|
-
...options,
|
|
183
|
-
safetyFactor: options?.safetyFactor ?? 2,
|
|
184
|
-
bitcoinBlocktime: options?.bitcoinBlocktime ?? 10*60,
|
|
185
|
-
unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? false
|
|
186
|
-
},
|
|
187
|
-
events
|
|
188
|
-
);
|
|
189
|
-
this._messenger = messenger;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* @inheritDoc
|
|
194
|
-
* @internal
|
|
195
|
-
*/
|
|
196
|
-
protected async processEventInitialize(swap: FromBTCLNAutoSwap<T>, event: InitializeEvent<T["Data"]>): Promise<boolean> {
|
|
197
|
-
if(swap._state===FromBTCLNAutoSwapState.PR_PAID || swap._state===FromBTCLNAutoSwapState.PR_CREATED || swap._state===FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED) {
|
|
198
|
-
if(swap._data==null) {
|
|
199
|
-
//Obtain data from the initialize event
|
|
200
|
-
const eventData = await event.swapData();
|
|
201
|
-
if(eventData==null) {
|
|
202
|
-
this.logger.error("processEventInitialize("+swap.getId()+"): Error when fetching swap data for swap, null returned!");
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
|
-
try {
|
|
206
|
-
await swap._saveRealSwapData(eventData, false);
|
|
207
|
-
this.logger.info("processEventInitialize("+swap.getId()+"): Successfully taken swap data from on-chain event!");
|
|
208
|
-
} catch (e) {
|
|
209
|
-
this.logger.error("processEventInitialize("+swap.getId()+"): Error when saving swap data for swap: ", e);
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if(swap._getEscrowHash()!==event.escrowHash) {
|
|
215
|
-
this.logger.error("processEventInitialize("+swap.getId()+"): Error when processing event, escrow hashes don't match!");
|
|
216
|
-
return false;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
swap._commitedAt ??= Date.now();
|
|
220
|
-
swap._state = FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
221
|
-
if(swap.hasSecretPreimage()) swap._broadcastSecret().catch(e => {
|
|
222
|
-
this.logger.error("processEventInitialize("+swap.getId()+"): Error when broadcasting swap secret: ", e);
|
|
223
|
-
});
|
|
224
|
-
return true;
|
|
225
|
-
}
|
|
226
|
-
return false;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* @inheritDoc
|
|
231
|
-
* @internal
|
|
232
|
-
*/
|
|
233
|
-
protected processEventClaim(swap: FromBTCLNAutoSwap<T>, event: ClaimEvent<T["Data"]>): Promise<boolean> {
|
|
234
|
-
if(swap._state!==FromBTCLNAutoSwapState.FAILED && swap._state!==FromBTCLNAutoSwapState.CLAIM_CLAIMED) {
|
|
235
|
-
swap._state = FromBTCLNAutoSwapState.CLAIM_CLAIMED;
|
|
236
|
-
swap._setSwapSecret(event.result);
|
|
237
|
-
return Promise.resolve(true);
|
|
238
|
-
}
|
|
239
|
-
return Promise.resolve(false);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* @inheritDoc
|
|
244
|
-
* @internal
|
|
245
|
-
*/
|
|
246
|
-
protected processEventRefund(swap: FromBTCLNAutoSwap<T>, event: RefundEvent<T["Data"]>): Promise<boolean> {
|
|
247
|
-
if(swap._state!==FromBTCLNAutoSwapState.CLAIM_CLAIMED && swap._state!==FromBTCLNAutoSwapState.FAILED) {
|
|
248
|
-
swap._state = FromBTCLNAutoSwapState.FAILED;
|
|
249
|
-
return Promise.resolve(true);
|
|
250
|
-
}
|
|
251
|
-
return Promise.resolve(false);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Pre-fetches claimer (watchtower) bounty data for the swap. Doesn't throw, instead returns null and aborts the
|
|
256
|
-
* provided abortController
|
|
257
|
-
*
|
|
258
|
-
* @param signer Smartchain signer address initiating the swap
|
|
259
|
-
* @param amountData
|
|
260
|
-
* @param options Options as passed to the swap creation function
|
|
261
|
-
* @param abortController
|
|
262
|
-
*
|
|
263
|
-
* @param contractVersions
|
|
264
|
-
* @private
|
|
265
|
-
*/
|
|
266
|
-
private preFetchClaimerBounty(
|
|
267
|
-
signer: string,
|
|
268
|
-
amountData: AmountData,
|
|
269
|
-
options: {feeSafetyFactor: number, unsafeZeroWatchtowerFee: boolean},
|
|
270
|
-
abortController: AbortController,
|
|
271
|
-
contractVersions: string[]
|
|
272
|
-
): {[chainVersion: string]: Promise<bigint | undefined>} {
|
|
273
|
-
return mapArrayToObject(contractVersions, async (contractVersion) => {
|
|
274
|
-
if(options.unsafeZeroWatchtowerFee) return 0n;
|
|
275
|
-
|
|
276
|
-
const dummyAmount = BigInt(Math.floor(Math.random()* 0x1000000));
|
|
277
|
-
const dummySwapData = await this._contract(contractVersion).createSwapData(
|
|
278
|
-
ChainSwapType.HTLC, this._chain.randomAddress(), signer, amountData.token,
|
|
279
|
-
dummyAmount, this._contract(contractVersion).getHashForHtlc(randomBytes(32)).toString("hex"),
|
|
280
|
-
this.getRandomSequence(), BigInt(Math.floor(Date.now()/1000)), false, true,
|
|
281
|
-
BigInt(Math.floor(Math.random() * 0x10000)), BigInt(Math.floor(Math.random() * 0x10000))
|
|
282
|
-
);
|
|
283
|
-
|
|
284
|
-
try {
|
|
285
|
-
const result = await this._contract(contractVersion).getClaimFee(this._chain.randomAddress(), dummySwapData);
|
|
286
|
-
return result * BigInt(Math.floor(options.feeSafetyFactor*1000000)) / 1_000_000n
|
|
287
|
-
} catch (e) {
|
|
288
|
-
abortController.abort(e);
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Verifies response returned from intermediary
|
|
295
|
-
*
|
|
296
|
-
* @param resp Response as returned by the intermediary
|
|
297
|
-
* @param amountData
|
|
298
|
-
* @param lp Intermediary
|
|
299
|
-
* @param options Options as passed to the swap creation function
|
|
300
|
-
* @param decodedPr Decoded bolt11 lightning network invoice
|
|
301
|
-
* @param paymentHash Expected payment hash of the bolt11 lightning network invoice
|
|
302
|
-
* @param claimerBounty Claimer bounty as request by the user
|
|
303
|
-
*
|
|
304
|
-
* @throws {IntermediaryError} in case the response is invalid
|
|
305
|
-
*
|
|
306
|
-
* @private
|
|
307
|
-
*/
|
|
308
|
-
private verifyReturnedData(
|
|
309
|
-
resp: FromBTCLNAutoResponseType,
|
|
310
|
-
amountData: AmountData,
|
|
311
|
-
lp: Intermediary,
|
|
312
|
-
options: {gasAmount: bigint, description?: string, descriptionHash?: Buffer},
|
|
313
|
-
decodedPr: PaymentRequestObject & {tagsObject: TagsObject},
|
|
314
|
-
paymentHash: Buffer,
|
|
315
|
-
claimerBounty: bigint
|
|
316
|
-
): void {
|
|
317
|
-
if(lp.getAddress(this.chainIdentifier)!==resp.intermediaryKey) throw new IntermediaryError("Invalid intermediary address/pubkey");
|
|
318
|
-
|
|
319
|
-
if(options.descriptionHash!=null && decodedPr.tagsObject.purpose_commit_hash!==options.descriptionHash.toString("hex"))
|
|
320
|
-
throw new IntermediaryError("Invalid pr returned - description hash");
|
|
321
|
-
|
|
322
|
-
if(options.description!=null && decodedPr.tagsObject.description!==options.description)
|
|
323
|
-
throw new IntermediaryError("Invalid pr returned - description");
|
|
324
|
-
|
|
325
|
-
if(
|
|
326
|
-
decodedPr.tagsObject.payment_hash==null ||
|
|
327
|
-
!Buffer.from(decodedPr.tagsObject.payment_hash, "hex").equals(paymentHash)
|
|
328
|
-
) throw new IntermediaryError("Invalid pr returned - payment hash");
|
|
329
|
-
|
|
330
|
-
if(decodedPr.millisatoshis==null) throw new IntermediaryError("Invalid pr returned - msat field");
|
|
331
|
-
|
|
332
|
-
const amountIn = (BigInt(decodedPr.millisatoshis) + 999n) / 1000n;
|
|
333
|
-
if(resp.btcAmountGas + resp.btcAmountSwap !== amountIn) throw new IntermediaryError("Invalid total btc returned");
|
|
334
|
-
if(resp.gasSwapFeeBtc + resp.swapFeeBtc !== resp.totalFeeBtc) throw new IntermediaryError("Invalid total btc fee returned");
|
|
335
|
-
if(resp.claimerBounty !== claimerBounty) throw new IntermediaryError("Invalid claimer bounty");
|
|
336
|
-
if(resp.totalGas !== options.gasAmount) throw new IntermediaryError("Invalid total gas amount");
|
|
337
|
-
if(!amountData.exactIn) {
|
|
338
|
-
if(resp.total != amountData.amount) throw new IntermediaryError("Invalid amount returned");
|
|
339
|
-
} else {
|
|
340
|
-
if(amountIn !== amountData.amount) throw new IntermediaryError("Invalid payment request returned, amount mismatch");
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Returns a newly created Lightning -> Smart chain swap using the HTLC based escrow swap protocol,
|
|
346
|
-
* where watchtowers handle the automatic settlement of the swap on the destination chain. Also allows
|
|
347
|
-
* specifying additional "gas drop" native token that the receipient receives on the destination chain
|
|
348
|
-
* in the `options` argument. The user has to pay a bolt11 invoice on the input lightning network side.
|
|
349
|
-
*
|
|
350
|
-
* @param recipient Recipient's address on the destination chain
|
|
351
|
-
* @param amountData Amount, token and exact input/output data for to swap
|
|
352
|
-
* @param lps An array of intermediaries (LPs) to get the quotes from
|
|
353
|
-
* @param options Optional additional quote options
|
|
354
|
-
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
|
|
355
|
-
* @param abortSignal Abort signal
|
|
356
|
-
* @param preFetches Optional pre-fetches for speeding up the quoting process (mainly used internally)
|
|
357
|
-
*/
|
|
358
|
-
create(
|
|
359
|
-
recipient: string,
|
|
360
|
-
amountData: AmountData,
|
|
361
|
-
lps: Intermediary[],
|
|
362
|
-
options?: FromBTCLNAutoOptions,
|
|
363
|
-
additionalParams?: Record<string, any>,
|
|
364
|
-
abortSignal?: AbortSignal,
|
|
365
|
-
preFetches?: {
|
|
366
|
-
pricePrefetchPromise: Promise<bigint | undefined>,
|
|
367
|
-
usdPricePrefetchPromise: Promise<number | undefined>,
|
|
368
|
-
claimerBountyPrefetch: {[contractVersion: string]: Promise<bigint | undefined>},
|
|
369
|
-
gasTokenPricePrefetchPromise?: Promise<bigint | undefined>,
|
|
370
|
-
}
|
|
371
|
-
): {
|
|
372
|
-
quote: Promise<FromBTCLNAutoSwap<T>>,
|
|
373
|
-
intermediary: Intermediary
|
|
374
|
-
}[] {
|
|
375
|
-
if(!this.isInitialized) throw new Error("Not initialized, call init() first!");
|
|
376
|
-
|
|
377
|
-
const _options = {
|
|
378
|
-
paymentHash: parseHashValueExact32Bytes(options?.paymentHash, "payment hash"),
|
|
379
|
-
unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck,
|
|
380
|
-
gasAmount: this.parseGasAmount(options?.gasAmount),
|
|
381
|
-
feeSafetyFactor: options?.feeSafetyFactor ?? 1.25, //No need to add much of a margin, since the claim should happen rather soon
|
|
382
|
-
unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
|
|
383
|
-
description: options?.description,
|
|
384
|
-
descriptionHash: parseHashValueExact32Bytes(options?.descriptionHash, "description hash")
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if(
|
|
389
|
-
_options.gasAmount!==0n &&
|
|
390
|
-
(
|
|
391
|
-
this._chain.shouldGetNativeTokenDrop!=null
|
|
392
|
-
? !this._chain.shouldGetNativeTokenDrop(amountData.token)
|
|
393
|
-
: amountData.token===this._chain.getNativeCurrencyAddress()
|
|
394
|
-
)
|
|
395
|
-
) throw new UserError("Cannot specify `gasAmount` for swaps to a native token!");
|
|
396
|
-
|
|
397
|
-
if(_options.description!=null && Buffer.byteLength(_options.description, "utf8") > 500)
|
|
398
|
-
throw new UserError("Invalid description length");
|
|
399
|
-
|
|
400
|
-
const lpVersions = Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
|
|
401
|
-
|
|
402
|
-
let secret: Buffer | undefined;
|
|
403
|
-
let paymentHash: Buffer;
|
|
404
|
-
if(_options?.paymentHash!=null) {
|
|
405
|
-
paymentHash = _options.paymentHash;
|
|
406
|
-
} else {
|
|
407
|
-
({secret, paymentHash} = this.getSecretAndHash());
|
|
408
|
-
}
|
|
409
|
-
const _hash = mapArrayToObject(lpVersions, (contractVersion: string) => {
|
|
410
|
-
return this._contract(contractVersion).getHashForHtlc(paymentHash).toString("hex");
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
const nativeTokenAddress = this._chain.getNativeCurrencyAddress();
|
|
414
|
-
|
|
415
|
-
const _abortController = extendAbortController(abortSignal);
|
|
416
|
-
|
|
417
|
-
const _preFetches = preFetches ?? {
|
|
418
|
-
pricePrefetchPromise: this.preFetchPrice(amountData, _abortController.signal),
|
|
419
|
-
usdPricePrefetchPromise: this.preFetchUsdPrice(_abortController.signal),
|
|
420
|
-
claimerBountyPrefetch: this.preFetchClaimerBounty(recipient, amountData, _options, _abortController, lpVersions),
|
|
421
|
-
gasTokenPricePrefetchPromise: _options.gasAmount!==0n || !_options.unsafeZeroWatchtowerFee ?
|
|
422
|
-
this.preFetchPrice({token: nativeTokenAddress}, _abortController.signal) :
|
|
423
|
-
undefined
|
|
424
|
-
};
|
|
425
|
-
|
|
426
|
-
return lps.map(lp => {
|
|
427
|
-
return {
|
|
428
|
-
intermediary: lp,
|
|
429
|
-
quote: (async () => {
|
|
430
|
-
if(lp.services[SwapType.FROM_BTCLN_AUTO]==null) throw new Error("LP service for processing from btcln auto swaps not found!");
|
|
431
|
-
const version = lp.getContractVersion(this.chainIdentifier);
|
|
432
|
-
|
|
433
|
-
const abortController = extendAbortController(_abortController.signal);
|
|
434
|
-
|
|
435
|
-
const liquidityPromise: Promise<bigint | undefined> = this.preFetchIntermediaryLiquidity(amountData, lp, abortController, version);
|
|
436
|
-
|
|
437
|
-
const {lnCapacityPromise, resp} = await tryWithRetries(async(retryCount: number) => {
|
|
438
|
-
const {lnPublicKey, response} = this._lpApi.initFromBTCLNAuto(
|
|
439
|
-
this.chainIdentifier, lp.url,
|
|
440
|
-
{
|
|
441
|
-
paymentHash,
|
|
442
|
-
amount: amountData.amount,
|
|
443
|
-
claimer: recipient,
|
|
444
|
-
token: amountData.token.toString(),
|
|
445
|
-
description: _options.description,
|
|
446
|
-
descriptionHash: _options.descriptionHash,
|
|
447
|
-
exactOut: !amountData.exactIn,
|
|
448
|
-
additionalParams,
|
|
449
|
-
gasToken: this._chain.getNativeCurrencyAddress(),
|
|
450
|
-
gasAmount: _options.gasAmount,
|
|
451
|
-
claimerBounty: throwIfUndefined(_preFetches.claimerBountyPrefetch[version], "Watchtower fee pre-fetch failed!")
|
|
452
|
-
},
|
|
453
|
-
this._options.postRequestTimeout, abortController.signal, retryCount>0 ? false : undefined
|
|
454
|
-
);
|
|
455
|
-
|
|
456
|
-
let lnCapacityPromise: Promise<LNNodeLiquidity | null> | undefined;
|
|
457
|
-
if(!_options.unsafeSkipLnNodeCheck) {
|
|
458
|
-
lnCapacityPromise = this.preFetchLnCapacity(lnPublicKey);
|
|
459
|
-
} else lnPublicKey.catch(() => {});
|
|
460
|
-
|
|
461
|
-
return {
|
|
462
|
-
lnCapacityPromise,
|
|
463
|
-
resp: await response
|
|
464
|
-
};
|
|
465
|
-
}, undefined, RequestError, abortController.signal);
|
|
466
|
-
|
|
467
|
-
const decodedPr = bolt11Decode(resp.pr);
|
|
468
|
-
if(decodedPr.millisatoshis==null) throw new IntermediaryError("Invalid returned swap invoice, no msat amount field");
|
|
469
|
-
if(decodedPr.timeExpireDate==null) throw new IntermediaryError("Invalid returned swap invoice, no expiry date field");
|
|
470
|
-
const amountIn = (BigInt(decodedPr.millisatoshis) + 999n) / 1000n;
|
|
471
|
-
const claimerBounty = (await _preFetches.claimerBountyPrefetch[version])!;
|
|
472
|
-
|
|
473
|
-
try {
|
|
474
|
-
this.verifyReturnedData(resp, amountData, lp, _options, decodedPr, paymentHash, claimerBounty);
|
|
475
|
-
const [pricingInfo, gasPricingInfo] = await Promise.all([
|
|
476
|
-
this.verifyReturnedPrice(
|
|
477
|
-
lp.services[SwapType.FROM_BTCLN_AUTO],
|
|
478
|
-
false, resp.btcAmountSwap,
|
|
479
|
-
resp.total,
|
|
480
|
-
amountData.token, {swapFeeBtc: resp.swapFeeBtc}, _preFetches.pricePrefetchPromise, _preFetches.usdPricePrefetchPromise, abortController.signal
|
|
481
|
-
),
|
|
482
|
-
_options.gasAmount===0n ? Promise.resolve(undefined) : this.verifyReturnedPrice(
|
|
483
|
-
{...lp.services[SwapType.FROM_BTCLN_AUTO], swapBaseFee: 0}, //Base fee should be charged only on the amount, not on gas
|
|
484
|
-
false, resp.btcAmountGas,
|
|
485
|
-
resp.totalGas + resp.claimerBounty,
|
|
486
|
-
nativeTokenAddress, {swapFeeBtc: resp.gasSwapFeeBtc}, _preFetches.gasTokenPricePrefetchPromise, _preFetches.usdPricePrefetchPromise, abortController.signal
|
|
487
|
-
),
|
|
488
|
-
this.verifyIntermediaryLiquidity(resp.total, throwIfUndefined(liquidityPromise, "LP liquidity pre-fetch failed!")),
|
|
489
|
-
_options.unsafeSkipLnNodeCheck ? Promise.resolve() : this.verifyLnNodeCapacity(lp, decodedPr, lnCapacityPromise, abortController.signal)
|
|
490
|
-
]);
|
|
491
|
-
|
|
492
|
-
const swapInit: FromBTCLNAutoSwapInit<T["Data"]> = {
|
|
493
|
-
pricingInfo,
|
|
494
|
-
url: lp.url,
|
|
495
|
-
expiry: decodedPr.timeExpireDate*1000,
|
|
496
|
-
|
|
497
|
-
swapFee: resp.swapFee,
|
|
498
|
-
gasSwapFee: resp.gasSwapFee,
|
|
499
|
-
|
|
500
|
-
swapFeeBtc: resp.swapFeeBtc,
|
|
501
|
-
gasSwapFeeBtc: resp.gasSwapFeeBtc,
|
|
502
|
-
|
|
503
|
-
btcAmountGas: resp.btcAmountGas,
|
|
504
|
-
btcAmountSwap: resp.btcAmountSwap,
|
|
505
|
-
|
|
506
|
-
gasPricingInfo,
|
|
507
|
-
|
|
508
|
-
initialSwapData: await this._contract(version).createSwapData(
|
|
509
|
-
ChainSwapType.HTLC, lp.getAddress(this.chainIdentifier), recipient, amountData.token,
|
|
510
|
-
resp.total, _hash[version],
|
|
511
|
-
this.getRandomSequence(), BigInt(Math.floor(Date.now()/1000)), false, true,
|
|
512
|
-
_options.gasAmount + resp.claimerBounty, resp.claimerBounty, nativeTokenAddress
|
|
513
|
-
),
|
|
514
|
-
pr: resp.pr,
|
|
515
|
-
secret: secret?.toString("hex"),
|
|
516
|
-
exactIn: amountData.exactIn ?? true,
|
|
517
|
-
contractVersion: version
|
|
518
|
-
};
|
|
519
|
-
const quote = new FromBTCLNAutoSwap<T>(this, swapInit);
|
|
520
|
-
return quote;
|
|
521
|
-
} catch (e) {
|
|
522
|
-
abortController.abort(e);
|
|
523
|
-
throw e;
|
|
524
|
-
}
|
|
525
|
-
})()
|
|
526
|
-
}
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
/**
|
|
531
|
-
* Returns a newly created Lightning -> Smart chain swap using the HTLC based escrow swap protocol,
|
|
532
|
-
* where watchtowers handle the automatic settlement of the swap on the destination chain. Also allows
|
|
533
|
-
* specifying additional "gas drop" native token that the receipient receives on the destination chain
|
|
534
|
-
* in the `options` argument. The swap is created with an LNURL-withdraw link which will be used to pay
|
|
535
|
-
* the generated bolt11 invoice automatically when {@link FromBTCLNSwap.waitForPayment} is called on the
|
|
536
|
-
* swap.
|
|
537
|
-
*
|
|
538
|
-
* @param recipient Recipient's address on the destination chain
|
|
539
|
-
* @param lnurl LNURL-withdraw link to pull the funds from
|
|
540
|
-
* @param amountData Amount, token and exact input/output data for to swap
|
|
541
|
-
* @param lps An array of intermediaries (LPs) to get the quotes from
|
|
542
|
-
* @param options Optional additional quote options
|
|
543
|
-
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
|
|
544
|
-
* @param abortSignal Abort signal
|
|
545
|
-
*/
|
|
546
|
-
async createViaLNURL(
|
|
547
|
-
recipient: string,
|
|
548
|
-
lnurl: string | LNURLWithdrawParamsWithUrl,
|
|
549
|
-
amountData: AmountData,
|
|
550
|
-
lps: Intermediary[],
|
|
551
|
-
options?: FromBTCLNAutoOptions,
|
|
552
|
-
additionalParams?: Record<string, any>,
|
|
553
|
-
abortSignal?: AbortSignal
|
|
554
|
-
): Promise<{
|
|
555
|
-
quote: Promise<FromBTCLNAutoSwap<T>>,
|
|
556
|
-
intermediary: Intermediary
|
|
557
|
-
}[]> {
|
|
558
|
-
if(!this.isInitialized) throw new Error("Not initialized, call init() first!");
|
|
559
|
-
|
|
560
|
-
const _options = {
|
|
561
|
-
paymentHash: parseHashValueExact32Bytes(options?.paymentHash, "payment hash"),
|
|
562
|
-
unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck,
|
|
563
|
-
gasAmount: this.parseGasAmount(options?.gasAmount),
|
|
564
|
-
feeSafetyFactor: options?.feeSafetyFactor ?? 1.25, //No need to add much of a margin, since the claim should happen rather soon
|
|
565
|
-
unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
|
|
566
|
-
description: options?.description,
|
|
567
|
-
descriptionHash: parseHashValueExact32Bytes(options?.descriptionHash, "description hash")
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
const lpVersions = Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
|
|
571
|
-
|
|
572
|
-
const abortController = extendAbortController(abortSignal);
|
|
573
|
-
const preFetches = {
|
|
574
|
-
pricePrefetchPromise: this.preFetchPrice(amountData, abortController.signal),
|
|
575
|
-
usdPricePrefetchPromise: this.preFetchUsdPrice(abortController.signal),
|
|
576
|
-
gasTokenPricePrefetchPromise: _options.gasAmount!==0n || !_options.unsafeZeroWatchtowerFee ?
|
|
577
|
-
this.preFetchPrice({token: this._chain.getNativeCurrencyAddress()}, abortController.signal) :
|
|
578
|
-
undefined,
|
|
579
|
-
claimerBountyPrefetch: this.preFetchClaimerBounty(recipient, amountData, _options, abortController, lpVersions)
|
|
580
|
-
};
|
|
581
|
-
|
|
582
|
-
try {
|
|
583
|
-
const exactOutAmountPromise: Promise<bigint | undefined> | undefined = !amountData.exactIn ? preFetches.pricePrefetchPromise.then(price =>
|
|
584
|
-
this._prices.getToBtcSwapAmount(this.chainIdentifier, amountData.amount, amountData.token, abortController.signal, price)
|
|
585
|
-
).catch(e => {
|
|
586
|
-
abortController.abort(e);
|
|
587
|
-
return undefined;
|
|
588
|
-
}) : undefined;
|
|
589
|
-
|
|
590
|
-
const withdrawRequest = await this.getLNURLWithdraw(lnurl, abortController.signal);
|
|
591
|
-
|
|
592
|
-
const min = BigInt(withdrawRequest.minWithdrawable) / 1000n;
|
|
593
|
-
const max = BigInt(withdrawRequest.maxWithdrawable) / 1000n;
|
|
594
|
-
|
|
595
|
-
if(amountData.exactIn) {
|
|
596
|
-
if(amountData.amount < min) throw new UserError("Amount less than LNURL-withdraw minimum");
|
|
597
|
-
if(amountData.amount > max) throw new UserError("Amount more than LNURL-withdraw maximum");
|
|
598
|
-
} else {
|
|
599
|
-
const amount = (await exactOutAmountPromise)!;
|
|
600
|
-
abortController.signal.throwIfAborted();
|
|
601
|
-
|
|
602
|
-
if((amount * 95n / 100n) < min) throw new UserError("Amount less than LNURL-withdraw minimum");
|
|
603
|
-
if((amount * 105n / 100n) > max) throw new UserError("Amount more than LNURL-withdraw maximum");
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
return this.create(recipient, amountData, lps, _options, additionalParams, abortSignal, preFetches).map(data => {
|
|
607
|
-
return {
|
|
608
|
-
quote: data.quote.then(quote => {
|
|
609
|
-
quote._setLNURLData(
|
|
610
|
-
withdrawRequest.url,
|
|
611
|
-
withdrawRequest.k1,
|
|
612
|
-
withdrawRequest.callback
|
|
613
|
-
);
|
|
614
|
-
|
|
615
|
-
const amountIn = quote.getInput().rawAmount!;
|
|
616
|
-
if(amountIn < min) throw new UserError("Amount less than LNURL-withdraw minimum");
|
|
617
|
-
if(amountIn > max) throw new UserError("Amount more than LNURL-withdraw maximum");
|
|
618
|
-
|
|
619
|
-
return quote;
|
|
620
|
-
}),
|
|
621
|
-
intermediary: data.intermediary
|
|
622
|
-
}
|
|
623
|
-
});
|
|
624
|
-
} catch (e) {
|
|
625
|
-
abortController.abort(e);
|
|
626
|
-
throw e;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/**
|
|
631
|
-
* @inheritDoc
|
|
632
|
-
* @internal
|
|
633
|
-
*/
|
|
634
|
-
protected async _checkPastSwaps(pastSwaps: FromBTCLNAutoSwap<T>[]): Promise<{
|
|
635
|
-
changedSwaps: FromBTCLNAutoSwap<T>[];
|
|
636
|
-
removeSwaps: FromBTCLNAutoSwap<T>[]
|
|
637
|
-
}> {
|
|
638
|
-
const changedSwapSet: Set<FromBTCLNAutoSwap<T>> = new Set();
|
|
639
|
-
|
|
640
|
-
const swapExpiredStatus: {[id: string]: boolean} = {};
|
|
641
|
-
const checkStatusSwaps: {[contractVersion: string]: (FromBTCLNAutoSwap<T> & {_data: T["Data"]})[]} = {};
|
|
642
|
-
|
|
643
|
-
await Promise.all(pastSwaps.map(async (pastSwap) => {
|
|
644
|
-
if(pastSwap._shouldCheckIntermediary()) {
|
|
645
|
-
try {
|
|
646
|
-
const result = await pastSwap._checkIntermediaryPaymentReceived(false);
|
|
647
|
-
if(result!=null) {
|
|
648
|
-
changedSwapSet.add(pastSwap);
|
|
649
|
-
}
|
|
650
|
-
} catch (e) {
|
|
651
|
-
this.logger.error(`_checkPastSwaps(): Failed to contact LP regarding swap ${pastSwap.getId()}, error: `, e);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
if(pastSwap._shouldFetchExpiryStatus()) {
|
|
655
|
-
//Check expiry
|
|
656
|
-
swapExpiredStatus[pastSwap.getId()] = await pastSwap._verifyQuoteDefinitelyExpired();
|
|
657
|
-
}
|
|
658
|
-
if(pastSwap._shouldFetchOnchainState()) {
|
|
659
|
-
//Add to swaps for which status should be checked
|
|
660
|
-
if(pastSwap._data!=null) (checkStatusSwaps[pastSwap._contractVersion ?? "v1"] ??= []).push(pastSwap as FromBTCLNAutoSwap<T> & {_data: T["Data"]});
|
|
661
|
-
}
|
|
662
|
-
}));
|
|
663
|
-
|
|
664
|
-
for(let version in checkStatusSwaps) {
|
|
665
|
-
if (this._versionedContracts[version] == null) {
|
|
666
|
-
this.logger.warn(`_checkPastSwaps(): No contract was found for ${this.chainIdentifier} version ${version}! Skipping these swaps!`);
|
|
667
|
-
continue;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
const _checkStatusSwap = checkStatusSwaps[version];
|
|
671
|
-
const swapStatuses = await this._contract(version).getCommitStatuses(_checkStatusSwap.map(val => ({signer: val._getInitiator(), swapData: val._data})));
|
|
672
|
-
|
|
673
|
-
for(let pastSwap of _checkStatusSwap) {
|
|
674
|
-
const shouldSave = await pastSwap._sync(
|
|
675
|
-
false, swapExpiredStatus[pastSwap.getId()],
|
|
676
|
-
swapStatuses[pastSwap.getEscrowHash()!], true
|
|
677
|
-
);
|
|
678
|
-
if(shouldSave) {
|
|
679
|
-
changedSwapSet.add(pastSwap);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
const changedSwaps: FromBTCLNAutoSwap<T>[] = [];
|
|
685
|
-
const removeSwaps: FromBTCLNAutoSwap<T>[] = [];
|
|
686
|
-
changedSwapSet.forEach(val => {
|
|
687
|
-
if(val.isQuoteExpired()) {
|
|
688
|
-
removeSwaps.push(val);
|
|
689
|
-
} else {
|
|
690
|
-
changedSwaps.push(val);
|
|
691
|
-
}
|
|
692
|
-
});
|
|
693
|
-
|
|
694
|
-
return {
|
|
695
|
-
changedSwaps,
|
|
696
|
-
removeSwaps
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
/**
|
|
701
|
-
* @inheritDoc
|
|
702
|
-
*/
|
|
703
|
-
async recoverFromSwapDataAndState(
|
|
704
|
-
init: {data: T["Data"], getInitTxId: () => Promise<string>, getTxBlock: () => Promise<{blockTime: number, blockHeight: number}>},
|
|
705
|
-
state: SwapCommitState,
|
|
706
|
-
contractVersion: string,
|
|
707
|
-
lp?: Intermediary
|
|
708
|
-
): Promise<FromBTCLNAutoSwap<T> | null> {
|
|
709
|
-
const data = init.data;
|
|
710
|
-
|
|
711
|
-
let paymentHash = data.getHTLCHashHint();
|
|
712
|
-
let secret: string | undefined;
|
|
713
|
-
if(state.type===SwapCommitStateType.PAID) {
|
|
714
|
-
secret = await state.getClaimResult();
|
|
715
|
-
paymentHash = Buffer.from(sha256(Buffer.from(secret, "hex"))).toString("hex");
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
const swapInit: FromBTCLNAutoSwapInit<T["Data"]> = {
|
|
719
|
-
pricingInfo: {
|
|
720
|
-
isValid: true,
|
|
721
|
-
satsBaseFee: 0n,
|
|
722
|
-
swapPriceUSatPerToken: 100_000_000_000_000n,
|
|
723
|
-
realPriceUSatPerToken: 100_000_000_000_000n,
|
|
724
|
-
differencePPM: 0n,
|
|
725
|
-
feePPM: 0n,
|
|
726
|
-
},
|
|
727
|
-
url: lp?.url,
|
|
728
|
-
expiry: 0,
|
|
729
|
-
swapFee: 0n,
|
|
730
|
-
swapFeeBtc: 0n,
|
|
731
|
-
gasSwapFee: 0n,
|
|
732
|
-
gasSwapFeeBtc: 0n,
|
|
733
|
-
initialSwapData: data,
|
|
734
|
-
data,
|
|
735
|
-
pr: paymentHash ?? undefined,
|
|
736
|
-
secret,
|
|
737
|
-
exactIn: false,
|
|
738
|
-
contractVersion
|
|
739
|
-
}
|
|
740
|
-
const swap = new FromBTCLNAutoSwap(this, swapInit);
|
|
741
|
-
swap._commitTxId = await init.getInitTxId();
|
|
742
|
-
const blockData = await init.getTxBlock();
|
|
743
|
-
swap.createdAt = blockData.blockTime * 1000;
|
|
744
|
-
swap._commitedAt = blockData.blockTime * 1000;
|
|
745
|
-
swap._setInitiated();
|
|
746
|
-
swap._state = FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
747
|
-
await swap._sync(false, false, state);
|
|
748
|
-
await swap._save();
|
|
749
|
-
return swap;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
}
|
|
1
|
+
import {decode as bolt11Decode, PaymentRequestObject, TagsObject} from "@atomiqlabs/bolt11";
|
|
2
|
+
import {
|
|
3
|
+
ChainSwapType,
|
|
4
|
+
ChainType,
|
|
5
|
+
ClaimEvent,
|
|
6
|
+
InitializeEvent, LightningNetworkApi, LNNodeLiquidity, Messenger,
|
|
7
|
+
RefundEvent, SwapCommitState, SwapCommitStateType
|
|
8
|
+
} from "@atomiqlabs/base";
|
|
9
|
+
import {Intermediary} from "../../../../intermediaries/Intermediary";
|
|
10
|
+
import {Buffer} from "buffer";
|
|
11
|
+
import {UserError} from "../../../../errors/UserError";
|
|
12
|
+
import {IntermediaryError} from "../../../../errors/IntermediaryError";
|
|
13
|
+
import {SwapType} from "../../../../enums/SwapType";
|
|
14
|
+
import {
|
|
15
|
+
extendAbortController, mapArrayToObject, parseHashValueExact32Bytes,
|
|
16
|
+
randomBytes,
|
|
17
|
+
throwIfUndefined
|
|
18
|
+
} from "../../../../utils/Utils";
|
|
19
|
+
import {
|
|
20
|
+
FromBTCLNAutoResponseType,
|
|
21
|
+
IntermediaryAPI
|
|
22
|
+
} from "../../../../intermediaries/apis/IntermediaryAPI";
|
|
23
|
+
import {RequestError} from "../../../../errors/RequestError";
|
|
24
|
+
import {ISwapPrice} from "../../../../prices/abstract/ISwapPrice";
|
|
25
|
+
import {EventEmitter} from "events";
|
|
26
|
+
import {ISwapWrapperOptions, WrapperCtorTokens} from "../../../ISwapWrapper";
|
|
27
|
+
import {UnifiedSwapEventListener} from "../../../../events/UnifiedSwapEventListener";
|
|
28
|
+
import {UnifiedSwapStorage} from "../../../../storage/UnifiedSwapStorage";
|
|
29
|
+
import {ISwap} from "../../../ISwap";
|
|
30
|
+
import {FromBTCLNAutoSwap, FromBTCLNAutoSwapInit, FromBTCLNAutoSwapState} from "./FromBTCLNAutoSwap";
|
|
31
|
+
import {IFromBTCLNDefinition, IFromBTCLNWrapper} from "../IFromBTCLNWrapper";
|
|
32
|
+
import {IClaimableSwapWrapper} from "../../../IClaimableSwapWrapper";
|
|
33
|
+
import {AmountData} from "../../../../types/AmountData";
|
|
34
|
+
import {LNURLWithdrawParamsWithUrl} from "../../../../types/lnurl/LNURLWithdraw";
|
|
35
|
+
import {tryWithRetries} from "../../../../utils/RetryUtils";
|
|
36
|
+
import {AllOptional} from "../../../../utils/TypeUtils";
|
|
37
|
+
import {sha256} from "@noble/hashes/sha2";
|
|
38
|
+
import {fromHumanReadableString} from "../../../../utils/TokenUtils";
|
|
39
|
+
|
|
40
|
+
export type FromBTCLNAutoOptions = {
|
|
41
|
+
/**
|
|
42
|
+
* Instead of letting the SDK generate the preimage/paymentHash pair internally you can pass your computed
|
|
43
|
+
* paymentHash here, this will create the swap with the provided payment hash. Note that swaps created this way
|
|
44
|
+
* won't settle automatically (as the SDK is missing the preimage). Once the HTLC towards the user is created in
|
|
45
|
+
* the {@link FromBTCLNAutoSwapState.CLAIM_COMMITED} state, you should pass the secret preimage manually in the
|
|
46
|
+
* {@link FromBTCLNAutoSwap.waitTillClaimed}, {@link FromBTCLNAutoSwap.claim} or {@link FromBTCLNAutoSwap.txsClaim}
|
|
47
|
+
* functions.
|
|
48
|
+
*
|
|
49
|
+
* Accepts both, a {@link Buffer} and a hexadecimal `string`
|
|
50
|
+
*/
|
|
51
|
+
paymentHash?: Buffer | string,
|
|
52
|
+
/**
|
|
53
|
+
* Optional description to use for the swap lightning network invoice, keep the invoice length below 500 characters
|
|
54
|
+
*/
|
|
55
|
+
description?: string,
|
|
56
|
+
/**
|
|
57
|
+
* Optional description hash to use for the lightning network invoice, useful when returning the invoice as part of
|
|
58
|
+
* an LNURL-pay service endpoint.
|
|
59
|
+
*
|
|
60
|
+
* Accepts both, a {@link Buffer} and a hexadecimal `string`
|
|
61
|
+
*/
|
|
62
|
+
descriptionHash?: Buffer | string,
|
|
63
|
+
/**
|
|
64
|
+
* Optional additional native token to receive as an output of the swap (e.g. STRK on Starknet or cBTC on Citrea).
|
|
65
|
+
* When passed as a `bigint` it is specified in base units of the token and in `string` it is the human readable
|
|
66
|
+
* decimal format.
|
|
67
|
+
*/
|
|
68
|
+
gasAmount?: bigint | string,
|
|
69
|
+
/**
|
|
70
|
+
* A flag to skip checking whether the lightning network node of the LP has enough channel liquidity to facilitate
|
|
71
|
+
* the swap.
|
|
72
|
+
*/
|
|
73
|
+
unsafeSkipLnNodeCheck?: boolean,
|
|
74
|
+
/**
|
|
75
|
+
* A flag to attach 0 watchtower fee to the swap, this would make the settlement unattractive for the watchtowers
|
|
76
|
+
* and therefore automatic settlement for such swaps will not be possible, you will have to settle manually
|
|
77
|
+
* with {@link FromBTCLNSwap.claim} or {@link FromBTCLNSwap.txsClaim} functions.
|
|
78
|
+
*/
|
|
79
|
+
unsafeZeroWatchtowerFee?: boolean,
|
|
80
|
+
/**
|
|
81
|
+
* A safety factor to use when estimating the watchtower fee to attach to the swap (this has to cover the gas fee
|
|
82
|
+
* of watchtowers settling the swap). A higher multiple here would mean that a swap is more attractive for
|
|
83
|
+
* watchtowers to settle automatically.
|
|
84
|
+
*
|
|
85
|
+
* Uses a `1.25` multiple by default (i.e. the current network fee is multiplied by 1.25 and then used to estimate
|
|
86
|
+
* the settlement gas fee cost)
|
|
87
|
+
*/
|
|
88
|
+
feeSafetyFactor?: number
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export type FromBTCLNAutoWrapperOptions = ISwapWrapperOptions & {
|
|
92
|
+
safetyFactor: number,
|
|
93
|
+
bitcoinBlocktime: number,
|
|
94
|
+
unsafeSkipLnNodeCheck: boolean
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export type FromBTCLNAutoDefinition<T extends ChainType> = IFromBTCLNDefinition<T, FromBTCLNAutoWrapper<T>, FromBTCLNAutoSwap<T>>;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* New escrow based (HTLC) swaps for Bitcoin Lightning -> Smart chain swaps not requiring manual settlement on
|
|
101
|
+
* the destination by the user, and instead letting the LP initiate the escrow. Permissionless watchtower network
|
|
102
|
+
* handles the claiming of HTLC, with the swap secret broadcasted over Nostr. Also adds a possibility for the user
|
|
103
|
+
* to receive a native token on the destination chain as part of the swap (a "gas drop" feature).
|
|
104
|
+
*
|
|
105
|
+
* @category Swaps/Lightning → Smart chain
|
|
106
|
+
*/
|
|
107
|
+
export class FromBTCLNAutoWrapper<
|
|
108
|
+
T extends ChainType
|
|
109
|
+
> extends IFromBTCLNWrapper<T, FromBTCLNAutoDefinition<T>, FromBTCLNAutoWrapperOptions> implements IClaimableSwapWrapper<FromBTCLNAutoSwap<T>> {
|
|
110
|
+
|
|
111
|
+
public readonly TYPE: SwapType.FROM_BTCLN_AUTO = SwapType.FROM_BTCLN_AUTO;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
protected readonly tickSwapState = [
|
|
117
|
+
FromBTCLNAutoSwapState.PR_CREATED,
|
|
118
|
+
FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED,
|
|
119
|
+
FromBTCLNAutoSwapState.PR_PAID,
|
|
120
|
+
FromBTCLNAutoSwapState.CLAIM_COMMITED
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
126
|
+
readonly _pendingSwapStates = [
|
|
127
|
+
FromBTCLNAutoSwapState.PR_CREATED,
|
|
128
|
+
FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED,
|
|
129
|
+
FromBTCLNAutoSwapState.PR_PAID,
|
|
130
|
+
FromBTCLNAutoSwapState.CLAIM_COMMITED,
|
|
131
|
+
FromBTCLNAutoSwapState.EXPIRED
|
|
132
|
+
];
|
|
133
|
+
/**
|
|
134
|
+
* @internal
|
|
135
|
+
*/
|
|
136
|
+
readonly _claimableSwapStates = [FromBTCLNAutoSwapState.CLAIM_COMMITED];
|
|
137
|
+
/**
|
|
138
|
+
* @internal
|
|
139
|
+
*/
|
|
140
|
+
readonly _swapDeserializer = FromBTCLNAutoSwap;
|
|
141
|
+
/**
|
|
142
|
+
* @internal
|
|
143
|
+
*/
|
|
144
|
+
readonly _messenger: Messenger;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param chainIdentifier
|
|
148
|
+
* @param unifiedStorage Storage interface for the current environment
|
|
149
|
+
* @param unifiedChainEvents On-chain event listener
|
|
150
|
+
* @param chain
|
|
151
|
+
* @param prices Swap pricing handler
|
|
152
|
+
* @param tokens
|
|
153
|
+
* @param versionedContracts
|
|
154
|
+
* @param lnApi
|
|
155
|
+
* @param messenger
|
|
156
|
+
* @param lpApi
|
|
157
|
+
* @param options
|
|
158
|
+
* @param events Instance to use for emitting events
|
|
159
|
+
*/
|
|
160
|
+
constructor(
|
|
161
|
+
chainIdentifier: string,
|
|
162
|
+
unifiedStorage: UnifiedSwapStorage<T>,
|
|
163
|
+
unifiedChainEvents: UnifiedSwapEventListener<T>,
|
|
164
|
+
chain: T["ChainInterface"],
|
|
165
|
+
prices: ISwapPrice,
|
|
166
|
+
tokens: WrapperCtorTokens,
|
|
167
|
+
versionedContracts: {
|
|
168
|
+
[version: string]: {
|
|
169
|
+
swapContract: T["Contract"],
|
|
170
|
+
swapDataConstructor: new (data: any) => T["Data"]
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
lnApi: LightningNetworkApi,
|
|
174
|
+
messenger: Messenger,
|
|
175
|
+
lpApi: IntermediaryAPI,
|
|
176
|
+
options?: AllOptional<FromBTCLNAutoWrapperOptions>,
|
|
177
|
+
events?: EventEmitter<{swapState: [ISwap]}>
|
|
178
|
+
) {
|
|
179
|
+
super(
|
|
180
|
+
chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens, versionedContracts, lnApi, lpApi,
|
|
181
|
+
{
|
|
182
|
+
...options,
|
|
183
|
+
safetyFactor: options?.safetyFactor ?? 2,
|
|
184
|
+
bitcoinBlocktime: options?.bitcoinBlocktime ?? 10*60,
|
|
185
|
+
unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? false
|
|
186
|
+
},
|
|
187
|
+
events
|
|
188
|
+
);
|
|
189
|
+
this._messenger = messenger;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @inheritDoc
|
|
194
|
+
* @internal
|
|
195
|
+
*/
|
|
196
|
+
protected async processEventInitialize(swap: FromBTCLNAutoSwap<T>, event: InitializeEvent<T["Data"]>): Promise<boolean> {
|
|
197
|
+
if(swap._state===FromBTCLNAutoSwapState.PR_PAID || swap._state===FromBTCLNAutoSwapState.PR_CREATED || swap._state===FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED) {
|
|
198
|
+
if(swap._data==null) {
|
|
199
|
+
//Obtain data from the initialize event
|
|
200
|
+
const eventData = await event.swapData();
|
|
201
|
+
if(eventData==null) {
|
|
202
|
+
this.logger.error("processEventInitialize("+swap.getId()+"): Error when fetching swap data for swap, null returned!");
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
await swap._saveRealSwapData(eventData, false);
|
|
207
|
+
this.logger.info("processEventInitialize("+swap.getId()+"): Successfully taken swap data from on-chain event!");
|
|
208
|
+
} catch (e) {
|
|
209
|
+
this.logger.error("processEventInitialize("+swap.getId()+"): Error when saving swap data for swap: ", e);
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if(swap._getEscrowHash()!==event.escrowHash) {
|
|
215
|
+
this.logger.error("processEventInitialize("+swap.getId()+"): Error when processing event, escrow hashes don't match!");
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
swap._commitedAt ??= Date.now();
|
|
220
|
+
swap._state = FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
221
|
+
if(swap.hasSecretPreimage()) swap._broadcastSecret().catch(e => {
|
|
222
|
+
this.logger.error("processEventInitialize("+swap.getId()+"): Error when broadcasting swap secret: ", e);
|
|
223
|
+
});
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @inheritDoc
|
|
231
|
+
* @internal
|
|
232
|
+
*/
|
|
233
|
+
protected processEventClaim(swap: FromBTCLNAutoSwap<T>, event: ClaimEvent<T["Data"]>): Promise<boolean> {
|
|
234
|
+
if(swap._state!==FromBTCLNAutoSwapState.FAILED && swap._state!==FromBTCLNAutoSwapState.CLAIM_CLAIMED) {
|
|
235
|
+
swap._state = FromBTCLNAutoSwapState.CLAIM_CLAIMED;
|
|
236
|
+
swap._setSwapSecret(event.result);
|
|
237
|
+
return Promise.resolve(true);
|
|
238
|
+
}
|
|
239
|
+
return Promise.resolve(false);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* @inheritDoc
|
|
244
|
+
* @internal
|
|
245
|
+
*/
|
|
246
|
+
protected processEventRefund(swap: FromBTCLNAutoSwap<T>, event: RefundEvent<T["Data"]>): Promise<boolean> {
|
|
247
|
+
if(swap._state!==FromBTCLNAutoSwapState.CLAIM_CLAIMED && swap._state!==FromBTCLNAutoSwapState.FAILED) {
|
|
248
|
+
swap._state = FromBTCLNAutoSwapState.FAILED;
|
|
249
|
+
return Promise.resolve(true);
|
|
250
|
+
}
|
|
251
|
+
return Promise.resolve(false);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Pre-fetches claimer (watchtower) bounty data for the swap. Doesn't throw, instead returns null and aborts the
|
|
256
|
+
* provided abortController
|
|
257
|
+
*
|
|
258
|
+
* @param signer Smartchain signer address initiating the swap
|
|
259
|
+
* @param amountData
|
|
260
|
+
* @param options Options as passed to the swap creation function
|
|
261
|
+
* @param abortController
|
|
262
|
+
*
|
|
263
|
+
* @param contractVersions
|
|
264
|
+
* @private
|
|
265
|
+
*/
|
|
266
|
+
private preFetchClaimerBounty(
|
|
267
|
+
signer: string,
|
|
268
|
+
amountData: AmountData,
|
|
269
|
+
options: {feeSafetyFactor: number, unsafeZeroWatchtowerFee: boolean},
|
|
270
|
+
abortController: AbortController,
|
|
271
|
+
contractVersions: string[]
|
|
272
|
+
): {[chainVersion: string]: Promise<bigint | undefined>} {
|
|
273
|
+
return mapArrayToObject(contractVersions, async (contractVersion) => {
|
|
274
|
+
if(options.unsafeZeroWatchtowerFee) return 0n;
|
|
275
|
+
|
|
276
|
+
const dummyAmount = BigInt(Math.floor(Math.random()* 0x1000000));
|
|
277
|
+
const dummySwapData = await this._contract(contractVersion).createSwapData(
|
|
278
|
+
ChainSwapType.HTLC, this._chain.randomAddress(), signer, amountData.token,
|
|
279
|
+
dummyAmount, this._contract(contractVersion).getHashForHtlc(randomBytes(32)).toString("hex"),
|
|
280
|
+
this.getRandomSequence(), BigInt(Math.floor(Date.now()/1000)), false, true,
|
|
281
|
+
BigInt(Math.floor(Math.random() * 0x10000)), BigInt(Math.floor(Math.random() * 0x10000))
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const result = await this._contract(contractVersion).getClaimFee(this._chain.randomAddress(), dummySwapData);
|
|
286
|
+
return result * BigInt(Math.floor(options.feeSafetyFactor*1000000)) / 1_000_000n
|
|
287
|
+
} catch (e) {
|
|
288
|
+
abortController.abort(e);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Verifies response returned from intermediary
|
|
295
|
+
*
|
|
296
|
+
* @param resp Response as returned by the intermediary
|
|
297
|
+
* @param amountData
|
|
298
|
+
* @param lp Intermediary
|
|
299
|
+
* @param options Options as passed to the swap creation function
|
|
300
|
+
* @param decodedPr Decoded bolt11 lightning network invoice
|
|
301
|
+
* @param paymentHash Expected payment hash of the bolt11 lightning network invoice
|
|
302
|
+
* @param claimerBounty Claimer bounty as request by the user
|
|
303
|
+
*
|
|
304
|
+
* @throws {IntermediaryError} in case the response is invalid
|
|
305
|
+
*
|
|
306
|
+
* @private
|
|
307
|
+
*/
|
|
308
|
+
private verifyReturnedData(
|
|
309
|
+
resp: FromBTCLNAutoResponseType,
|
|
310
|
+
amountData: AmountData,
|
|
311
|
+
lp: Intermediary,
|
|
312
|
+
options: {gasAmount: bigint, description?: string, descriptionHash?: Buffer},
|
|
313
|
+
decodedPr: PaymentRequestObject & {tagsObject: TagsObject},
|
|
314
|
+
paymentHash: Buffer,
|
|
315
|
+
claimerBounty: bigint
|
|
316
|
+
): void {
|
|
317
|
+
if(lp.getAddress(this.chainIdentifier)!==resp.intermediaryKey) throw new IntermediaryError("Invalid intermediary address/pubkey");
|
|
318
|
+
|
|
319
|
+
if(options.descriptionHash!=null && decodedPr.tagsObject.purpose_commit_hash!==options.descriptionHash.toString("hex"))
|
|
320
|
+
throw new IntermediaryError("Invalid pr returned - description hash");
|
|
321
|
+
|
|
322
|
+
if(options.description!=null && decodedPr.tagsObject.description!==options.description)
|
|
323
|
+
throw new IntermediaryError("Invalid pr returned - description");
|
|
324
|
+
|
|
325
|
+
if(
|
|
326
|
+
decodedPr.tagsObject.payment_hash==null ||
|
|
327
|
+
!Buffer.from(decodedPr.tagsObject.payment_hash, "hex").equals(paymentHash)
|
|
328
|
+
) throw new IntermediaryError("Invalid pr returned - payment hash");
|
|
329
|
+
|
|
330
|
+
if(decodedPr.millisatoshis==null) throw new IntermediaryError("Invalid pr returned - msat field");
|
|
331
|
+
|
|
332
|
+
const amountIn = (BigInt(decodedPr.millisatoshis) + 999n) / 1000n;
|
|
333
|
+
if(resp.btcAmountGas + resp.btcAmountSwap !== amountIn) throw new IntermediaryError("Invalid total btc returned");
|
|
334
|
+
if(resp.gasSwapFeeBtc + resp.swapFeeBtc !== resp.totalFeeBtc) throw new IntermediaryError("Invalid total btc fee returned");
|
|
335
|
+
if(resp.claimerBounty !== claimerBounty) throw new IntermediaryError("Invalid claimer bounty");
|
|
336
|
+
if(resp.totalGas !== options.gasAmount) throw new IntermediaryError("Invalid total gas amount");
|
|
337
|
+
if(!amountData.exactIn) {
|
|
338
|
+
if(resp.total != amountData.amount) throw new IntermediaryError("Invalid amount returned");
|
|
339
|
+
} else {
|
|
340
|
+
if(amountIn !== amountData.amount) throw new IntermediaryError("Invalid payment request returned, amount mismatch");
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Returns a newly created Lightning -> Smart chain swap using the HTLC based escrow swap protocol,
|
|
346
|
+
* where watchtowers handle the automatic settlement of the swap on the destination chain. Also allows
|
|
347
|
+
* specifying additional "gas drop" native token that the receipient receives on the destination chain
|
|
348
|
+
* in the `options` argument. The user has to pay a bolt11 invoice on the input lightning network side.
|
|
349
|
+
*
|
|
350
|
+
* @param recipient Recipient's address on the destination chain
|
|
351
|
+
* @param amountData Amount, token and exact input/output data for to swap
|
|
352
|
+
* @param lps An array of intermediaries (LPs) to get the quotes from
|
|
353
|
+
* @param options Optional additional quote options
|
|
354
|
+
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
|
|
355
|
+
* @param abortSignal Abort signal
|
|
356
|
+
* @param preFetches Optional pre-fetches for speeding up the quoting process (mainly used internally)
|
|
357
|
+
*/
|
|
358
|
+
create(
|
|
359
|
+
recipient: string,
|
|
360
|
+
amountData: AmountData,
|
|
361
|
+
lps: Intermediary[],
|
|
362
|
+
options?: FromBTCLNAutoOptions,
|
|
363
|
+
additionalParams?: Record<string, any>,
|
|
364
|
+
abortSignal?: AbortSignal,
|
|
365
|
+
preFetches?: {
|
|
366
|
+
pricePrefetchPromise: Promise<bigint | undefined>,
|
|
367
|
+
usdPricePrefetchPromise: Promise<number | undefined>,
|
|
368
|
+
claimerBountyPrefetch: {[contractVersion: string]: Promise<bigint | undefined>},
|
|
369
|
+
gasTokenPricePrefetchPromise?: Promise<bigint | undefined>,
|
|
370
|
+
}
|
|
371
|
+
): {
|
|
372
|
+
quote: Promise<FromBTCLNAutoSwap<T>>,
|
|
373
|
+
intermediary: Intermediary
|
|
374
|
+
}[] {
|
|
375
|
+
if(!this.isInitialized) throw new Error("Not initialized, call init() first!");
|
|
376
|
+
|
|
377
|
+
const _options = {
|
|
378
|
+
paymentHash: parseHashValueExact32Bytes(options?.paymentHash, "payment hash"),
|
|
379
|
+
unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck,
|
|
380
|
+
gasAmount: this.parseGasAmount(options?.gasAmount),
|
|
381
|
+
feeSafetyFactor: options?.feeSafetyFactor ?? 1.25, //No need to add much of a margin, since the claim should happen rather soon
|
|
382
|
+
unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
|
|
383
|
+
description: options?.description,
|
|
384
|
+
descriptionHash: parseHashValueExact32Bytes(options?.descriptionHash, "description hash")
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
if(
|
|
389
|
+
_options.gasAmount!==0n &&
|
|
390
|
+
(
|
|
391
|
+
this._chain.shouldGetNativeTokenDrop!=null
|
|
392
|
+
? !this._chain.shouldGetNativeTokenDrop(amountData.token)
|
|
393
|
+
: amountData.token===this._chain.getNativeCurrencyAddress()
|
|
394
|
+
)
|
|
395
|
+
) throw new UserError("Cannot specify `gasAmount` for swaps to a native token!");
|
|
396
|
+
|
|
397
|
+
if(_options.description!=null && Buffer.byteLength(_options.description, "utf8") > 500)
|
|
398
|
+
throw new UserError("Invalid description length");
|
|
399
|
+
|
|
400
|
+
const lpVersions = Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
|
|
401
|
+
|
|
402
|
+
let secret: Buffer | undefined;
|
|
403
|
+
let paymentHash: Buffer;
|
|
404
|
+
if(_options?.paymentHash!=null) {
|
|
405
|
+
paymentHash = _options.paymentHash;
|
|
406
|
+
} else {
|
|
407
|
+
({secret, paymentHash} = this.getSecretAndHash());
|
|
408
|
+
}
|
|
409
|
+
const _hash = mapArrayToObject(lpVersions, (contractVersion: string) => {
|
|
410
|
+
return this._contract(contractVersion).getHashForHtlc(paymentHash).toString("hex");
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
const nativeTokenAddress = this._chain.getNativeCurrencyAddress();
|
|
414
|
+
|
|
415
|
+
const _abortController = extendAbortController(abortSignal);
|
|
416
|
+
|
|
417
|
+
const _preFetches = preFetches ?? {
|
|
418
|
+
pricePrefetchPromise: this.preFetchPrice(amountData, _abortController.signal),
|
|
419
|
+
usdPricePrefetchPromise: this.preFetchUsdPrice(_abortController.signal),
|
|
420
|
+
claimerBountyPrefetch: this.preFetchClaimerBounty(recipient, amountData, _options, _abortController, lpVersions),
|
|
421
|
+
gasTokenPricePrefetchPromise: _options.gasAmount!==0n || !_options.unsafeZeroWatchtowerFee ?
|
|
422
|
+
this.preFetchPrice({token: nativeTokenAddress}, _abortController.signal) :
|
|
423
|
+
undefined
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
return lps.map(lp => {
|
|
427
|
+
return {
|
|
428
|
+
intermediary: lp,
|
|
429
|
+
quote: (async () => {
|
|
430
|
+
if(lp.services[SwapType.FROM_BTCLN_AUTO]==null) throw new Error("LP service for processing from btcln auto swaps not found!");
|
|
431
|
+
const version = lp.getContractVersion(this.chainIdentifier);
|
|
432
|
+
|
|
433
|
+
const abortController = extendAbortController(_abortController.signal);
|
|
434
|
+
|
|
435
|
+
const liquidityPromise: Promise<bigint | undefined> = this.preFetchIntermediaryLiquidity(amountData, lp, abortController, version);
|
|
436
|
+
|
|
437
|
+
const {lnCapacityPromise, resp} = await tryWithRetries(async(retryCount: number) => {
|
|
438
|
+
const {lnPublicKey, response} = this._lpApi.initFromBTCLNAuto(
|
|
439
|
+
this.chainIdentifier, lp.url,
|
|
440
|
+
{
|
|
441
|
+
paymentHash,
|
|
442
|
+
amount: amountData.amount,
|
|
443
|
+
claimer: recipient,
|
|
444
|
+
token: amountData.token.toString(),
|
|
445
|
+
description: _options.description,
|
|
446
|
+
descriptionHash: _options.descriptionHash,
|
|
447
|
+
exactOut: !amountData.exactIn,
|
|
448
|
+
additionalParams,
|
|
449
|
+
gasToken: this._chain.getNativeCurrencyAddress(),
|
|
450
|
+
gasAmount: _options.gasAmount,
|
|
451
|
+
claimerBounty: throwIfUndefined(_preFetches.claimerBountyPrefetch[version], "Watchtower fee pre-fetch failed!")
|
|
452
|
+
},
|
|
453
|
+
this._options.postRequestTimeout, abortController.signal, retryCount>0 ? false : undefined
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
let lnCapacityPromise: Promise<LNNodeLiquidity | null> | undefined;
|
|
457
|
+
if(!_options.unsafeSkipLnNodeCheck) {
|
|
458
|
+
lnCapacityPromise = this.preFetchLnCapacity(lnPublicKey);
|
|
459
|
+
} else lnPublicKey.catch(() => {});
|
|
460
|
+
|
|
461
|
+
return {
|
|
462
|
+
lnCapacityPromise,
|
|
463
|
+
resp: await response
|
|
464
|
+
};
|
|
465
|
+
}, undefined, RequestError, abortController.signal);
|
|
466
|
+
|
|
467
|
+
const decodedPr = bolt11Decode(resp.pr);
|
|
468
|
+
if(decodedPr.millisatoshis==null) throw new IntermediaryError("Invalid returned swap invoice, no msat amount field");
|
|
469
|
+
if(decodedPr.timeExpireDate==null) throw new IntermediaryError("Invalid returned swap invoice, no expiry date field");
|
|
470
|
+
const amountIn = (BigInt(decodedPr.millisatoshis) + 999n) / 1000n;
|
|
471
|
+
const claimerBounty = (await _preFetches.claimerBountyPrefetch[version])!;
|
|
472
|
+
|
|
473
|
+
try {
|
|
474
|
+
this.verifyReturnedData(resp, amountData, lp, _options, decodedPr, paymentHash, claimerBounty);
|
|
475
|
+
const [pricingInfo, gasPricingInfo] = await Promise.all([
|
|
476
|
+
this.verifyReturnedPrice(
|
|
477
|
+
lp.services[SwapType.FROM_BTCLN_AUTO],
|
|
478
|
+
false, resp.btcAmountSwap,
|
|
479
|
+
resp.total,
|
|
480
|
+
amountData.token, {swapFeeBtc: resp.swapFeeBtc}, _preFetches.pricePrefetchPromise, _preFetches.usdPricePrefetchPromise, abortController.signal
|
|
481
|
+
),
|
|
482
|
+
_options.gasAmount===0n ? Promise.resolve(undefined) : this.verifyReturnedPrice(
|
|
483
|
+
{...lp.services[SwapType.FROM_BTCLN_AUTO], swapBaseFee: 0}, //Base fee should be charged only on the amount, not on gas
|
|
484
|
+
false, resp.btcAmountGas,
|
|
485
|
+
resp.totalGas + resp.claimerBounty,
|
|
486
|
+
nativeTokenAddress, {swapFeeBtc: resp.gasSwapFeeBtc}, _preFetches.gasTokenPricePrefetchPromise, _preFetches.usdPricePrefetchPromise, abortController.signal
|
|
487
|
+
),
|
|
488
|
+
this.verifyIntermediaryLiquidity(resp.total, throwIfUndefined(liquidityPromise, "LP liquidity pre-fetch failed!")),
|
|
489
|
+
_options.unsafeSkipLnNodeCheck ? Promise.resolve() : this.verifyLnNodeCapacity(lp, decodedPr, lnCapacityPromise, abortController.signal)
|
|
490
|
+
]);
|
|
491
|
+
|
|
492
|
+
const swapInit: FromBTCLNAutoSwapInit<T["Data"]> = {
|
|
493
|
+
pricingInfo,
|
|
494
|
+
url: lp.url,
|
|
495
|
+
expiry: decodedPr.timeExpireDate*1000,
|
|
496
|
+
|
|
497
|
+
swapFee: resp.swapFee,
|
|
498
|
+
gasSwapFee: resp.gasSwapFee,
|
|
499
|
+
|
|
500
|
+
swapFeeBtc: resp.swapFeeBtc,
|
|
501
|
+
gasSwapFeeBtc: resp.gasSwapFeeBtc,
|
|
502
|
+
|
|
503
|
+
btcAmountGas: resp.btcAmountGas,
|
|
504
|
+
btcAmountSwap: resp.btcAmountSwap,
|
|
505
|
+
|
|
506
|
+
gasPricingInfo,
|
|
507
|
+
|
|
508
|
+
initialSwapData: await this._contract(version).createSwapData(
|
|
509
|
+
ChainSwapType.HTLC, lp.getAddress(this.chainIdentifier), recipient, amountData.token,
|
|
510
|
+
resp.total, _hash[version],
|
|
511
|
+
this.getRandomSequence(), BigInt(Math.floor(Date.now()/1000)), false, true,
|
|
512
|
+
_options.gasAmount + resp.claimerBounty, resp.claimerBounty, nativeTokenAddress
|
|
513
|
+
),
|
|
514
|
+
pr: resp.pr,
|
|
515
|
+
secret: secret?.toString("hex"),
|
|
516
|
+
exactIn: amountData.exactIn ?? true,
|
|
517
|
+
contractVersion: version
|
|
518
|
+
};
|
|
519
|
+
const quote = new FromBTCLNAutoSwap<T>(this, swapInit);
|
|
520
|
+
return quote;
|
|
521
|
+
} catch (e) {
|
|
522
|
+
abortController.abort(e);
|
|
523
|
+
throw e;
|
|
524
|
+
}
|
|
525
|
+
})()
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Returns a newly created Lightning -> Smart chain swap using the HTLC based escrow swap protocol,
|
|
532
|
+
* where watchtowers handle the automatic settlement of the swap on the destination chain. Also allows
|
|
533
|
+
* specifying additional "gas drop" native token that the receipient receives on the destination chain
|
|
534
|
+
* in the `options` argument. The swap is created with an LNURL-withdraw link which will be used to pay
|
|
535
|
+
* the generated bolt11 invoice automatically when {@link FromBTCLNSwap.waitForPayment} is called on the
|
|
536
|
+
* swap.
|
|
537
|
+
*
|
|
538
|
+
* @param recipient Recipient's address on the destination chain
|
|
539
|
+
* @param lnurl LNURL-withdraw link to pull the funds from
|
|
540
|
+
* @param amountData Amount, token and exact input/output data for to swap
|
|
541
|
+
* @param lps An array of intermediaries (LPs) to get the quotes from
|
|
542
|
+
* @param options Optional additional quote options
|
|
543
|
+
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
|
|
544
|
+
* @param abortSignal Abort signal
|
|
545
|
+
*/
|
|
546
|
+
async createViaLNURL(
|
|
547
|
+
recipient: string,
|
|
548
|
+
lnurl: string | LNURLWithdrawParamsWithUrl,
|
|
549
|
+
amountData: AmountData,
|
|
550
|
+
lps: Intermediary[],
|
|
551
|
+
options?: FromBTCLNAutoOptions,
|
|
552
|
+
additionalParams?: Record<string, any>,
|
|
553
|
+
abortSignal?: AbortSignal
|
|
554
|
+
): Promise<{
|
|
555
|
+
quote: Promise<FromBTCLNAutoSwap<T>>,
|
|
556
|
+
intermediary: Intermediary
|
|
557
|
+
}[]> {
|
|
558
|
+
if(!this.isInitialized) throw new Error("Not initialized, call init() first!");
|
|
559
|
+
|
|
560
|
+
const _options = {
|
|
561
|
+
paymentHash: parseHashValueExact32Bytes(options?.paymentHash, "payment hash"),
|
|
562
|
+
unsafeSkipLnNodeCheck: options?.unsafeSkipLnNodeCheck ?? this._options.unsafeSkipLnNodeCheck,
|
|
563
|
+
gasAmount: this.parseGasAmount(options?.gasAmount),
|
|
564
|
+
feeSafetyFactor: options?.feeSafetyFactor ?? 1.25, //No need to add much of a margin, since the claim should happen rather soon
|
|
565
|
+
unsafeZeroWatchtowerFee: options?.unsafeZeroWatchtowerFee ?? false,
|
|
566
|
+
description: options?.description,
|
|
567
|
+
descriptionHash: parseHashValueExact32Bytes(options?.descriptionHash, "description hash")
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
const lpVersions = Intermediary.getContractVersionsForLps(this.chainIdentifier, lps);
|
|
571
|
+
|
|
572
|
+
const abortController = extendAbortController(abortSignal);
|
|
573
|
+
const preFetches = {
|
|
574
|
+
pricePrefetchPromise: this.preFetchPrice(amountData, abortController.signal),
|
|
575
|
+
usdPricePrefetchPromise: this.preFetchUsdPrice(abortController.signal),
|
|
576
|
+
gasTokenPricePrefetchPromise: _options.gasAmount!==0n || !_options.unsafeZeroWatchtowerFee ?
|
|
577
|
+
this.preFetchPrice({token: this._chain.getNativeCurrencyAddress()}, abortController.signal) :
|
|
578
|
+
undefined,
|
|
579
|
+
claimerBountyPrefetch: this.preFetchClaimerBounty(recipient, amountData, _options, abortController, lpVersions)
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
try {
|
|
583
|
+
const exactOutAmountPromise: Promise<bigint | undefined> | undefined = !amountData.exactIn ? preFetches.pricePrefetchPromise.then(price =>
|
|
584
|
+
this._prices.getToBtcSwapAmount(this.chainIdentifier, amountData.amount, amountData.token, abortController.signal, price)
|
|
585
|
+
).catch(e => {
|
|
586
|
+
abortController.abort(e);
|
|
587
|
+
return undefined;
|
|
588
|
+
}) : undefined;
|
|
589
|
+
|
|
590
|
+
const withdrawRequest = await this.getLNURLWithdraw(lnurl, abortController.signal);
|
|
591
|
+
|
|
592
|
+
const min = BigInt(withdrawRequest.minWithdrawable) / 1000n;
|
|
593
|
+
const max = BigInt(withdrawRequest.maxWithdrawable) / 1000n;
|
|
594
|
+
|
|
595
|
+
if(amountData.exactIn) {
|
|
596
|
+
if(amountData.amount < min) throw new UserError("Amount less than LNURL-withdraw minimum");
|
|
597
|
+
if(amountData.amount > max) throw new UserError("Amount more than LNURL-withdraw maximum");
|
|
598
|
+
} else {
|
|
599
|
+
const amount = (await exactOutAmountPromise)!;
|
|
600
|
+
abortController.signal.throwIfAborted();
|
|
601
|
+
|
|
602
|
+
if((amount * 95n / 100n) < min) throw new UserError("Amount less than LNURL-withdraw minimum");
|
|
603
|
+
if((amount * 105n / 100n) > max) throw new UserError("Amount more than LNURL-withdraw maximum");
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
return this.create(recipient, amountData, lps, _options, additionalParams, abortSignal, preFetches).map(data => {
|
|
607
|
+
return {
|
|
608
|
+
quote: data.quote.then(quote => {
|
|
609
|
+
quote._setLNURLData(
|
|
610
|
+
withdrawRequest.url,
|
|
611
|
+
withdrawRequest.k1,
|
|
612
|
+
withdrawRequest.callback
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
const amountIn = quote.getInput().rawAmount!;
|
|
616
|
+
if(amountIn < min) throw new UserError("Amount less than LNURL-withdraw minimum");
|
|
617
|
+
if(amountIn > max) throw new UserError("Amount more than LNURL-withdraw maximum");
|
|
618
|
+
|
|
619
|
+
return quote;
|
|
620
|
+
}),
|
|
621
|
+
intermediary: data.intermediary
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
} catch (e) {
|
|
625
|
+
abortController.abort(e);
|
|
626
|
+
throw e;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* @inheritDoc
|
|
632
|
+
* @internal
|
|
633
|
+
*/
|
|
634
|
+
protected async _checkPastSwaps(pastSwaps: FromBTCLNAutoSwap<T>[]): Promise<{
|
|
635
|
+
changedSwaps: FromBTCLNAutoSwap<T>[];
|
|
636
|
+
removeSwaps: FromBTCLNAutoSwap<T>[]
|
|
637
|
+
}> {
|
|
638
|
+
const changedSwapSet: Set<FromBTCLNAutoSwap<T>> = new Set();
|
|
639
|
+
|
|
640
|
+
const swapExpiredStatus: {[id: string]: boolean} = {};
|
|
641
|
+
const checkStatusSwaps: {[contractVersion: string]: (FromBTCLNAutoSwap<T> & {_data: T["Data"]})[]} = {};
|
|
642
|
+
|
|
643
|
+
await Promise.all(pastSwaps.map(async (pastSwap) => {
|
|
644
|
+
if(pastSwap._shouldCheckIntermediary()) {
|
|
645
|
+
try {
|
|
646
|
+
const result = await pastSwap._checkIntermediaryPaymentReceived(false);
|
|
647
|
+
if(result!=null) {
|
|
648
|
+
changedSwapSet.add(pastSwap);
|
|
649
|
+
}
|
|
650
|
+
} catch (e) {
|
|
651
|
+
this.logger.error(`_checkPastSwaps(): Failed to contact LP regarding swap ${pastSwap.getId()}, error: `, e);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if(pastSwap._shouldFetchExpiryStatus()) {
|
|
655
|
+
//Check expiry
|
|
656
|
+
swapExpiredStatus[pastSwap.getId()] = await pastSwap._verifyQuoteDefinitelyExpired();
|
|
657
|
+
}
|
|
658
|
+
if(pastSwap._shouldFetchOnchainState()) {
|
|
659
|
+
//Add to swaps for which status should be checked
|
|
660
|
+
if(pastSwap._data!=null) (checkStatusSwaps[pastSwap._contractVersion ?? "v1"] ??= []).push(pastSwap as FromBTCLNAutoSwap<T> & {_data: T["Data"]});
|
|
661
|
+
}
|
|
662
|
+
}));
|
|
663
|
+
|
|
664
|
+
for(let version in checkStatusSwaps) {
|
|
665
|
+
if (this._versionedContracts[version] == null) {
|
|
666
|
+
this.logger.warn(`_checkPastSwaps(): No contract was found for ${this.chainIdentifier} version ${version}! Skipping these swaps!`);
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const _checkStatusSwap = checkStatusSwaps[version];
|
|
671
|
+
const swapStatuses = await this._contract(version).getCommitStatuses(_checkStatusSwap.map(val => ({signer: val._getInitiator(), swapData: val._data})));
|
|
672
|
+
|
|
673
|
+
for(let pastSwap of _checkStatusSwap) {
|
|
674
|
+
const shouldSave = await pastSwap._sync(
|
|
675
|
+
false, swapExpiredStatus[pastSwap.getId()],
|
|
676
|
+
swapStatuses[pastSwap.getEscrowHash()!], true
|
|
677
|
+
);
|
|
678
|
+
if(shouldSave) {
|
|
679
|
+
changedSwapSet.add(pastSwap);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const changedSwaps: FromBTCLNAutoSwap<T>[] = [];
|
|
685
|
+
const removeSwaps: FromBTCLNAutoSwap<T>[] = [];
|
|
686
|
+
changedSwapSet.forEach(val => {
|
|
687
|
+
if(val.isQuoteExpired()) {
|
|
688
|
+
removeSwaps.push(val);
|
|
689
|
+
} else {
|
|
690
|
+
changedSwaps.push(val);
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
return {
|
|
695
|
+
changedSwaps,
|
|
696
|
+
removeSwaps
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* @inheritDoc
|
|
702
|
+
*/
|
|
703
|
+
async recoverFromSwapDataAndState(
|
|
704
|
+
init: {data: T["Data"], getInitTxId: () => Promise<string>, getTxBlock: () => Promise<{blockTime: number, blockHeight: number}>},
|
|
705
|
+
state: SwapCommitState,
|
|
706
|
+
contractVersion: string,
|
|
707
|
+
lp?: Intermediary
|
|
708
|
+
): Promise<FromBTCLNAutoSwap<T> | null> {
|
|
709
|
+
const data = init.data;
|
|
710
|
+
|
|
711
|
+
let paymentHash = data.getHTLCHashHint();
|
|
712
|
+
let secret: string | undefined;
|
|
713
|
+
if(state.type===SwapCommitStateType.PAID) {
|
|
714
|
+
secret = await state.getClaimResult();
|
|
715
|
+
paymentHash = Buffer.from(sha256(Buffer.from(secret, "hex"))).toString("hex");
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
const swapInit: FromBTCLNAutoSwapInit<T["Data"]> = {
|
|
719
|
+
pricingInfo: {
|
|
720
|
+
isValid: true,
|
|
721
|
+
satsBaseFee: 0n,
|
|
722
|
+
swapPriceUSatPerToken: 100_000_000_000_000n,
|
|
723
|
+
realPriceUSatPerToken: 100_000_000_000_000n,
|
|
724
|
+
differencePPM: 0n,
|
|
725
|
+
feePPM: 0n,
|
|
726
|
+
},
|
|
727
|
+
url: lp?.url,
|
|
728
|
+
expiry: 0,
|
|
729
|
+
swapFee: 0n,
|
|
730
|
+
swapFeeBtc: 0n,
|
|
731
|
+
gasSwapFee: 0n,
|
|
732
|
+
gasSwapFeeBtc: 0n,
|
|
733
|
+
initialSwapData: data,
|
|
734
|
+
data,
|
|
735
|
+
pr: paymentHash ?? undefined,
|
|
736
|
+
secret,
|
|
737
|
+
exactIn: false,
|
|
738
|
+
contractVersion
|
|
739
|
+
}
|
|
740
|
+
const swap = new FromBTCLNAutoSwap(this, swapInit);
|
|
741
|
+
swap._commitTxId = await init.getInitTxId();
|
|
742
|
+
const blockData = await init.getTxBlock();
|
|
743
|
+
swap.createdAt = blockData.blockTime * 1000;
|
|
744
|
+
swap._commitedAt = blockData.blockTime * 1000;
|
|
745
|
+
swap._setInitiated();
|
|
746
|
+
swap._state = FromBTCLNAutoSwapState.CLAIM_COMMITED;
|
|
747
|
+
await swap._sync(false, false, state);
|
|
748
|
+
await swap._save();
|
|
749
|
+
return swap;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
}
|