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