@atomiqlabs/sdk 8.1.7 → 8.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +41 -5
- package/dist/bitcoin/wallet/BitcoinWallet.js +36 -1
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +52 -2
- package/dist/bitcoin/wallet/IBitcoinWallet.js +2 -1
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +42 -7
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +36 -1
- package/dist/enums/FeeType.d.ts +7 -0
- package/dist/enums/FeeType.js +7 -0
- package/dist/enums/SwapAmountType.d.ts +7 -0
- package/dist/enums/SwapAmountType.js +7 -0
- package/dist/enums/SwapDirection.d.ts +7 -0
- package/dist/enums/SwapDirection.js +7 -0
- package/dist/enums/SwapType.d.ts +62 -1
- package/dist/enums/SwapType.js +62 -1
- package/dist/errors/IntermediaryError.d.ts +4 -0
- package/dist/errors/IntermediaryError.js +1 -0
- package/dist/errors/RequestError.d.ts +15 -1
- package/dist/errors/RequestError.js +8 -0
- package/dist/errors/UserError.d.ts +1 -0
- package/dist/errors/UserError.js +1 -0
- package/dist/index.d.ts +4 -5
- package/dist/index.js +3 -4
- package/dist/intermediaries/Intermediary.d.ts +57 -10
- package/dist/intermediaries/Intermediary.js +37 -10
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +55 -22
- package/dist/intermediaries/IntermediaryDiscovery.js +35 -22
- package/dist/prices/RedundantSwapPrice.d.ts +24 -3
- package/dist/prices/RedundantSwapPrice.js +21 -1
- package/dist/prices/SingleSwapPrice.d.ts +9 -6
- package/dist/prices/SingleSwapPrice.js +10 -7
- package/dist/prices/SwapPriceWithChain.d.ts +54 -16
- package/dist/prices/SwapPriceWithChain.js +58 -20
- package/dist/prices/abstract/ISwapPrice.d.ts +94 -45
- package/dist/prices/abstract/ISwapPrice.js +103 -55
- package/dist/prices/providers/BinancePriceProvider.d.ts +7 -0
- package/dist/prices/providers/BinancePriceProvider.js +7 -0
- package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +6 -0
- package/dist/prices/providers/CoinGeckoPriceProvider.js +6 -0
- package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +6 -0
- package/dist/prices/providers/CoinPaprikaPriceProvider.js +6 -0
- package/dist/prices/providers/CustomPriceProvider.d.ts +11 -0
- package/dist/prices/providers/CustomPriceProvider.js +11 -0
- package/dist/prices/providers/KrakenPriceProvider.d.ts +9 -0
- package/dist/prices/providers/KrakenPriceProvider.js +9 -0
- package/dist/prices/providers/OKXPriceProvider.d.ts +6 -0
- package/dist/prices/providers/OKXPriceProvider.js +6 -0
- package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +3 -0
- package/dist/prices/providers/abstract/ExchangePriceProvider.js +3 -0
- package/dist/storage/IUnifiedStorage.d.ts +19 -7
- package/dist/storage/UnifiedSwapStorage.d.ts +33 -3
- package/dist/storage/UnifiedSwapStorage.js +29 -1
- package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +31 -7
- package/dist/storage-browser/IndexedDBUnifiedStorage.js +29 -6
- package/dist/storage-browser/LocalStorageManager.d.ts +25 -1
- package/dist/storage-browser/LocalStorageManager.js +25 -1
- package/dist/swapper/Swapper.d.ts +303 -222
- package/dist/swapper/Swapper.js +376 -344
- package/dist/swapper/SwapperFactory.d.ts +41 -17
- package/dist/swapper/SwapperFactory.js +23 -2
- package/dist/swapper/SwapperUtils.d.ts +75 -28
- package/dist/swapper/SwapperUtils.js +107 -60
- package/dist/swapper/SwapperWithChain.d.ts +286 -91
- package/dist/swapper/SwapperWithChain.js +218 -64
- package/dist/swapper/SwapperWithSigner.d.ts +229 -80
- package/dist/swapper/SwapperWithSigner.js +190 -44
- package/dist/swaps/IAddressSwap.d.ts +10 -1
- package/dist/swaps/IAddressSwap.js +2 -1
- package/dist/swaps/IBTCWalletSwap.d.ts +24 -6
- package/dist/swaps/IBTCWalletSwap.js +2 -1
- package/dist/swaps/IClaimableSwap.d.ts +36 -4
- package/dist/swaps/IClaimableSwap.js +2 -1
- package/dist/swaps/IClaimableSwapWrapper.d.ts +11 -1
- package/dist/swaps/IRefundableSwap.d.ts +29 -3
- package/dist/swaps/IRefundableSwap.js +2 -1
- package/dist/swaps/ISwap.d.ts +159 -21
- package/dist/swaps/ISwap.js +90 -33
- package/dist/swaps/ISwapWithGasDrop.d.ts +6 -0
- package/dist/swaps/ISwapWithGasDrop.js +1 -0
- package/dist/swaps/ISwapWrapper.d.ts +157 -48
- package/dist/swaps/ISwapWrapper.js +130 -72
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +49 -6
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +22 -12
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +65 -12
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +38 -19
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +39 -9
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +30 -21
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +31 -15
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +33 -18
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +94 -29
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +90 -27
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +22 -9
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +24 -11
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +275 -58
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +516 -239
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +76 -25
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +131 -49
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +311 -51
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +542 -193
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +87 -26
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +147 -58
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +209 -53
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +449 -242
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +77 -23
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +116 -46
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +197 -56
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +326 -189
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +30 -5
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +44 -19
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +60 -19
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +74 -31
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +76 -50
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +106 -101
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +36 -13
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +65 -19
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +46 -17
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +82 -27
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +328 -92
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +460 -219
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +76 -24
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +244 -124
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +146 -18
- package/dist/swaps/trusted/ln/LnForGasSwap.js +173 -43
- package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +29 -10
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +30 -11
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +200 -47
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +230 -78
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +34 -12
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +33 -14
- package/dist/types/AmountData.d.ts +2 -1
- package/dist/types/CustomPriceFunction.d.ts +7 -1
- package/dist/types/SwapExecutionAction.d.ts +74 -4
- package/dist/types/SwapWithSigner.d.ts +4 -1
- package/dist/types/SwapWithSigner.js +5 -2
- package/dist/types/Token.d.ts +11 -5
- package/dist/types/Token.js +6 -3
- package/dist/types/TokenAmount.d.ts +3 -0
- package/dist/types/TokenAmount.js +2 -0
- package/dist/types/fees/Fee.d.ts +2 -1
- package/dist/types/fees/FeeBreakdown.d.ts +2 -1
- package/dist/types/fees/PercentagePPM.d.ts +2 -0
- package/dist/types/fees/PercentagePPM.js +1 -0
- package/dist/types/lnurl/LNURLPay.d.ts +14 -6
- package/dist/types/lnurl/LNURLPay.js +6 -2
- package/dist/types/lnurl/LNURLWithdraw.d.ts +12 -5
- package/dist/types/lnurl/LNURLWithdraw.js +6 -2
- package/dist/types/wallets/LightningInvoiceCreateService.d.ts +20 -0
- package/dist/types/wallets/LightningInvoiceCreateService.js +15 -0
- package/dist/types/wallets/MinimalBitcoinWalletInterface.d.ts +3 -1
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.d.ts +3 -1
- package/dist/utils/BitcoinUtils.d.ts +1 -0
- package/dist/utils/BitcoinUtils.js +5 -1
- package/dist/utils/SwapUtils.d.ts +56 -1
- package/dist/utils/SwapUtils.js +53 -1
- package/dist/utils/TokenUtils.d.ts +10 -2
- package/dist/utils/TokenUtils.js +12 -4
- package/package.json +3 -3
- package/src/bitcoin/wallet/BitcoinWallet.ts +41 -5
- package/src/bitcoin/wallet/IBitcoinWallet.ts +57 -2
- package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +42 -6
- package/src/enums/FeeType.ts +7 -0
- package/src/enums/SwapAmountType.ts +7 -0
- package/src/enums/SwapDirection.ts +7 -0
- package/src/enums/SwapType.ts +62 -2
- package/src/errors/IntermediaryError.ts +4 -0
- package/src/errors/RequestError.ts +15 -1
- package/src/errors/UserError.ts +1 -0
- package/src/index.ts +6 -5
- package/src/intermediaries/Intermediary.ts +57 -10
- package/src/intermediaries/IntermediaryDiscovery.ts +60 -27
- package/src/prices/RedundantSwapPrice.ts +24 -4
- package/src/prices/SingleSwapPrice.ts +10 -7
- package/src/prices/SwapPriceWithChain.ts +59 -21
- package/src/prices/abstract/ISwapPrice.ts +114 -65
- package/src/prices/providers/BinancePriceProvider.ts +7 -0
- package/src/prices/providers/CoinGeckoPriceProvider.ts +6 -0
- package/src/prices/providers/CoinPaprikaPriceProvider.ts +6 -0
- package/src/prices/providers/CustomPriceProvider.ts +11 -0
- package/src/prices/providers/KrakenPriceProvider.ts +9 -0
- package/src/prices/providers/OKXPriceProvider.ts +6 -0
- package/src/prices/providers/abstract/ExchangePriceProvider.ts +3 -0
- package/src/storage/IUnifiedStorage.ts +19 -7
- package/src/storage/UnifiedSwapStorage.ts +33 -3
- package/src/storage-browser/IndexedDBUnifiedStorage.ts +31 -8
- package/src/storage-browser/LocalStorageManager.ts +25 -1
- package/src/swapper/Swapper.ts +513 -379
- package/src/swapper/SwapperFactory.ts +44 -21
- package/src/swapper/SwapperUtils.ts +107 -60
- package/src/swapper/SwapperWithChain.ts +320 -81
- package/src/swapper/SwapperWithSigner.ts +263 -56
- package/src/swaps/IAddressSwap.ts +11 -1
- package/src/swaps/IBTCWalletSwap.ts +24 -8
- package/src/swaps/IClaimableSwap.ts +39 -4
- package/src/swaps/IClaimableSwapWrapper.ts +11 -2
- package/src/swaps/IRefundableSwap.ts +32 -3
- package/src/swaps/ISwap.ts +221 -82
- package/src/swaps/ISwapWithGasDrop.ts +6 -0
- package/src/swaps/ISwapWrapper.ts +212 -94
- package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +62 -18
- package/src/swaps/escrow_swaps/IEscrowSwap.ts +83 -37
- package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +61 -30
- package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +37 -19
- package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +120 -51
- package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +24 -11
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +559 -256
- package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +155 -61
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +590 -226
- package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +177 -74
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +470 -243
- package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +141 -59
- package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +352 -193
- package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +48 -23
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +86 -39
- package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +110 -110
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +88 -33
- package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +101 -31
- package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +534 -263
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +289 -148
- package/src/swaps/trusted/ln/LnForGasSwap.ts +184 -45
- package/src/swaps/trusted/ln/LnForGasWrapper.ts +34 -15
- package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +260 -86
- package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +41 -19
- package/src/types/AmountData.ts +2 -1
- package/src/types/CustomPriceFunction.ts +7 -1
- package/src/types/SwapExecutionAction.ts +84 -5
- package/src/types/SwapWithSigner.ts +7 -3
- package/src/types/Token.ts +12 -5
- package/src/types/TokenAmount.ts +3 -0
- package/src/types/fees/Fee.ts +2 -1
- package/src/types/fees/FeeBreakdown.ts +2 -1
- package/src/types/fees/PercentagePPM.ts +2 -0
- package/src/types/lnurl/LNURLPay.ts +14 -6
- package/src/types/lnurl/LNURLWithdraw.ts +12 -5
- package/src/types/wallets/LightningInvoiceCreateService.ts +26 -0
- package/src/types/wallets/MinimalBitcoinWalletInterface.ts +3 -1
- package/src/types/wallets/MinimalLightningNetworkWalletInterface.ts +3 -1
- package/src/utils/BitcoinUtils.ts +5 -0
- package/src/utils/SwapUtils.ts +61 -1
- package/src/utils/TokenUtils.ts +12 -4
- package/dist/bitcoin/BitcoinRpcWithAddressIndex.d.ts +0 -68
- package/dist/bitcoin/BitcoinRpcWithAddressIndex.js +0 -2
- package/dist/bitcoin/LightningNetworkApi.d.ts +0 -12
- package/dist/bitcoin/LightningNetworkApi.js +0 -2
- package/dist/bitcoin/mempool/MempoolApi.d.ts +0 -350
- package/dist/bitcoin/mempool/MempoolApi.js +0 -311
- package/dist/bitcoin/mempool/MempoolBitcoinBlock.d.ts +0 -44
- package/dist/bitcoin/mempool/MempoolBitcoinBlock.js +0 -48
- package/dist/bitcoin/mempool/MempoolBitcoinRpc.d.ts +0 -119
- package/dist/bitcoin/mempool/MempoolBitcoinRpc.js +0 -361
- package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.d.ts +0 -22
- package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.js +0 -105
- package/dist/errors/PaymentAuthError.d.ts +0 -11
- package/dist/errors/PaymentAuthError.js +0 -23
- package/src/errors/PaymentAuthError.ts +0 -26
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {ISwapWrapper, ISwapWrapperOptions, SwapTypeDefinition, WrapperCtorTokens} from "../ISwapWrapper";
|
|
2
2
|
import {
|
|
3
|
-
BitcoinRpcWithAddressIndex,
|
|
3
|
+
BitcoinRpcWithAddressIndex, BtcBlock,
|
|
4
4
|
BtcRelay,
|
|
5
5
|
ChainEvent,
|
|
6
6
|
ChainType,
|
|
7
7
|
RelaySynchronizer,
|
|
8
8
|
SpvVaultClaimEvent,
|
|
9
|
-
SpvVaultCloseEvent,
|
|
9
|
+
SpvVaultCloseEvent, SpvVaultData,
|
|
10
10
|
SpvVaultFrontEvent,
|
|
11
11
|
SpvVaultTokenBalance,
|
|
12
|
+
SpvWithdrawalClaimedState,
|
|
13
|
+
SpvWithdrawalFrontedState,
|
|
12
14
|
SpvWithdrawalStateType
|
|
13
15
|
} from "@atomiqlabs/base";
|
|
14
16
|
import {SpvFromBTCSwap, SpvFromBTCSwapInit, SpvFromBTCSwapState} from "./SpvFromBTCSwap";
|
|
@@ -20,7 +22,7 @@ import {ISwapPrice} from "../../prices/abstract/ISwapPrice";
|
|
|
20
22
|
import {EventEmitter} from "events";
|
|
21
23
|
import {Intermediary} from "../../intermediaries/Intermediary";
|
|
22
24
|
import {extendAbortController, randomBytes, throwIfUndefined} from "../../utils/Utils";
|
|
23
|
-
import {toCoinselectAddressType, toOutputScript} from "../../utils/BitcoinUtils";
|
|
25
|
+
import {fromOutputScript, toCoinselectAddressType, toOutputScript} from "../../utils/BitcoinUtils";
|
|
24
26
|
import {IntermediaryAPI, SpvFromBTCPrepareResponseType} from "../../intermediaries/apis/IntermediaryAPI";
|
|
25
27
|
import {RequestError} from "../../errors/RequestError";
|
|
26
28
|
import {IntermediaryError} from "../../errors/IntermediaryError";
|
|
@@ -51,20 +53,71 @@ export type SpvFromBTCWrapperOptions = ISwapWrapperOptions & {
|
|
|
51
53
|
|
|
52
54
|
export type SpvFromBTCTypeDefinition<T extends ChainType> = SwapTypeDefinition<T, SpvFromBTCWrapper<T>, SpvFromBTCSwap<T>>;
|
|
53
55
|
|
|
56
|
+
/**
|
|
57
|
+
* New spv vault (UTXO-controlled vault) based swaps for Bitcoin -> Smart chain swaps not requiring
|
|
58
|
+
* any initiation on the destination chain, and with the added possibility for the user to receive
|
|
59
|
+
* a native token on the destination chain as part of the swap (a "gas drop" feature).
|
|
60
|
+
*
|
|
61
|
+
* @category Swaps
|
|
62
|
+
*/
|
|
54
63
|
export class SpvFromBTCWrapper<
|
|
55
64
|
T extends ChainType
|
|
56
65
|
> extends ISwapWrapper<T, SpvFromBTCTypeDefinition<T>, SpvFromBTCWrapperOptions> implements IClaimableSwapWrapper<SpvFromBTCSwap<T>> {
|
|
66
|
+
public readonly TYPE: SwapType.SPV_VAULT_FROM_BTC = SwapType.SPV_VAULT_FROM_BTC;
|
|
67
|
+
/**
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
readonly _claimableSwapStates = [SpvFromBTCSwapState.BTC_TX_CONFIRMED];
|
|
71
|
+
/**
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
readonly _swapDeserializer = SpvFromBTCSwap;
|
|
57
75
|
|
|
58
|
-
public readonly claimableSwapStates = [SpvFromBTCSwapState.BTC_TX_CONFIRMED];
|
|
59
|
-
public readonly TYPE = SwapType.SPV_VAULT_FROM_BTC;
|
|
60
|
-
public readonly swapDeserializer = SpvFromBTCSwap;
|
|
61
76
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
readonly
|
|
77
|
+
/**
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
protected readonly btcRelay: T["BtcRelay"];
|
|
81
|
+
/**
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
84
|
+
protected readonly tickSwapState: Array<SpvFromBTCSwap<T>["_state"]> = [
|
|
85
|
+
SpvFromBTCSwapState.CREATED,
|
|
86
|
+
SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED,
|
|
87
|
+
SpvFromBTCSwapState.SIGNED,
|
|
88
|
+
SpvFromBTCSwapState.POSTED,
|
|
89
|
+
SpvFromBTCSwapState.BROADCASTED
|
|
90
|
+
];
|
|
66
91
|
|
|
67
|
-
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
readonly _synchronizer: RelaySynchronizer<any, T["TX"], any>;
|
|
97
|
+
/**
|
|
98
|
+
* @internal
|
|
99
|
+
*/
|
|
100
|
+
readonly _contract: T["SpvVaultContract"];
|
|
101
|
+
/**
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
readonly _btcRpc: BitcoinRpcWithAddressIndex<BtcBlock>;
|
|
105
|
+
/**
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
108
|
+
readonly _spvWithdrawalDataDeserializer: new (data: any) => T["SpvVaultWithdrawalData"];
|
|
109
|
+
/**
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
readonly _pendingSwapStates: Array<SpvFromBTCSwap<T>["_state"]> = [
|
|
113
|
+
SpvFromBTCSwapState.CREATED,
|
|
114
|
+
SpvFromBTCSwapState.SIGNED,
|
|
115
|
+
SpvFromBTCSwapState.POSTED,
|
|
116
|
+
SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED,
|
|
117
|
+
SpvFromBTCSwapState.BROADCASTED,
|
|
118
|
+
SpvFromBTCSwapState.DECLINED,
|
|
119
|
+
SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
120
|
+
];
|
|
68
121
|
|
|
69
122
|
/**
|
|
70
123
|
* @param chainIdentifier
|
|
@@ -96,108 +149,87 @@ export class SpvFromBTCWrapper<
|
|
|
96
149
|
options?: AllOptional<SpvFromBTCWrapperOptions>,
|
|
97
150
|
events?: EventEmitter<{swapState: [ISwap]}>
|
|
98
151
|
) {
|
|
99
|
-
if(options==null) options = {};
|
|
100
|
-
options.bitcoinNetwork ??= TEST_NETWORK;
|
|
101
|
-
options.maxConfirmations ??= 6;
|
|
102
|
-
options.bitcoinBlocktime ??= 10*60;
|
|
103
|
-
options.maxTransactionsDelta ??= 3;
|
|
104
|
-
options.maxRawAmountAdjustmentDifferencePPM ??= 100;
|
|
105
|
-
options.maxBtcFeeOffset ??= 5;
|
|
106
|
-
options.maxBtcFeeMultiplier ??= 1.5;
|
|
107
152
|
super(
|
|
108
153
|
chainIdentifier, unifiedStorage, unifiedChainEvents, chain, prices, tokens,
|
|
109
154
|
{
|
|
110
|
-
bitcoinNetwork: options
|
|
111
|
-
maxConfirmations: options
|
|
112
|
-
bitcoinBlocktime: options
|
|
113
|
-
maxTransactionsDelta: options
|
|
114
|
-
maxRawAmountAdjustmentDifferencePPM: options
|
|
115
|
-
maxBtcFeeOffset: options
|
|
116
|
-
maxBtcFeeMultiplier: options
|
|
155
|
+
bitcoinNetwork: options?.bitcoinNetwork ?? TEST_NETWORK,
|
|
156
|
+
maxConfirmations: options?.maxConfirmations ?? 6,
|
|
157
|
+
bitcoinBlocktime: options?.bitcoinBlocktime ?? 10*60,
|
|
158
|
+
maxTransactionsDelta: options?.maxTransactionsDelta ?? 3,
|
|
159
|
+
maxRawAmountAdjustmentDifferencePPM: options?.maxRawAmountAdjustmentDifferencePPM ?? 100,
|
|
160
|
+
maxBtcFeeOffset: options?.maxBtcFeeOffset ?? 10,
|
|
161
|
+
maxBtcFeeMultiplier: options?.maxBtcFeeMultiplier ?? 1.5
|
|
117
162
|
},
|
|
118
163
|
events
|
|
119
164
|
);
|
|
120
|
-
this.
|
|
121
|
-
this.
|
|
165
|
+
this._spvWithdrawalDataDeserializer = spvWithdrawalDataDeserializer;
|
|
166
|
+
this._contract = contract;
|
|
122
167
|
this.btcRelay = btcRelay;
|
|
123
|
-
this.
|
|
124
|
-
this.
|
|
168
|
+
this._synchronizer = synchronizer;
|
|
169
|
+
this._btcRpc = btcRpc;
|
|
125
170
|
}
|
|
126
171
|
|
|
127
|
-
|
|
128
|
-
SpvFromBTCSwapState.CREATED,
|
|
129
|
-
SpvFromBTCSwapState.SIGNED,
|
|
130
|
-
SpvFromBTCSwapState.POSTED,
|
|
131
|
-
SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED,
|
|
132
|
-
SpvFromBTCSwapState.BROADCASTED,
|
|
133
|
-
SpvFromBTCSwapState.DECLINED,
|
|
134
|
-
SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
135
|
-
];
|
|
136
|
-
readonly tickSwapState: Array<SpvFromBTCSwap<T>["state"]> = [
|
|
137
|
-
SpvFromBTCSwapState.CREATED,
|
|
138
|
-
SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED,
|
|
139
|
-
SpvFromBTCSwapState.SIGNED,
|
|
140
|
-
SpvFromBTCSwapState.POSTED,
|
|
141
|
-
SpvFromBTCSwapState.BROADCASTED
|
|
142
|
-
];
|
|
143
|
-
|
|
144
|
-
protected async processEventFront(event: SpvVaultFrontEvent, swap: SpvFromBTCSwap<T>): Promise<boolean> {
|
|
172
|
+
private async processEventFront(event: SpvVaultFrontEvent, swap: SpvFromBTCSwap<T>): Promise<boolean> {
|
|
145
173
|
if(
|
|
146
|
-
swap.
|
|
147
|
-
swap.
|
|
148
|
-
swap.
|
|
174
|
+
swap._state===SpvFromBTCSwapState.SIGNED || swap._state===SpvFromBTCSwapState.POSTED ||
|
|
175
|
+
swap._state===SpvFromBTCSwapState.BROADCASTED || swap._state===SpvFromBTCSwapState.DECLINED ||
|
|
176
|
+
swap._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED || swap._state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
149
177
|
) {
|
|
150
178
|
await swap._setBitcoinTxId(event.btcTxId).catch(e => {
|
|
151
179
|
this.logger.warn("processEventFront(): Failed to set bitcoin txId: ", e);
|
|
152
180
|
});
|
|
153
|
-
swap.
|
|
181
|
+
swap._state = SpvFromBTCSwapState.FRONTED;
|
|
154
182
|
return true;
|
|
155
183
|
}
|
|
156
184
|
return false;
|
|
157
185
|
}
|
|
158
186
|
|
|
159
|
-
|
|
187
|
+
private async processEventClaim(event: SpvVaultClaimEvent, swap: SpvFromBTCSwap<T>): Promise<boolean> {
|
|
160
188
|
if(
|
|
161
|
-
swap.
|
|
162
|
-
swap.
|
|
163
|
-
swap.
|
|
189
|
+
swap._state===SpvFromBTCSwapState.SIGNED || swap._state===SpvFromBTCSwapState.POSTED ||
|
|
190
|
+
swap._state===SpvFromBTCSwapState.BROADCASTED || swap._state===SpvFromBTCSwapState.DECLINED ||
|
|
191
|
+
swap._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED || swap._state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
164
192
|
) {
|
|
165
193
|
await swap._setBitcoinTxId(event.btcTxId).catch(e => {
|
|
166
194
|
this.logger.warn("processEventClaim(): Failed to set bitcoin txId: ", e);
|
|
167
195
|
});
|
|
168
|
-
swap.
|
|
196
|
+
swap._state = SpvFromBTCSwapState.CLAIMED;
|
|
169
197
|
return true;
|
|
170
198
|
}
|
|
171
199
|
return false;
|
|
172
200
|
}
|
|
173
201
|
|
|
174
|
-
|
|
202
|
+
private processEventClose(event: SpvVaultCloseEvent, swap: SpvFromBTCSwap<T>): Promise<boolean> {
|
|
175
203
|
if(
|
|
176
|
-
swap.
|
|
177
|
-
swap.
|
|
178
|
-
swap.
|
|
204
|
+
swap._state===SpvFromBTCSwapState.SIGNED || swap._state===SpvFromBTCSwapState.POSTED ||
|
|
205
|
+
swap._state===SpvFromBTCSwapState.BROADCASTED || swap._state===SpvFromBTCSwapState.DECLINED ||
|
|
206
|
+
swap._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED || swap._state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
179
207
|
) {
|
|
180
|
-
swap.
|
|
208
|
+
swap._state = SpvFromBTCSwapState.CLOSED;
|
|
181
209
|
return Promise.resolve(true);
|
|
182
210
|
}
|
|
183
211
|
return Promise.resolve(false);
|
|
184
212
|
}
|
|
185
213
|
|
|
214
|
+
/**
|
|
215
|
+
* @inheritDoc
|
|
216
|
+
* @internal
|
|
217
|
+
*/
|
|
186
218
|
protected async processEvent(event: ChainEvent<T["Data"]>, swap: SpvFromBTCSwap<T>): Promise<void> {
|
|
187
219
|
if(swap==null) return;
|
|
188
220
|
|
|
189
221
|
let swapChanged: boolean = false;
|
|
190
222
|
if(event instanceof SpvVaultFrontEvent) {
|
|
191
223
|
swapChanged = await this.processEventFront(event, swap);
|
|
192
|
-
if(event.meta?.txId!=null && swap.
|
|
193
|
-
swap.
|
|
224
|
+
if(event.meta?.txId!=null && swap._frontTxId!==event.meta.txId) {
|
|
225
|
+
swap._frontTxId = event.meta.txId;
|
|
194
226
|
swapChanged ||= true;
|
|
195
227
|
}
|
|
196
228
|
}
|
|
197
229
|
if(event instanceof SpvVaultClaimEvent) {
|
|
198
230
|
swapChanged = await this.processEventClaim(event, swap);
|
|
199
|
-
if(event.meta?.txId!=null && swap.
|
|
200
|
-
swap.
|
|
231
|
+
if(event.meta?.txId!=null && swap._claimTxId!==event.meta.txId) {
|
|
232
|
+
swap._claimTxId = event.meta.txId;
|
|
201
233
|
swapChanged ||= true;
|
|
202
234
|
}
|
|
203
235
|
}
|
|
@@ -220,7 +252,7 @@ export class SpvFromBTCWrapper<
|
|
|
220
252
|
*/
|
|
221
253
|
private async preFetchFinalizedBlockHeight(abortController: AbortController): Promise<number | undefined> {
|
|
222
254
|
try {
|
|
223
|
-
const block = await this.
|
|
255
|
+
const block = await this._chain.getFinalizedBlock();
|
|
224
256
|
return block.height;
|
|
225
257
|
} catch (e) {
|
|
226
258
|
abortController.abort(e);
|
|
@@ -258,36 +290,36 @@ export class SpvFromBTCWrapper<
|
|
|
258
290
|
] = await Promise.all([
|
|
259
291
|
this.btcRelay.getFeePerBlock(),
|
|
260
292
|
this.btcRelay.getTipData(),
|
|
261
|
-
this.
|
|
262
|
-
this.
|
|
263
|
-
nativeTokenPricePrefetch ?? (amountData.token===this.
|
|
293
|
+
this._btcRpc.getTipHeight(),
|
|
294
|
+
this._contract.getClaimFee(this._chain.randomAddress()),
|
|
295
|
+
nativeTokenPricePrefetch ?? (amountData.token===this._chain.getNativeCurrencyAddress() ?
|
|
264
296
|
pricePrefetch :
|
|
265
|
-
this.
|
|
297
|
+
this._prices.preFetchPrice(this.chainIdentifier, this._chain.getNativeCurrencyAddress(), abortController.signal))
|
|
266
298
|
]);
|
|
267
299
|
|
|
268
300
|
if(btcRelayData==null) throw new Error("Btc relay doesn't seem to be initialized!");
|
|
269
301
|
|
|
270
302
|
const currentBtcRelayBlock = btcRelayData.blockheight;
|
|
271
|
-
const blockDelta = Math.max(currentBtcBlock-currentBtcRelayBlock+this.
|
|
303
|
+
const blockDelta = Math.max(currentBtcBlock-currentBtcRelayBlock+this._options.maxConfirmations, 0);
|
|
272
304
|
|
|
273
305
|
const totalFeeInNativeToken = (
|
|
274
306
|
(BigInt(blockDelta) * feePerBlock) +
|
|
275
|
-
(claimFeeRate * BigInt(this.
|
|
307
|
+
(claimFeeRate * BigInt(this._options.maxTransactionsDelta))
|
|
276
308
|
) * BigInt(Math.floor(options.feeSafetyFactor*1000000)) / 1_000_000n;
|
|
277
309
|
|
|
278
310
|
let payoutAmount: bigint;
|
|
279
311
|
if(amountData.exactIn) {
|
|
280
312
|
//Convert input amount in BTC to
|
|
281
|
-
const amountInNativeToken = await this.
|
|
313
|
+
const amountInNativeToken = await this._prices.getFromBtcSwapAmount(this.chainIdentifier, amountData.amount, this._chain.getNativeCurrencyAddress(), abortController.signal, nativeTokenPrice);
|
|
282
314
|
payoutAmount = amountInNativeToken - totalFeeInNativeToken;
|
|
283
315
|
} else {
|
|
284
|
-
if(amountData.token===this.
|
|
316
|
+
if(amountData.token===this._chain.getNativeCurrencyAddress()) {
|
|
285
317
|
//Both amounts in same currency
|
|
286
318
|
payoutAmount = amountData.amount;
|
|
287
319
|
} else {
|
|
288
320
|
//Need to convert both to native currency
|
|
289
|
-
const btcAmount = await this.
|
|
290
|
-
payoutAmount = await this.
|
|
321
|
+
const btcAmount = await this._prices.getToBtcSwapAmount(this.chainIdentifier, amountData.amount, amountData.token, abortController.signal, await pricePrefetch);
|
|
322
|
+
payoutAmount = await this._prices.getFromBtcSwapAmount(this.chainIdentifier, btcAmount, this._chain.getNativeCurrencyAddress(), abortController.signal, nativeTokenPrice);
|
|
291
323
|
}
|
|
292
324
|
}
|
|
293
325
|
|
|
@@ -330,7 +362,7 @@ export class SpvFromBTCWrapper<
|
|
|
330
362
|
}> {
|
|
331
363
|
const btcFeeRate = await throwIfUndefined(bitcoinFeeRatePromise, "Bitcoin fee rate promise failed!");
|
|
332
364
|
abortSignal.throwIfAborted();
|
|
333
|
-
if(btcFeeRate!=null && resp.btcFeeRate > btcFeeRate) throw new IntermediaryError(
|
|
365
|
+
if(btcFeeRate!=null && resp.btcFeeRate > btcFeeRate) throw new IntermediaryError(`Required bitcoin fee rate returned from the LP is too high! Maximum accepted: ${btcFeeRate} sats/vB, required by LP: ${resp.btcFeeRate} sats/vB`);
|
|
334
366
|
|
|
335
367
|
//Vault related
|
|
336
368
|
let vaultScript: Uint8Array;
|
|
@@ -338,9 +370,9 @@ export class SpvFromBTCWrapper<
|
|
|
338
370
|
let btcAddressScript: Uint8Array;
|
|
339
371
|
//Ensure valid btc addresses returned
|
|
340
372
|
try {
|
|
341
|
-
vaultScript = toOutputScript(this.
|
|
373
|
+
vaultScript = toOutputScript(this._options.bitcoinNetwork, resp.vaultBtcAddress);
|
|
342
374
|
vaultAddressType = toCoinselectAddressType(vaultScript);
|
|
343
|
-
btcAddressScript = toOutputScript(this.
|
|
375
|
+
btcAddressScript = toOutputScript(this._options.bitcoinNetwork, resp.btcAddress);
|
|
344
376
|
} catch (e) {
|
|
345
377
|
throw new IntermediaryError("Invalid btc address data returned", e);
|
|
346
378
|
}
|
|
@@ -379,7 +411,7 @@ export class SpvFromBTCWrapper<
|
|
|
379
411
|
//Fetch vault data
|
|
380
412
|
let vault: T["SpvVaultData"] | null;
|
|
381
413
|
try {
|
|
382
|
-
vault = await this.
|
|
414
|
+
vault = await this._contract.getVaultData(resp.address, resp.vaultId);
|
|
383
415
|
} catch (e) {
|
|
384
416
|
this.logger.error("Error getting spv vault (owner: "+resp.address+" vaultId: "+resp.vaultId.toString(10)+"): ", e);
|
|
385
417
|
throw new IntermediaryError("Spv swap vault not found", e);
|
|
@@ -389,7 +421,7 @@ export class SpvFromBTCWrapper<
|
|
|
389
421
|
//Make sure vault is opened
|
|
390
422
|
if(vault==null || !vault.isOpened()) throw new IntermediaryError("Returned spv swap vault is not opened!");
|
|
391
423
|
//Make sure the vault doesn't require insane amount of confirmations
|
|
392
|
-
if(vault.getConfirmations()>this.
|
|
424
|
+
if(vault.getConfirmations()>this._options.maxConfirmations) throw new IntermediaryError("SPV swap vault needs too many confirmations: "+vault.getConfirmations());
|
|
393
425
|
const tokenData = vault.getTokenData();
|
|
394
426
|
|
|
395
427
|
//Amounts - make sure the amounts match
|
|
@@ -399,7 +431,7 @@ export class SpvFromBTCWrapper<
|
|
|
399
431
|
//Check the difference between amount adjusted due to scaling to raw amount
|
|
400
432
|
const adjustedAmount = amountData.amount / tokenData[0].multiplier * tokenData[0].multiplier;
|
|
401
433
|
const adjustmentPPM = (amountData.amount - adjustedAmount)*1_000_000n / amountData.amount;
|
|
402
|
-
if(adjustmentPPM > this.
|
|
434
|
+
if(adjustmentPPM > this._options.maxRawAmountAdjustmentDifferencePPM)
|
|
403
435
|
throw new IntermediaryError("Invalid amount0 multiplier used, rawAmount diff too high");
|
|
404
436
|
if(resp.total !== adjustedAmount) throw new IntermediaryError("Invalid total returned");
|
|
405
437
|
}
|
|
@@ -409,7 +441,7 @@ export class SpvFromBTCWrapper<
|
|
|
409
441
|
//Check the difference between amount adjusted due to scaling to raw amount
|
|
410
442
|
const adjustedGasAmount = options.gasAmount / tokenData[0].multiplier * tokenData[0].multiplier;
|
|
411
443
|
const adjustmentPPM = (options.gasAmount - adjustedGasAmount)*1_000_000n / options.gasAmount;
|
|
412
|
-
if(adjustmentPPM > this.
|
|
444
|
+
if(adjustmentPPM > this._options.maxRawAmountAdjustmentDifferencePPM)
|
|
413
445
|
throw new IntermediaryError("Invalid amount1 multiplier used, rawAmount diff too high");
|
|
414
446
|
if(resp.totalGas !== adjustedGasAmount) throw new IntermediaryError("Invalid gas total returned");
|
|
415
447
|
}
|
|
@@ -418,7 +450,7 @@ export class SpvFromBTCWrapper<
|
|
|
418
450
|
})(),
|
|
419
451
|
(async() => {
|
|
420
452
|
//Require the vault UTXO to have at least 1 confirmation
|
|
421
|
-
let btcTx = await this.
|
|
453
|
+
let btcTx = await this._btcRpc.getTransaction(txId);
|
|
422
454
|
if(btcTx==null) throw new IntermediaryError("Invalid UTXO, doesn't exist (txId)");
|
|
423
455
|
abortController.signal.throwIfAborted();
|
|
424
456
|
if(btcTx.confirmations==null || btcTx.confirmations<1) throw new IntermediaryError("SPV vault UTXO not confirmed");
|
|
@@ -429,7 +461,7 @@ export class SpvFromBTCWrapper<
|
|
|
429
461
|
})(),
|
|
430
462
|
(async() => {
|
|
431
463
|
//Require vault UTXO is unspent
|
|
432
|
-
if(await this.
|
|
464
|
+
if(await this._btcRpc.isSpent(utxo)) throw new IntermediaryError("Returned spv vault UTXO is already spent", null, true);
|
|
433
465
|
abortController.signal.throwIfAborted();
|
|
434
466
|
})()
|
|
435
467
|
]).catch(e => {
|
|
@@ -445,17 +477,17 @@ export class SpvFromBTCWrapper<
|
|
|
445
477
|
const [txId, voutStr] = utxo.split(":");
|
|
446
478
|
//Such that 1st tx isn't fetched twice
|
|
447
479
|
if(btcTx.txid!==txId) {
|
|
448
|
-
const _btcTx = await this.
|
|
480
|
+
const _btcTx = await this._btcRpc.getTransaction(txId);
|
|
449
481
|
if(_btcTx==null) throw new IntermediaryError("Invalid ancestor transaction (not found)");
|
|
450
482
|
btcTx = _btcTx;
|
|
451
483
|
}
|
|
452
|
-
const withdrawalData = await this.
|
|
484
|
+
const withdrawalData = await this._contract.getWithdrawalData(btcTx);
|
|
453
485
|
abortSignal.throwIfAborted();
|
|
454
486
|
pendingWithdrawals.unshift(withdrawalData);
|
|
455
487
|
utxo = pendingWithdrawals[0].getSpentVaultUtxo();
|
|
456
488
|
this.logger.debug("verifyReturnedData(): Vault UTXO: "+vault.getUtxo()+" current utxo: "+utxo);
|
|
457
|
-
if(pendingWithdrawals.length>=this.
|
|
458
|
-
throw new IntermediaryError("BTC <> SC state difference too deep, maximum: "+this.
|
|
489
|
+
if(pendingWithdrawals.length>=this._options.maxTransactionsDelta)
|
|
490
|
+
throw new IntermediaryError("BTC <> SC state difference too deep, maximum: "+this._options.maxTransactionsDelta);
|
|
459
491
|
}
|
|
460
492
|
|
|
461
493
|
//Verify that the vault has enough balance after processing all pending withdrawals
|
|
@@ -476,7 +508,7 @@ export class SpvFromBTCWrapper<
|
|
|
476
508
|
//Also verify that all the withdrawal txns are valid, this is an extra sanity check
|
|
477
509
|
try {
|
|
478
510
|
for(let withdrawal of pendingWithdrawals) {
|
|
479
|
-
await this.
|
|
511
|
+
await this._contract.checkWithdrawalTx(withdrawal);
|
|
480
512
|
}
|
|
481
513
|
} catch (e) {
|
|
482
514
|
this.logger.error("Error calculating spv vault balance (owner: "+resp.address+" vaultId: "+resp.vaultId.toString(10)+"): ", e);
|
|
@@ -491,17 +523,19 @@ export class SpvFromBTCWrapper<
|
|
|
491
523
|
}
|
|
492
524
|
|
|
493
525
|
/**
|
|
494
|
-
* Returns a newly created swap
|
|
526
|
+
* Returns a newly created Bitcoin -> Smart chain swap using the SPV vault (UTXO-controlled vault) swap protocol,
|
|
527
|
+
* with the passed amount. Also allows specifying additional "gas drop" native token that the receipient receives
|
|
528
|
+
* on the destination chain in the `options` argument.
|
|
495
529
|
*
|
|
496
|
-
* @param
|
|
497
|
-
* @param amountData
|
|
498
|
-
* @param lps
|
|
499
|
-
* @param options
|
|
500
|
-
* @param additionalParams
|
|
501
|
-
* @param abortSignal
|
|
530
|
+
* @param recipient Recipient address on the destination smart chain
|
|
531
|
+
* @param amountData Amount, token and exact input/output data for to swap
|
|
532
|
+
* @param lps An array of intermediaries (LPs) to get the quotes from
|
|
533
|
+
* @param options Optional additional quote options
|
|
534
|
+
* @param additionalParams Optional additional parameters sent to the LP when creating the swap
|
|
535
|
+
* @param abortSignal Abort signal
|
|
502
536
|
*/
|
|
503
|
-
create(
|
|
504
|
-
|
|
537
|
+
public create(
|
|
538
|
+
recipient: string,
|
|
505
539
|
amountData: AmountData,
|
|
506
540
|
lps: Intermediary[],
|
|
507
541
|
options?: SpvFromBTCOptions,
|
|
@@ -522,14 +556,14 @@ export class SpvFromBTCWrapper<
|
|
|
522
556
|
const pricePrefetchPromise: Promise<bigint | undefined> = this.preFetchPrice(amountData, _abortController.signal);
|
|
523
557
|
const usdPricePrefetchPromise: Promise<number | undefined> = this.preFetchUsdPrice(_abortController.signal);
|
|
524
558
|
const finalizedBlockHeightPrefetchPromise: Promise<number | undefined> = this.preFetchFinalizedBlockHeight(_abortController);
|
|
525
|
-
const nativeTokenAddress = this.
|
|
559
|
+
const nativeTokenAddress = this._chain.getNativeCurrencyAddress();
|
|
526
560
|
const gasTokenPricePrefetchPromise: Promise<bigint | undefined> | undefined = _options.gasAmount===0n ?
|
|
527
561
|
undefined :
|
|
528
562
|
this.preFetchPrice({token: nativeTokenAddress}, _abortController.signal);
|
|
529
563
|
const callerFeePrefetchPromise = this.preFetchCallerFeeShare(amountData, _options, pricePrefetchPromise, gasTokenPricePrefetchPromise, _abortController);
|
|
530
564
|
const bitcoinFeeRatePromise: Promise<number | undefined> = _options.maxAllowedNetworkFeeRate!=Infinity ?
|
|
531
565
|
Promise.resolve(_options.maxAllowedNetworkFeeRate) :
|
|
532
|
-
this.
|
|
566
|
+
this._btcRpc.getFeeRate().then(x => this._options.maxBtcFeeOffset + (x*this._options.maxBtcFeeMultiplier)).catch(e => {
|
|
533
567
|
_abortController.abort(e);
|
|
534
568
|
return undefined;
|
|
535
569
|
});
|
|
@@ -547,7 +581,7 @@ export class SpvFromBTCWrapper<
|
|
|
547
581
|
return await IntermediaryAPI.prepareSpvFromBTC(
|
|
548
582
|
this.chainIdentifier, lp.url,
|
|
549
583
|
{
|
|
550
|
-
address:
|
|
584
|
+
address: recipient,
|
|
551
585
|
amount: amountData.amount,
|
|
552
586
|
token: amountData.token.toString(),
|
|
553
587
|
exactOut: !amountData.exactIn,
|
|
@@ -557,7 +591,7 @@ export class SpvFromBTCWrapper<
|
|
|
557
591
|
frontingFeeRate: 0n,
|
|
558
592
|
additionalParams
|
|
559
593
|
},
|
|
560
|
-
this.
|
|
594
|
+
this._options.postRequestTimeout, abortController.signal, retryCount>0 ? false : undefined
|
|
561
595
|
);
|
|
562
596
|
}, undefined, e => e instanceof RequestError, abortController.signal);
|
|
563
597
|
|
|
@@ -595,7 +629,7 @@ export class SpvFromBTCWrapper<
|
|
|
595
629
|
|
|
596
630
|
quoteId: resp.quoteId,
|
|
597
631
|
|
|
598
|
-
recipient
|
|
632
|
+
recipient,
|
|
599
633
|
|
|
600
634
|
vaultOwner: resp.address,
|
|
601
635
|
vaultId: resp.vaultId,
|
|
@@ -640,11 +674,117 @@ export class SpvFromBTCWrapper<
|
|
|
640
674
|
});
|
|
641
675
|
}
|
|
642
676
|
|
|
677
|
+
/**
|
|
678
|
+
* Recovers an SPV vault (UTXO-controlled vault) based swap from smart chain on-chain data
|
|
679
|
+
*
|
|
680
|
+
* @param state State of the spv vault withdrawal recovered from on-chain data
|
|
681
|
+
* @param vault SPV vault processing the swap
|
|
682
|
+
* @param lp Intermediary (LP) used as a counterparty for the swap
|
|
683
|
+
*/
|
|
684
|
+
public async recoverFromState(state: SpvWithdrawalClaimedState | SpvWithdrawalFrontedState, vault?: SpvVaultData | null, lp?: Intermediary): Promise<SpvFromBTCSwap<T> | null> {
|
|
685
|
+
//Get the vault
|
|
686
|
+
vault ??= await this._contract.getVaultData(state.owner, state.vaultId);
|
|
687
|
+
if(vault==null) return null;
|
|
688
|
+
if(state.btcTxId==null) return null;
|
|
689
|
+
const btcTx = await this._btcRpc.getTransaction(state.btcTxId);
|
|
690
|
+
if(btcTx==null) return null;
|
|
691
|
+
const withdrawalData = await this._contract.getWithdrawalData(btcTx)
|
|
692
|
+
.catch(e => {
|
|
693
|
+
this.logger.warn(`Error parsing withdrawal data for tx ${btcTx.txid}: `, e);
|
|
694
|
+
return null;
|
|
695
|
+
});
|
|
696
|
+
if(withdrawalData==null) return null;
|
|
697
|
+
|
|
698
|
+
const vaultTokens = vault.getTokenData();
|
|
699
|
+
const withdrawalDataOutputs = withdrawalData.getTotalOutput();
|
|
700
|
+
|
|
701
|
+
const txBlock = await state.getTxBlock?.();
|
|
702
|
+
|
|
703
|
+
const swapInit: SpvFromBTCSwapInit = {
|
|
704
|
+
pricingInfo: {
|
|
705
|
+
isValid: true,
|
|
706
|
+
satsBaseFee: 0n,
|
|
707
|
+
swapPriceUSatPerToken: 100_000_000_000_000n,
|
|
708
|
+
realPriceUSatPerToken: 100_000_000_000_000n,
|
|
709
|
+
differencePPM: 0n,
|
|
710
|
+
feePPM: 0n,
|
|
711
|
+
},
|
|
712
|
+
url: lp?.url,
|
|
713
|
+
expiry: 0,
|
|
714
|
+
swapFee: 0n,
|
|
715
|
+
swapFeeBtc: 0n,
|
|
716
|
+
exactIn: true,
|
|
717
|
+
|
|
718
|
+
//Use bitcoin tx id as quote id, even though this is not strictly correct as this
|
|
719
|
+
// is an off-chain identifier presented by the LP that cannot be recovered from on-chain
|
|
720
|
+
// data
|
|
721
|
+
quoteId: btcTx.txid,
|
|
722
|
+
|
|
723
|
+
recipient: state.recipient,
|
|
724
|
+
|
|
725
|
+
vaultOwner: state.owner,
|
|
726
|
+
vaultId: state.vaultId,
|
|
727
|
+
vaultRequiredConfirmations: vault.getConfirmations(),
|
|
728
|
+
vaultTokenMultipliers: vault.getTokenData().map(val => val.multiplier),
|
|
729
|
+
vaultBtcAddress: fromOutputScript(this._options.bitcoinNetwork, withdrawalData.getNewVaultScript().toString("hex")),
|
|
730
|
+
vaultUtxo: withdrawalData.getSpentVaultUtxo(),
|
|
731
|
+
vaultUtxoValue: BigInt(withdrawalData.getNewVaultBtcAmount()),
|
|
732
|
+
|
|
733
|
+
btcDestinationAddress: fromOutputScript(this._options.bitcoinNetwork, btcTx.outs[2].scriptPubKey.hex),
|
|
734
|
+
btcAmount: BigInt(btcTx.outs[2].value),
|
|
735
|
+
btcAmountSwap: BigInt(btcTx.outs[2].value),
|
|
736
|
+
btcAmountGas: 0n,
|
|
737
|
+
minimumBtcFeeRate: 0,
|
|
738
|
+
|
|
739
|
+
outputTotalSwap: withdrawalDataOutputs[0] * vaultTokens[0].multiplier,
|
|
740
|
+
outputSwapToken: vaultTokens[0].token,
|
|
741
|
+
outputTotalGas: withdrawalDataOutputs[1] * vaultTokens[1].multiplier,
|
|
742
|
+
outputGasToken: vaultTokens[1].token,
|
|
743
|
+
gasSwapFeeBtc: 0n,
|
|
744
|
+
gasSwapFee: 0n,
|
|
745
|
+
gasPricingInfo: {
|
|
746
|
+
isValid: true,
|
|
747
|
+
satsBaseFee: 0n,
|
|
748
|
+
swapPriceUSatPerToken: 100_000_000_000_000n,
|
|
749
|
+
realPriceUSatPerToken: 100_000_000_000_000n,
|
|
750
|
+
differencePPM: 0n,
|
|
751
|
+
feePPM: 0n,
|
|
752
|
+
},
|
|
753
|
+
|
|
754
|
+
callerFeeShare: withdrawalData.callerFeeRate,
|
|
755
|
+
frontingFeeShare: withdrawalData.frontingFeeRate,
|
|
756
|
+
executionFeeShare: withdrawalData.executionFeeRate,
|
|
757
|
+
|
|
758
|
+
genesisSmartChainBlockHeight: txBlock?.blockHeight ?? 0
|
|
759
|
+
};
|
|
760
|
+
const quote = new SpvFromBTCSwap<T>(this, swapInit);
|
|
761
|
+
quote._data = withdrawalData;
|
|
762
|
+
if(txBlock!=null) {
|
|
763
|
+
quote.createdAt = txBlock.blockTime*1000;
|
|
764
|
+
} else if(btcTx.blockhash==null) {
|
|
765
|
+
quote.createdAt = Date.now();
|
|
766
|
+
} else {
|
|
767
|
+
const blockHeader = await this._btcRpc.getBlockHeader(btcTx.blockhash);
|
|
768
|
+
quote.createdAt = blockHeader==null ? Date.now() : blockHeader.getTimestamp()*1000;
|
|
769
|
+
}
|
|
770
|
+
quote._setInitiated();
|
|
771
|
+
if(btcTx.inputAddresses!=null) quote._senderAddress = btcTx.inputAddresses[1];
|
|
772
|
+
if(state.type===SpvWithdrawalStateType.FRONTED) {
|
|
773
|
+
quote._frontTxId = state.txId;
|
|
774
|
+
quote._state = SpvFromBTCSwapState.FRONTED;
|
|
775
|
+
} else {
|
|
776
|
+
quote._claimTxId = state.txId;
|
|
777
|
+
quote._state = SpvFromBTCSwapState.CLAIMED;
|
|
778
|
+
}
|
|
779
|
+
await quote._save();
|
|
780
|
+
return quote;
|
|
781
|
+
}
|
|
782
|
+
|
|
643
783
|
/**
|
|
644
784
|
* Returns a random dummy PSBT that can be used for fee estimation, the last output (the LP output) is omitted
|
|
645
785
|
* to allow for coinselection algorithm to determine maximum sendable amount there
|
|
646
786
|
*
|
|
647
|
-
* @param includeGasToken
|
|
787
|
+
* @param includeGasToken Whether to return the PSBT also with the gas token amount (increases the vSize by 8)
|
|
648
788
|
*/
|
|
649
789
|
public getDummySwapPsbt(includeGasToken = false): Transaction {
|
|
650
790
|
//Construct dummy swap psbt
|
|
@@ -670,8 +810,8 @@ export class SpvFromBTCWrapper<
|
|
|
670
810
|
amount: 600n
|
|
671
811
|
});
|
|
672
812
|
|
|
673
|
-
const opReturnData = this.
|
|
674
|
-
this.
|
|
813
|
+
const opReturnData = this._contract.toOpReturnData(
|
|
814
|
+
this._chain.randomAddress(),
|
|
675
815
|
includeGasToken ? [0xFFFFFFFFFFFFFFFFn, 0xFFFFFFFFFFFFFFFFn] : [0xFFFFFFFFFFFFFFFFn]
|
|
676
816
|
);
|
|
677
817
|
|
|
@@ -686,6 +826,10 @@ export class SpvFromBTCWrapper<
|
|
|
686
826
|
return psbt;
|
|
687
827
|
}
|
|
688
828
|
|
|
829
|
+
/**
|
|
830
|
+
* @inheritDoc
|
|
831
|
+
* @internal
|
|
832
|
+
*/
|
|
689
833
|
protected async _checkPastSwaps(pastSwaps: SpvFromBTCSwap<T>[]): Promise<{
|
|
690
834
|
changedSwaps: SpvFromBTCSwap<T>[];
|
|
691
835
|
removeSwaps: SpvFromBTCSwap<T>[]
|
|
@@ -693,33 +837,33 @@ export class SpvFromBTCWrapper<
|
|
|
693
837
|
const changedSwaps: Set<SpvFromBTCSwap<T>> = new Set();
|
|
694
838
|
const removeSwaps: SpvFromBTCSwap<T>[] = [];
|
|
695
839
|
|
|
696
|
-
const broadcastedOrConfirmedSwaps: (SpvFromBTCSwap<T> & {
|
|
840
|
+
const broadcastedOrConfirmedSwaps: (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]})[] = [];
|
|
697
841
|
|
|
698
842
|
for(let pastSwap of pastSwaps) {
|
|
699
843
|
let changed: boolean = false;
|
|
700
844
|
|
|
701
845
|
if(
|
|
702
|
-
pastSwap.
|
|
703
|
-
pastSwap.
|
|
704
|
-
pastSwap.
|
|
705
|
-
pastSwap.
|
|
706
|
-
pastSwap.
|
|
707
|
-
pastSwap.
|
|
846
|
+
pastSwap._state===SpvFromBTCSwapState.SIGNED ||
|
|
847
|
+
pastSwap._state===SpvFromBTCSwapState.POSTED ||
|
|
848
|
+
pastSwap._state===SpvFromBTCSwapState.BROADCASTED ||
|
|
849
|
+
pastSwap._state===SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED ||
|
|
850
|
+
pastSwap._state===SpvFromBTCSwapState.DECLINED ||
|
|
851
|
+
pastSwap._state===SpvFromBTCSwapState.BTC_TX_CONFIRMED
|
|
708
852
|
) {
|
|
709
853
|
//Check BTC transaction
|
|
710
854
|
if(await pastSwap._syncStateFromBitcoin(false)) changed ||= true;
|
|
711
855
|
}
|
|
712
856
|
|
|
713
857
|
if(
|
|
714
|
-
pastSwap.
|
|
715
|
-
pastSwap.
|
|
716
|
-
pastSwap.
|
|
858
|
+
pastSwap._state===SpvFromBTCSwapState.CREATED ||
|
|
859
|
+
pastSwap._state===SpvFromBTCSwapState.SIGNED ||
|
|
860
|
+
pastSwap._state===SpvFromBTCSwapState.POSTED
|
|
717
861
|
) {
|
|
718
|
-
if(pastSwap.
|
|
719
|
-
if(pastSwap.
|
|
720
|
-
pastSwap.
|
|
862
|
+
if(await pastSwap._verifyQuoteDefinitelyExpired()) {
|
|
863
|
+
if(pastSwap._state===SpvFromBTCSwapState.CREATED) {
|
|
864
|
+
pastSwap._state = SpvFromBTCSwapState.QUOTE_EXPIRED;
|
|
721
865
|
} else {
|
|
722
|
-
pastSwap.
|
|
866
|
+
pastSwap._state = SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED;
|
|
723
867
|
}
|
|
724
868
|
changed ||= true;
|
|
725
869
|
}
|
|
@@ -731,56 +875,53 @@ export class SpvFromBTCWrapper<
|
|
|
731
875
|
}
|
|
732
876
|
if(changed) changedSwaps.add(pastSwap);
|
|
733
877
|
|
|
734
|
-
if(pastSwap.
|
|
735
|
-
if(pastSwap.
|
|
878
|
+
if(pastSwap._state===SpvFromBTCSwapState.BROADCASTED || pastSwap._state===SpvFromBTCSwapState.BTC_TX_CONFIRMED) {
|
|
879
|
+
if(pastSwap._data!=null) broadcastedOrConfirmedSwaps.push(pastSwap as (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]}));
|
|
736
880
|
}
|
|
737
881
|
}
|
|
738
882
|
|
|
739
|
-
const checkWithdrawalStateSwaps: (SpvFromBTCSwap<T> & {
|
|
740
|
-
const _fronts = await this.
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
withdrawal: val.data!
|
|
744
|
-
})));
|
|
745
|
-
const _vaultUtxos = await this.contract.getVaultLatestUtxos(broadcastedOrConfirmedSwaps.map(val => ({
|
|
746
|
-
owner: val.vaultOwner,
|
|
747
|
-
vaultId: val.vaultId
|
|
883
|
+
const checkWithdrawalStateSwaps: (SpvFromBTCSwap<T> & {_data: T["SpvVaultWithdrawalData"]})[] = [];
|
|
884
|
+
const _fronts = await this._contract.getFronterAddresses(broadcastedOrConfirmedSwaps.map(val => ({
|
|
885
|
+
...val.getSpvVaultData(),
|
|
886
|
+
withdrawal: val._data!
|
|
748
887
|
})));
|
|
888
|
+
const _vaultUtxos = await this._contract.getVaultLatestUtxos(broadcastedOrConfirmedSwaps.map(val => val.getSpvVaultData()));
|
|
749
889
|
for(const pastSwap of broadcastedOrConfirmedSwaps) {
|
|
750
|
-
const fronterAddress = _fronts[pastSwap.
|
|
751
|
-
const
|
|
752
|
-
|
|
753
|
-
if(
|
|
890
|
+
const fronterAddress = _fronts[pastSwap._data.getTxId()];
|
|
891
|
+
const vault = pastSwap.getSpvVaultData();
|
|
892
|
+
const latestVaultUtxo = _vaultUtxos[vault.owner]?.[vault.vaultId.toString(10)];
|
|
893
|
+
if(fronterAddress===undefined) this.logger.warn(`_checkPastSwaps(): No fronter address returned for ${pastSwap._data.getTxId()}`);
|
|
894
|
+
if(latestVaultUtxo===undefined) this.logger.warn(`_checkPastSwaps(): No last vault utxo returned for ${pastSwap._data.getTxId()}`);
|
|
754
895
|
if(await pastSwap._shouldCheckWithdrawalState(fronterAddress, latestVaultUtxo)) checkWithdrawalStateSwaps.push(pastSwap);
|
|
755
896
|
}
|
|
756
897
|
|
|
757
|
-
const withdrawalStates = await this.
|
|
898
|
+
const withdrawalStates = await this._contract.getWithdrawalStates(
|
|
758
899
|
checkWithdrawalStateSwaps.map(val => ({
|
|
759
|
-
withdrawal: val.
|
|
760
|
-
scStartBlockheight: val.
|
|
900
|
+
withdrawal: val._data,
|
|
901
|
+
scStartBlockheight: val._genesisSmartChainBlockHeight
|
|
761
902
|
}))
|
|
762
903
|
);
|
|
763
904
|
for(const pastSwap of checkWithdrawalStateSwaps) {
|
|
764
|
-
const status = withdrawalStates[pastSwap.
|
|
905
|
+
const status = withdrawalStates[pastSwap._data.getTxId()];
|
|
765
906
|
if(status==null) {
|
|
766
|
-
this.logger.warn(`_checkPastSwaps(): No withdrawal state returned for ${pastSwap.
|
|
907
|
+
this.logger.warn(`_checkPastSwaps(): No withdrawal state returned for ${pastSwap._data.getTxId()}`);
|
|
767
908
|
continue;
|
|
768
909
|
}
|
|
769
|
-
this.logger.debug("syncStateFromChain(): status of "+pastSwap.
|
|
910
|
+
this.logger.debug("syncStateFromChain(): status of "+pastSwap._data.btcTx.txid, status?.type);
|
|
770
911
|
let changed = false;
|
|
771
912
|
switch(status.type) {
|
|
772
913
|
case SpvWithdrawalStateType.FRONTED:
|
|
773
|
-
pastSwap.
|
|
774
|
-
pastSwap.
|
|
914
|
+
pastSwap._frontTxId = status.txId;
|
|
915
|
+
pastSwap._state = SpvFromBTCSwapState.FRONTED;
|
|
775
916
|
changed ||= true;
|
|
776
917
|
break;
|
|
777
918
|
case SpvWithdrawalStateType.CLAIMED:
|
|
778
|
-
pastSwap.
|
|
779
|
-
pastSwap.
|
|
919
|
+
pastSwap._claimTxId = status.txId;
|
|
920
|
+
pastSwap._state = SpvFromBTCSwapState.CLAIMED;
|
|
780
921
|
changed ||= true;
|
|
781
922
|
break;
|
|
782
923
|
case SpvWithdrawalStateType.CLOSED:
|
|
783
|
-
pastSwap.
|
|
924
|
+
pastSwap._state = SpvFromBTCSwapState.CLOSED;
|
|
784
925
|
changed ||= true;
|
|
785
926
|
break;
|
|
786
927
|
}
|