@atomiqlabs/sdk 8.6.5 → 8.6.6
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/SmartChainAssets.d.ts +181 -181
- package/dist/SmartChainAssets.js +181 -181
- package/dist/bitcoin/coinselect2/accumulative.d.ts +6 -6
- package/dist/bitcoin/coinselect2/accumulative.js +51 -52
- package/dist/bitcoin/coinselect2/blackjack.d.ts +6 -6
- package/dist/bitcoin/coinselect2/blackjack.js +37 -38
- package/dist/bitcoin/coinselect2/index.d.ts +17 -19
- package/dist/bitcoin/coinselect2/index.js +69 -69
- package/dist/bitcoin/coinselect2/utils.d.ts +75 -77
- package/dist/bitcoin/coinselect2/utils.js +123 -123
- package/dist/bitcoin/wallet/BitcoinWallet.d.ts +128 -130
- package/dist/bitcoin/wallet/BitcoinWallet.js +322 -322
- package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +78 -78
- package/dist/bitcoin/wallet/IBitcoinWallet.js +20 -21
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +99 -101
- package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +176 -176
- package/dist/enums/FeeType.d.ts +15 -15
- package/dist/enums/FeeType.js +19 -19
- package/dist/enums/SwapAmountType.d.ts +15 -15
- package/dist/enums/SwapAmountType.js +19 -19
- package/dist/enums/SwapDirection.d.ts +15 -15
- package/dist/enums/SwapDirection.js +19 -19
- package/dist/enums/SwapSide.d.ts +15 -15
- package/dist/enums/SwapSide.js +19 -19
- package/dist/enums/SwapType.d.ts +75 -75
- package/dist/enums/SwapType.js +79 -79
- package/dist/errors/IntermediaryError.d.ts +13 -13
- package/dist/errors/IntermediaryError.js +27 -27
- package/dist/errors/RequestError.d.ts +32 -32
- package/dist/errors/RequestError.js +54 -54
- package/dist/errors/UserError.d.ts +8 -8
- package/dist/errors/UserError.js +16 -16
- package/dist/events/UnifiedSwapEventListener.d.ts +23 -23
- package/dist/events/UnifiedSwapEventListener.js +130 -130
- package/dist/http/HttpUtils.d.ts +27 -27
- package/dist/http/HttpUtils.js +90 -91
- package/dist/http/paramcoders/IParamReader.d.ts +8 -8
- package/dist/http/paramcoders/IParamReader.js +2 -2
- package/dist/http/paramcoders/ParamDecoder.d.ts +42 -44
- package/dist/http/paramcoders/ParamDecoder.js +137 -137
- package/dist/http/paramcoders/ParamEncoder.d.ts +18 -20
- package/dist/http/paramcoders/ParamEncoder.js +36 -36
- package/dist/http/paramcoders/SchemaVerifier.d.ts +26 -26
- package/dist/http/paramcoders/SchemaVerifier.js +145 -145
- package/dist/http/paramcoders/client/ResponseParamDecoder.d.ts +11 -11
- package/dist/http/paramcoders/client/ResponseParamDecoder.js +57 -57
- package/dist/http/paramcoders/client/StreamParamEncoder.d.ts +11 -13
- package/dist/http/paramcoders/client/StreamParamEncoder.js +26 -26
- package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +16 -16
- package/dist/http/paramcoders/client/StreamingFetchPromise.js +173 -174
- package/dist/index.d.ts +85 -85
- package/dist/index.js +158 -158
- package/dist/intermediaries/Intermediary.d.ts +157 -157
- package/dist/intermediaries/Intermediary.js +142 -142
- package/dist/intermediaries/IntermediaryDiscovery.d.ts +198 -199
- package/dist/intermediaries/IntermediaryDiscovery.js +406 -406
- package/dist/intermediaries/apis/IntermediaryAPI.d.ts +437 -438
- package/dist/intermediaries/apis/IntermediaryAPI.js +603 -602
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.d.ts +155 -155
- package/dist/intermediaries/apis/TrustedIntermediaryAPI.js +137 -137
- package/dist/lnurl/LNURL.d.ts +102 -102
- package/dist/lnurl/LNURL.js +321 -321
- package/dist/prices/RedundantSwapPrice.d.ts +110 -110
- package/dist/prices/RedundantSwapPrice.js +222 -222
- package/dist/prices/SingleSwapPrice.d.ts +34 -34
- package/dist/prices/SingleSwapPrice.js +44 -44
- package/dist/prices/SwapPriceWithChain.d.ts +107 -107
- package/dist/prices/SwapPriceWithChain.js +128 -128
- package/dist/prices/abstract/ICachedSwapPrice.d.ts +28 -28
- package/dist/prices/abstract/ICachedSwapPrice.js +62 -62
- package/dist/prices/abstract/IPriceProvider.d.ts +81 -81
- package/dist/prices/abstract/IPriceProvider.js +74 -74
- package/dist/prices/abstract/ISwapPrice.d.ts +168 -168
- package/dist/prices/abstract/ISwapPrice.js +279 -279
- package/dist/prices/providers/BinancePriceProvider.d.ts +23 -23
- package/dist/prices/providers/BinancePriceProvider.js +30 -30
- package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +23 -23
- package/dist/prices/providers/CoinGeckoPriceProvider.js +29 -29
- package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +25 -25
- package/dist/prices/providers/CoinPaprikaPriceProvider.js +29 -29
- package/dist/prices/providers/CustomPriceProvider.d.ts +24 -24
- package/dist/prices/providers/CustomPriceProvider.js +35 -35
- package/dist/prices/providers/KrakenPriceProvider.d.ts +38 -38
- package/dist/prices/providers/KrakenPriceProvider.js +45 -45
- package/dist/prices/providers/OKXPriceProvider.d.ts +34 -34
- package/dist/prices/providers/OKXPriceProvider.js +29 -29
- package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +17 -17
- package/dist/prices/providers/abstract/ExchangePriceProvider.js +21 -21
- package/dist/prices/providers/abstract/HttpPriceProvider.d.ts +7 -7
- package/dist/prices/providers/abstract/HttpPriceProvider.js +12 -12
- package/dist/storage/IUnifiedStorage.d.ts +85 -85
- package/dist/storage/IUnifiedStorage.js +2 -2
- package/dist/storage/UnifiedSwapStorage.d.ts +114 -114
- package/dist/storage/UnifiedSwapStorage.js +116 -116
- package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +63 -63
- package/dist/storage-browser/IndexedDBUnifiedStorage.js +298 -298
- package/dist/storage-browser/LocalStorageManager.d.ts +49 -49
- package/dist/storage-browser/LocalStorageManager.js +93 -93
- package/dist/swapper/Swapper.d.ts +686 -687
- package/dist/swapper/Swapper.js +1603 -1603
- package/dist/swapper/SwapperFactory.d.ts +135 -135
- package/dist/swapper/SwapperFactory.js +162 -162
- package/dist/swapper/SwapperUtils.d.ts +200 -200
- package/dist/swapper/SwapperUtils.js +467 -467
- package/dist/swapper/SwapperWithChain.d.ts +404 -404
- package/dist/swapper/SwapperWithChain.js +469 -469
- package/dist/swapper/SwapperWithSigner.d.ts +322 -322
- package/dist/swapper/SwapperWithSigner.js +318 -318
- package/dist/swaps/IAddressSwap.d.ts +22 -22
- package/dist/swaps/IAddressSwap.js +13 -14
- package/dist/swaps/IBTCWalletSwap.d.ts +73 -73
- package/dist/swaps/IBTCWalletSwap.js +17 -18
- package/dist/swaps/IClaimableSwap.d.ts +49 -49
- package/dist/swaps/IClaimableSwap.js +14 -15
- package/dist/swaps/IClaimableSwapWrapper.d.ts +15 -15
- package/dist/swaps/IClaimableSwapWrapper.js +2 -2
- package/dist/swaps/IRefundableSwap.d.ts +43 -43
- package/dist/swaps/IRefundableSwap.js +13 -14
- package/dist/swaps/ISwap.d.ts +386 -387
- package/dist/swaps/ISwap.js +346 -346
- package/dist/swaps/ISwapWithGasDrop.d.ts +21 -21
- package/dist/swaps/ISwapWithGasDrop.js +11 -12
- package/dist/swaps/ISwapWrapper.d.ts +283 -285
- package/dist/swaps/ISwapWrapper.js +353 -353
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +98 -98
- package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +126 -126
- package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +133 -135
- package/dist/swaps/escrow_swaps/IEscrowSwap.js +169 -169
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +114 -115
- package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +134 -134
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +98 -101
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +130 -130
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +162 -162
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +190 -190
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +58 -58
- package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +78 -78
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +529 -531
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +1285 -1285
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +181 -184
- package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +418 -418
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +581 -583
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +1371 -1371
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +225 -228
- package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +506 -506
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +458 -458
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +1126 -1126
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +190 -191
- package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +378 -378
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +403 -403
- package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +924 -924
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +62 -62
- package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +112 -112
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +125 -127
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +256 -256
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +241 -242
- package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +520 -520
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +73 -73
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +155 -155
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +127 -128
- package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +278 -278
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +630 -630
- package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +1443 -1443
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +213 -207
- package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +756 -755
- package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +261 -261
- package/dist/swaps/trusted/ln/LnForGasSwap.js +511 -511
- package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +40 -40
- package/dist/swaps/trusted/ln/LnForGasWrapper.js +82 -82
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +342 -342
- package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +715 -715
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +68 -69
- package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +92 -92
- package/dist/types/AmountData.d.ts +10 -10
- package/dist/types/AmountData.js +2 -2
- package/dist/types/CustomPriceFunction.d.ts +11 -11
- package/dist/types/CustomPriceFunction.js +2 -2
- package/dist/types/PriceInfoType.d.ts +28 -28
- package/dist/types/PriceInfoType.js +56 -57
- package/dist/types/SwapExecutionAction.d.ts +88 -88
- package/dist/types/SwapExecutionAction.js +2 -2
- package/dist/types/SwapStateInfo.d.ts +5 -5
- package/dist/types/SwapStateInfo.js +2 -2
- package/dist/types/SwapWithSigner.d.ts +17 -17
- package/dist/types/SwapWithSigner.js +42 -43
- package/dist/types/Token.d.ts +99 -99
- package/dist/types/Token.js +76 -76
- package/dist/types/TokenAmount.d.ts +69 -69
- package/dist/types/TokenAmount.js +59 -60
- package/dist/types/fees/Fee.d.ts +50 -50
- package/dist/types/fees/Fee.js +2 -2
- package/dist/types/fees/FeeBreakdown.d.ts +11 -11
- package/dist/types/fees/FeeBreakdown.js +2 -2
- package/dist/types/fees/PercentagePPM.d.ts +17 -17
- package/dist/types/fees/PercentagePPM.js +17 -18
- package/dist/types/lnurl/LNURLPay.d.ts +61 -61
- package/dist/types/lnurl/LNURLPay.js +30 -31
- package/dist/types/lnurl/LNURLWithdraw.d.ts +48 -48
- package/dist/types/lnurl/LNURLWithdraw.js +26 -27
- package/dist/types/wallets/LightningInvoiceCreateService.d.ts +24 -24
- package/dist/types/wallets/LightningInvoiceCreateService.js +14 -15
- package/dist/types/wallets/MinimalBitcoinWalletInterface.d.ts +23 -23
- package/dist/types/wallets/MinimalBitcoinWalletInterface.js +2 -2
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.d.ts +9 -9
- package/dist/types/wallets/MinimalLightningNetworkWalletInterface.js +2 -2
- package/dist/utils/AutomaticClockDriftCorrection.d.ts +1 -1
- package/dist/utils/AutomaticClockDriftCorrection.js +69 -70
- package/dist/utils/BitcoinUtils.d.ts +12 -14
- package/dist/utils/BitcoinUtils.js +101 -102
- package/dist/utils/BitcoinWalletUtils.d.ts +7 -7
- package/dist/utils/BitcoinWalletUtils.js +13 -14
- package/dist/utils/Logger.d.ts +7 -7
- package/dist/utils/Logger.js +11 -12
- package/dist/utils/RetryUtils.d.ts +22 -22
- package/dist/utils/RetryUtils.js +66 -67
- package/dist/utils/SwapUtils.d.ts +88 -88
- package/dist/utils/SwapUtils.js +72 -72
- package/dist/utils/TimeoutUtils.d.ts +17 -17
- package/dist/utils/TimeoutUtils.js +54 -55
- package/dist/utils/TokenUtils.d.ts +19 -19
- package/dist/utils/TokenUtils.js +36 -37
- package/dist/utils/TypeUtils.d.ts +7 -7
- package/dist/utils/TypeUtils.js +2 -2
- package/dist/utils/Utils.d.ts +56 -58
- package/dist/utils/Utils.js +193 -194
- package/package.json +1 -1
- package/src/intermediaries/apis/IntermediaryAPI.ts +4 -2
- package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +8 -0
|
@@ -1,406 +1,406 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.IntermediaryDiscovery = exports.SwapHandlerType = void 0;
|
|
4
|
-
const Intermediary_1 = require("./Intermediary");
|
|
5
|
-
const SwapType_1 = require("../enums/SwapType");
|
|
6
|
-
const events_1 = require("events");
|
|
7
|
-
const buffer_1 = require("buffer");
|
|
8
|
-
const Utils_1 = require("../utils/Utils");
|
|
9
|
-
const IntermediaryAPI_1 = require("./apis/IntermediaryAPI");
|
|
10
|
-
const Logger_1 = require("../utils/Logger");
|
|
11
|
-
const HttpUtils_1 = require("../http/HttpUtils");
|
|
12
|
-
const RetryUtils_1 = require("../utils/RetryUtils");
|
|
13
|
-
/**
|
|
14
|
-
* Swap handler type mapping for intermediary communication
|
|
15
|
-
*
|
|
16
|
-
* @category LPs
|
|
17
|
-
*/
|
|
18
|
-
var SwapHandlerType;
|
|
19
|
-
(function (SwapHandlerType) {
|
|
20
|
-
SwapHandlerType["TO_BTC"] = "TO_BTC";
|
|
21
|
-
SwapHandlerType["FROM_BTC"] = "FROM_BTC";
|
|
22
|
-
SwapHandlerType["TO_BTCLN"] = "TO_BTCLN";
|
|
23
|
-
SwapHandlerType["FROM_BTCLN"] = "FROM_BTCLN";
|
|
24
|
-
SwapHandlerType["FROM_BTC_TRUSTED"] = "FROM_BTC_TRUSTED";
|
|
25
|
-
SwapHandlerType["FROM_BTCLN_TRUSTED"] = "FROM_BTCLN_TRUSTED";
|
|
26
|
-
SwapHandlerType["FROM_BTC_SPV"] = "FROM_BTC_SPV";
|
|
27
|
-
SwapHandlerType["FROM_BTCLN_AUTO"] = "FROM_BTCLN_AUTO";
|
|
28
|
-
})(SwapHandlerType
|
|
29
|
-
/**
|
|
30
|
-
* Converts SwapHandlerType (represented as string & used in REST API communication with intermediaries) to regular
|
|
31
|
-
* {@link SwapType}
|
|
32
|
-
*
|
|
33
|
-
* @param swapHandlerType
|
|
34
|
-
*/
|
|
35
|
-
function swapHandlerTypeToSwapType(swapHandlerType) {
|
|
36
|
-
switch (swapHandlerType) {
|
|
37
|
-
case SwapHandlerType.FROM_BTC:
|
|
38
|
-
return SwapType_1.SwapType.FROM_BTC;
|
|
39
|
-
case SwapHandlerType.TO_BTC:
|
|
40
|
-
return SwapType_1.SwapType.TO_BTC;
|
|
41
|
-
case SwapHandlerType.FROM_BTCLN:
|
|
42
|
-
return SwapType_1.SwapType.FROM_BTCLN;
|
|
43
|
-
case SwapHandlerType.TO_BTCLN:
|
|
44
|
-
return SwapType_1.SwapType.TO_BTCLN;
|
|
45
|
-
case SwapHandlerType.FROM_BTC_TRUSTED:
|
|
46
|
-
return SwapType_1.SwapType.TRUSTED_FROM_BTC;
|
|
47
|
-
case SwapHandlerType.FROM_BTCLN_TRUSTED:
|
|
48
|
-
return SwapType_1.SwapType.TRUSTED_FROM_BTCLN;
|
|
49
|
-
case SwapHandlerType.FROM_BTC_SPV:
|
|
50
|
-
return SwapType_1.SwapType.SPV_VAULT_FROM_BTC;
|
|
51
|
-
case SwapHandlerType.FROM_BTCLN_AUTO:
|
|
52
|
-
return SwapType_1.SwapType.FROM_BTCLN_AUTO;
|
|
53
|
-
default:
|
|
54
|
-
return SwapType_1.SwapType.TRUSTED_FROM_BTCLN;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* A default intermediary comparator, only takes the announced fee into consideration
|
|
59
|
-
*
|
|
60
|
-
* @param swapType
|
|
61
|
-
* @param tokenAddress
|
|
62
|
-
* @param swapAmount
|
|
63
|
-
*/
|
|
64
|
-
function getIntermediaryComparator(swapType, tokenAddress, swapAmount) {
|
|
65
|
-
if (swapType === SwapType_1.SwapType.TO_BTC) {
|
|
66
|
-
//TODO: Also take reputation into account
|
|
67
|
-
}
|
|
68
|
-
return (a, b) => {
|
|
69
|
-
const aService = a.services[swapType];
|
|
70
|
-
const bService = b.services[swapType];
|
|
71
|
-
if (aService == null && bService == null)
|
|
72
|
-
return 0;
|
|
73
|
-
if (aService == null)
|
|
74
|
-
return 1;
|
|
75
|
-
if (bService == null)
|
|
76
|
-
return -1;
|
|
77
|
-
if (swapAmount == null) {
|
|
78
|
-
return aService.swapFeePPM - bService.swapFeePPM;
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
const feeA = BigInt(aService.swapBaseFee) + (swapAmount * BigInt(aService.swapFeePPM) / 1000000n);
|
|
82
|
-
const feeB = BigInt(bService.swapBaseFee) + (swapAmount * BigInt(bService.swapFeePPM) / 1000000n);
|
|
83
|
-
return feeA - feeB > 0n ? 1 : feeA === feeB ? 0 : -1;
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
const logger = (0, Logger_1.getLogger)("IntermediaryDiscovery: ");
|
|
88
|
-
const REGISTRY_URL = "https://api.github.com/repos/adambor/SolLightning-registry/contents/registry.json?ref=main";
|
|
89
|
-
//To allow for legacy responses from not-yet updated LPs
|
|
90
|
-
const DEFAULT_CHAIN = "SOLANA";
|
|
91
|
-
/**
|
|
92
|
-
* Discovery service for available intermediaries (liquidity providers)
|
|
93
|
-
*
|
|
94
|
-
* @category LPs
|
|
95
|
-
*/
|
|
96
|
-
class IntermediaryDiscovery extends events_1.EventEmitter {
|
|
97
|
-
constructor(swapContracts, registryUrl = REGISTRY_URL, nodeUrls, httpRequestTimeout, maxWaitForOthersTimeout) {
|
|
98
|
-
super();
|
|
99
|
-
/**
|
|
100
|
-
* A current list of active intermediaries
|
|
101
|
-
*/
|
|
102
|
-
this.intermediaries = [];
|
|
103
|
-
this.swapContracts = swapContracts;
|
|
104
|
-
this.registryUrl = registryUrl;
|
|
105
|
-
this.overrideNodeUrls = nodeUrls;
|
|
106
|
-
this.httpRequestTimeout = httpRequestTimeout;
|
|
107
|
-
this.maxWaitForOthersTimeout = maxWaitForOthersTimeout;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Fetches the URLs of swap intermediaries from registry or from a pre-defined array of node urls
|
|
111
|
-
*
|
|
112
|
-
* @param abortSignal
|
|
113
|
-
*/
|
|
114
|
-
async getIntermediaryUrls(abortSignal) {
|
|
115
|
-
if (this.overrideNodeUrls != null && this.overrideNodeUrls.length > 0) {
|
|
116
|
-
return this.overrideNodeUrls;
|
|
117
|
-
}
|
|
118
|
-
const response = await (0, RetryUtils_1.tryWithRetries)(() => (0, HttpUtils_1.httpGet)(this.registryUrl, this.httpRequestTimeout, abortSignal), { maxRetries: 3, delay: 100, exponential: true });
|
|
119
|
-
const content = response.content.replace(new RegExp("\\n", "g"), "");
|
|
120
|
-
return JSON.parse(buffer_1.Buffer.from(content, "base64").toString());
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Returns data as reported by a specific node (as identified by its URL). This function is specifically made
|
|
124
|
-
* in a way, that in case the abortSignal fires AFTER the LP response was received (and during signature checking),
|
|
125
|
-
* it proceeds with the addresses it was able to verify already. Hence after calling abort, this function is guaranteed
|
|
126
|
-
* to either reject or resolve instantly.
|
|
127
|
-
*
|
|
128
|
-
* @param url
|
|
129
|
-
* @param abortSignal
|
|
130
|
-
*/
|
|
131
|
-
async getNodeInfo(url, abortSignal) {
|
|
132
|
-
const response = await (0, RetryUtils_1.tryWithRetries)(() => IntermediaryAPI_1.IntermediaryAPI.getIntermediaryInfo(url, this.httpRequestTimeout, abortSignal), { maxRetries: 3, delay: 100, exponential: true }, undefined, abortSignal, "debug");
|
|
133
|
-
abortSignal?.throwIfAborted();
|
|
134
|
-
const promises = [];
|
|
135
|
-
const addresses = {};
|
|
136
|
-
for (let chain in response.chains) {
|
|
137
|
-
if (this.swapContracts[chain] != null) {
|
|
138
|
-
promises.push((async () => {
|
|
139
|
-
const { signature, address } = response.chains[chain];
|
|
140
|
-
try {
|
|
141
|
-
await this.swapContracts[chain].isValidDataSignature(buffer_1.Buffer.from(response.envelope), signature, address);
|
|
142
|
-
addresses[chain] = address;
|
|
143
|
-
}
|
|
144
|
-
catch (e) {
|
|
145
|
-
logger.warn("getNodeInfo(): Failed to verify " + chain + " signature for intermediary: " + url);
|
|
146
|
-
}
|
|
147
|
-
})());
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (abortSignal != null) {
|
|
151
|
-
await Promise.race([
|
|
152
|
-
Promise.all(promises),
|
|
153
|
-
new Promise(resolve => abortSignal.addEventListener("abort", resolve))
|
|
154
|
-
]);
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
await Promise.all(promises);
|
|
158
|
-
}
|
|
159
|
-
//Handle legacy responses
|
|
160
|
-
const info = JSON.parse(response.envelope);
|
|
161
|
-
for (let swapType in info.services) {
|
|
162
|
-
const serviceData = info.services[swapType];
|
|
163
|
-
if (serviceData.chainTokens == null)
|
|
164
|
-
serviceData.chainTokens = {
|
|
165
|
-
[DEFAULT_CHAIN]: serviceData.tokens
|
|
166
|
-
};
|
|
167
|
-
for (let chain in serviceData.chainTokens) {
|
|
168
|
-
if (addresses[chain] == null)
|
|
169
|
-
delete serviceData.chainTokens[chain];
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return {
|
|
173
|
-
addresses,
|
|
174
|
-
info
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Inherits abort signal logic from `getNodeInfo()`, check those function docs to better understand
|
|
179
|
-
*
|
|
180
|
-
* @param url
|
|
181
|
-
* @param abortSignal
|
|
182
|
-
* @private
|
|
183
|
-
*/
|
|
184
|
-
async loadIntermediary(url, abortSignal) {
|
|
185
|
-
try {
|
|
186
|
-
const nodeInfo = await this.getNodeInfo(url, abortSignal);
|
|
187
|
-
const services = {};
|
|
188
|
-
for (let key in nodeInfo.info.services) {
|
|
189
|
-
services[swapHandlerTypeToSwapType(key)] = nodeInfo.info.services[key];
|
|
190
|
-
}
|
|
191
|
-
return new Intermediary_1.Intermediary(url, nodeInfo.addresses, services);
|
|
192
|
-
}
|
|
193
|
-
catch (e) {
|
|
194
|
-
logger.warn("fetchIntermediaries(): Intermediary " + url + ` is unreachable due to ${e.name ?? e.message} error, skipping...`);
|
|
195
|
-
logger.debug("fetchIntermediaries(): Error contacting intermediary " + url + ": ", e);
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Returns the intermediary at the provided URL, either from the already fetched list of LPs
|
|
201
|
-
* or fetches the data on-demand, by sending the handshake HTTP request (/info) to the LP.
|
|
202
|
-
*
|
|
203
|
-
* Doesn't save the fetched intermediary to the list of intermediaries if it isn't already
|
|
204
|
-
* part of the known intermediaries
|
|
205
|
-
*
|
|
206
|
-
* @param url Base URL of the intermediary, which accepts HTTP requests
|
|
207
|
-
* @param abortSignal
|
|
208
|
-
*/
|
|
209
|
-
getIntermediary(url, abortSignal) {
|
|
210
|
-
const foundLp = this.intermediaries.find(lp => lp.url === url);
|
|
211
|
-
if (foundLp != null)
|
|
212
|
-
return Promise.resolve(foundLp);
|
|
213
|
-
return this.loadIntermediary(url, abortSignal);
|
|
214
|
-
}
|
|
215
|
-
/**
|
|
216
|
-
* Reloads the saves a list of intermediaries
|
|
217
|
-
*
|
|
218
|
-
* @param abortSignal
|
|
219
|
-
*/
|
|
220
|
-
async reloadIntermediaries(abortSignal) {
|
|
221
|
-
//Get LP urls
|
|
222
|
-
const urls = await this.getIntermediaryUrls(abortSignal);
|
|
223
|
-
logger.debug("reloadIntermediaries(): Pinging intermediaries: ", urls.join());
|
|
224
|
-
const abortController = (0, Utils_1.extendAbortController)(abortSignal);
|
|
225
|
-
let timer;
|
|
226
|
-
const intermediaries = await Promise.all(urls.map(url => this.loadIntermediary(url, abortController.signal).then(lp => {
|
|
227
|
-
if (lp != null && timer == null)
|
|
228
|
-
timer = setTimeout(() => {
|
|
229
|
-
//Trigger abort through the abort controller, such that all underlying promises resolve instantly
|
|
230
|
-
abortController.abort();
|
|
231
|
-
}, this.maxWaitForOthersTimeout ?? 5 * 1000);
|
|
232
|
-
return lp;
|
|
233
|
-
})));
|
|
234
|
-
if (timer != null)
|
|
235
|
-
clearTimeout(timer);
|
|
236
|
-
const activeNodes = intermediaries.filter(intermediary => intermediary != null);
|
|
237
|
-
if (activeNodes.length === 0)
|
|
238
|
-
logger.error("reloadIntermediaries(): No online intermediary found! Swaps might not be possible!");
|
|
239
|
-
this.intermediaries = activeNodes;
|
|
240
|
-
this.emit("added", activeNodes);
|
|
241
|
-
logger.info("reloadIntermediaries(): Using active intermediaries: ", activeNodes.map(lp => lp.url).join());
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Initializes the discovery by fetching/reloading intermediaries
|
|
245
|
-
*
|
|
246
|
-
* @param abortSignal
|
|
247
|
-
*/
|
|
248
|
-
init(abortSignal) {
|
|
249
|
-
logger.info("init(): Initializing with registryUrl: " + this.registryUrl + " intermediary array: " + (this.overrideNodeUrls || []).join());
|
|
250
|
-
return this.reloadIntermediaries(abortSignal);
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Returns known swap bounds (in satoshis - BTC) by aggregating values from all known intermediaries
|
|
254
|
-
*/
|
|
255
|
-
getMultichainSwapBounds() {
|
|
256
|
-
const bounds = {};
|
|
257
|
-
this.intermediaries.forEach(intermediary => {
|
|
258
|
-
for (let _swapType in intermediary.services) {
|
|
259
|
-
const swapType = parseInt(_swapType);
|
|
260
|
-
const swapService = intermediary.services[swapType];
|
|
261
|
-
const multichainBounds = (bounds[swapType] ??= {});
|
|
262
|
-
for (let chainId in swapService.chainTokens) {
|
|
263
|
-
multichainBounds[chainId] ??= {};
|
|
264
|
-
const tokenBounds = multichainBounds[chainId];
|
|
265
|
-
for (let token of swapService.chainTokens[chainId]) {
|
|
266
|
-
const tokenMinMax = tokenBounds[token];
|
|
267
|
-
if (tokenMinMax == null) {
|
|
268
|
-
tokenBounds[token] = {
|
|
269
|
-
min: BigInt(swapService.min),
|
|
270
|
-
max: BigInt(swapService.max)
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
tokenMinMax.min = (0, Utils_1.bigIntMin)(tokenMinMax.min, BigInt(swapService.min));
|
|
275
|
-
tokenMinMax.max = (0, Utils_1.bigIntMax)(tokenMinMax.max, BigInt(swapService.max));
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
return bounds;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Returns aggregate swap bounds (in satoshis - BTC) as indicated by the intermediaries
|
|
285
|
-
*/
|
|
286
|
-
getSwapBounds(chainIdentifier) {
|
|
287
|
-
const bounds = {};
|
|
288
|
-
this.intermediaries.forEach(intermediary => {
|
|
289
|
-
for (let _swapType in intermediary.services) {
|
|
290
|
-
const swapType = parseInt(_swapType);
|
|
291
|
-
const swapService = intermediary.services[swapType];
|
|
292
|
-
const tokenBounds = (bounds[swapType] ??= {});
|
|
293
|
-
if (swapService.chainTokens != null && swapService.chainTokens[chainIdentifier] != null) {
|
|
294
|
-
for (let token of swapService.chainTokens[chainIdentifier]) {
|
|
295
|
-
const tokenMinMax = tokenBounds[token];
|
|
296
|
-
if (tokenMinMax == null) {
|
|
297
|
-
tokenBounds[token] = {
|
|
298
|
-
min: BigInt(swapService.min),
|
|
299
|
-
max: BigInt(swapService.max)
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
tokenMinMax.min = (0, Utils_1.bigIntMin)(tokenMinMax.min, BigInt(swapService.min));
|
|
304
|
-
tokenMinMax.max = (0, Utils_1.bigIntMax)(tokenMinMax.max, BigInt(swapService.max));
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
return bounds;
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Returns the aggregate swap minimum (in satoshis - BTC) for a specific swap type & token
|
|
314
|
-
* as indicated by the intermediaries
|
|
315
|
-
*
|
|
316
|
-
* @param chainIdentifier Chain identifier of the smart chain
|
|
317
|
-
* @param swapType Swap protocol type
|
|
318
|
-
* @param tokenAddress Token address
|
|
319
|
-
*/
|
|
320
|
-
getSwapMinimum(chainIdentifier, swapType, tokenAddress) {
|
|
321
|
-
const tokenStr = tokenAddress.toString();
|
|
322
|
-
return this.intermediaries.reduce((prevMin, intermediary) => {
|
|
323
|
-
const swapService = intermediary.services[swapType];
|
|
324
|
-
if (swapService == null)
|
|
325
|
-
return prevMin;
|
|
326
|
-
const chainTokens = swapService.chainTokens?.[chainIdentifier];
|
|
327
|
-
if (chainTokens == null)
|
|
328
|
-
return prevMin;
|
|
329
|
-
if (!chainTokens.includes(tokenStr))
|
|
330
|
-
return prevMin;
|
|
331
|
-
return prevMin == null ? swapService.min : Math.min(prevMin, swapService.min);
|
|
332
|
-
}, null);
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Returns the aggregate swap maximum (in satoshis - BTC) for a specific swap type & token
|
|
336
|
-
* as indicated by the intermediaries
|
|
337
|
-
*
|
|
338
|
-
* @param chainIdentifier Chain identifier of the smart chain
|
|
339
|
-
* @param swapType Swap protocol type
|
|
340
|
-
* @param tokenAddress Token address
|
|
341
|
-
*/
|
|
342
|
-
getSwapMaximum(chainIdentifier, swapType, tokenAddress) {
|
|
343
|
-
const tokenStr = tokenAddress.toString();
|
|
344
|
-
return this.intermediaries.reduce((prevMax, intermediary) => {
|
|
345
|
-
const swapService = intermediary.services[swapType];
|
|
346
|
-
if (swapService == null)
|
|
347
|
-
return prevMax;
|
|
348
|
-
const chainTokens = swapService.chainTokens?.[chainIdentifier];
|
|
349
|
-
if (chainTokens == null)
|
|
350
|
-
return prevMax;
|
|
351
|
-
if (!chainTokens.includes(tokenStr))
|
|
352
|
-
return prevMax;
|
|
353
|
-
return prevMax == null ? swapService.max : Math.max(prevMax, swapService.max);
|
|
354
|
-
}, null);
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* Returns swap candidates for a specific swap type & token address
|
|
358
|
-
*
|
|
359
|
-
* @param chainIdentifier Chain identifier of the smart chain
|
|
360
|
-
* @param swapType Swap protocol type
|
|
361
|
-
* @param tokenAddress Token address
|
|
362
|
-
* @param amount Amount to be swapped in sats - BTC
|
|
363
|
-
* @param count How many intermediaries to return at most
|
|
364
|
-
*/
|
|
365
|
-
getSwapCandidates(chainIdentifier, swapType, tokenAddress, amount, count) {
|
|
366
|
-
const candidates = this.intermediaries.filter(e => {
|
|
367
|
-
const swapService = e.services[swapType];
|
|
368
|
-
if (swapService == null)
|
|
369
|
-
return false;
|
|
370
|
-
if (amount != null && amount < BigInt(swapService.min))
|
|
371
|
-
return false;
|
|
372
|
-
if (amount != null && amount > BigInt(swapService.max))
|
|
373
|
-
return false;
|
|
374
|
-
if (swapService.chainTokens == null)
|
|
375
|
-
return false;
|
|
376
|
-
if (swapService.chainTokens[chainIdentifier] == null)
|
|
377
|
-
return false;
|
|
378
|
-
if (!swapService.chainTokens[chainIdentifier].includes(tokenAddress.toString()))
|
|
379
|
-
return false;
|
|
380
|
-
return true;
|
|
381
|
-
});
|
|
382
|
-
candidates.sort(getIntermediaryComparator(swapType, tokenAddress, amount));
|
|
383
|
-
if (count == null) {
|
|
384
|
-
return candidates;
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
return candidates.slice(0, count);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* Removes a specific intermediary from the list of active intermediaries (used for blacklisting)
|
|
392
|
-
*
|
|
393
|
-
* @param intermediary
|
|
394
|
-
*/
|
|
395
|
-
removeIntermediary(intermediary) {
|
|
396
|
-
const index = this.intermediaries.indexOf(intermediary);
|
|
397
|
-
if (index >= 0) {
|
|
398
|
-
logger.info("removeIntermediary(): Removing intermediary: " + intermediary.url);
|
|
399
|
-
this.intermediaries.splice(index, 1);
|
|
400
|
-
this.emit("removed", [intermediary]);
|
|
401
|
-
return true;
|
|
402
|
-
}
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
exports.IntermediaryDiscovery = IntermediaryDiscovery;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IntermediaryDiscovery = exports.SwapHandlerType = void 0;
|
|
4
|
+
const Intermediary_1 = require("./Intermediary");
|
|
5
|
+
const SwapType_1 = require("../enums/SwapType");
|
|
6
|
+
const events_1 = require("events");
|
|
7
|
+
const buffer_1 = require("buffer");
|
|
8
|
+
const Utils_1 = require("../utils/Utils");
|
|
9
|
+
const IntermediaryAPI_1 = require("./apis/IntermediaryAPI");
|
|
10
|
+
const Logger_1 = require("../utils/Logger");
|
|
11
|
+
const HttpUtils_1 = require("../http/HttpUtils");
|
|
12
|
+
const RetryUtils_1 = require("../utils/RetryUtils");
|
|
13
|
+
/**
|
|
14
|
+
* Swap handler type mapping for intermediary communication
|
|
15
|
+
*
|
|
16
|
+
* @category LPs
|
|
17
|
+
*/
|
|
18
|
+
var SwapHandlerType;
|
|
19
|
+
(function (SwapHandlerType) {
|
|
20
|
+
SwapHandlerType["TO_BTC"] = "TO_BTC";
|
|
21
|
+
SwapHandlerType["FROM_BTC"] = "FROM_BTC";
|
|
22
|
+
SwapHandlerType["TO_BTCLN"] = "TO_BTCLN";
|
|
23
|
+
SwapHandlerType["FROM_BTCLN"] = "FROM_BTCLN";
|
|
24
|
+
SwapHandlerType["FROM_BTC_TRUSTED"] = "FROM_BTC_TRUSTED";
|
|
25
|
+
SwapHandlerType["FROM_BTCLN_TRUSTED"] = "FROM_BTCLN_TRUSTED";
|
|
26
|
+
SwapHandlerType["FROM_BTC_SPV"] = "FROM_BTC_SPV";
|
|
27
|
+
SwapHandlerType["FROM_BTCLN_AUTO"] = "FROM_BTCLN_AUTO";
|
|
28
|
+
})(SwapHandlerType || (exports.SwapHandlerType = SwapHandlerType = {}));
|
|
29
|
+
/**
|
|
30
|
+
* Converts SwapHandlerType (represented as string & used in REST API communication with intermediaries) to regular
|
|
31
|
+
* {@link SwapType}
|
|
32
|
+
*
|
|
33
|
+
* @param swapHandlerType
|
|
34
|
+
*/
|
|
35
|
+
function swapHandlerTypeToSwapType(swapHandlerType) {
|
|
36
|
+
switch (swapHandlerType) {
|
|
37
|
+
case SwapHandlerType.FROM_BTC:
|
|
38
|
+
return SwapType_1.SwapType.FROM_BTC;
|
|
39
|
+
case SwapHandlerType.TO_BTC:
|
|
40
|
+
return SwapType_1.SwapType.TO_BTC;
|
|
41
|
+
case SwapHandlerType.FROM_BTCLN:
|
|
42
|
+
return SwapType_1.SwapType.FROM_BTCLN;
|
|
43
|
+
case SwapHandlerType.TO_BTCLN:
|
|
44
|
+
return SwapType_1.SwapType.TO_BTCLN;
|
|
45
|
+
case SwapHandlerType.FROM_BTC_TRUSTED:
|
|
46
|
+
return SwapType_1.SwapType.TRUSTED_FROM_BTC;
|
|
47
|
+
case SwapHandlerType.FROM_BTCLN_TRUSTED:
|
|
48
|
+
return SwapType_1.SwapType.TRUSTED_FROM_BTCLN;
|
|
49
|
+
case SwapHandlerType.FROM_BTC_SPV:
|
|
50
|
+
return SwapType_1.SwapType.SPV_VAULT_FROM_BTC;
|
|
51
|
+
case SwapHandlerType.FROM_BTCLN_AUTO:
|
|
52
|
+
return SwapType_1.SwapType.FROM_BTCLN_AUTO;
|
|
53
|
+
default:
|
|
54
|
+
return SwapType_1.SwapType.TRUSTED_FROM_BTCLN;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A default intermediary comparator, only takes the announced fee into consideration
|
|
59
|
+
*
|
|
60
|
+
* @param swapType
|
|
61
|
+
* @param tokenAddress
|
|
62
|
+
* @param swapAmount
|
|
63
|
+
*/
|
|
64
|
+
function getIntermediaryComparator(swapType, tokenAddress, swapAmount) {
|
|
65
|
+
if (swapType === SwapType_1.SwapType.TO_BTC) {
|
|
66
|
+
//TODO: Also take reputation into account
|
|
67
|
+
}
|
|
68
|
+
return (a, b) => {
|
|
69
|
+
const aService = a.services[swapType];
|
|
70
|
+
const bService = b.services[swapType];
|
|
71
|
+
if (aService == null && bService == null)
|
|
72
|
+
return 0;
|
|
73
|
+
if (aService == null)
|
|
74
|
+
return 1;
|
|
75
|
+
if (bService == null)
|
|
76
|
+
return -1;
|
|
77
|
+
if (swapAmount == null) {
|
|
78
|
+
return aService.swapFeePPM - bService.swapFeePPM;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const feeA = BigInt(aService.swapBaseFee) + (swapAmount * BigInt(aService.swapFeePPM) / 1000000n);
|
|
82
|
+
const feeB = BigInt(bService.swapBaseFee) + (swapAmount * BigInt(bService.swapFeePPM) / 1000000n);
|
|
83
|
+
return feeA - feeB > 0n ? 1 : feeA === feeB ? 0 : -1;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const logger = (0, Logger_1.getLogger)("IntermediaryDiscovery: ");
|
|
88
|
+
const REGISTRY_URL = "https://api.github.com/repos/adambor/SolLightning-registry/contents/registry.json?ref=main";
|
|
89
|
+
//To allow for legacy responses from not-yet updated LPs
|
|
90
|
+
const DEFAULT_CHAIN = "SOLANA";
|
|
91
|
+
/**
|
|
92
|
+
* Discovery service for available intermediaries (liquidity providers)
|
|
93
|
+
*
|
|
94
|
+
* @category LPs
|
|
95
|
+
*/
|
|
96
|
+
class IntermediaryDiscovery extends events_1.EventEmitter {
|
|
97
|
+
constructor(swapContracts, registryUrl = REGISTRY_URL, nodeUrls, httpRequestTimeout, maxWaitForOthersTimeout) {
|
|
98
|
+
super();
|
|
99
|
+
/**
|
|
100
|
+
* A current list of active intermediaries
|
|
101
|
+
*/
|
|
102
|
+
this.intermediaries = [];
|
|
103
|
+
this.swapContracts = swapContracts;
|
|
104
|
+
this.registryUrl = registryUrl;
|
|
105
|
+
this.overrideNodeUrls = nodeUrls;
|
|
106
|
+
this.httpRequestTimeout = httpRequestTimeout;
|
|
107
|
+
this.maxWaitForOthersTimeout = maxWaitForOthersTimeout;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Fetches the URLs of swap intermediaries from registry or from a pre-defined array of node urls
|
|
111
|
+
*
|
|
112
|
+
* @param abortSignal
|
|
113
|
+
*/
|
|
114
|
+
async getIntermediaryUrls(abortSignal) {
|
|
115
|
+
if (this.overrideNodeUrls != null && this.overrideNodeUrls.length > 0) {
|
|
116
|
+
return this.overrideNodeUrls;
|
|
117
|
+
}
|
|
118
|
+
const response = await (0, RetryUtils_1.tryWithRetries)(() => (0, HttpUtils_1.httpGet)(this.registryUrl, this.httpRequestTimeout, abortSignal), { maxRetries: 3, delay: 100, exponential: true });
|
|
119
|
+
const content = response.content.replace(new RegExp("\\n", "g"), "");
|
|
120
|
+
return JSON.parse(buffer_1.Buffer.from(content, "base64").toString());
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Returns data as reported by a specific node (as identified by its URL). This function is specifically made
|
|
124
|
+
* in a way, that in case the abortSignal fires AFTER the LP response was received (and during signature checking),
|
|
125
|
+
* it proceeds with the addresses it was able to verify already. Hence after calling abort, this function is guaranteed
|
|
126
|
+
* to either reject or resolve instantly.
|
|
127
|
+
*
|
|
128
|
+
* @param url
|
|
129
|
+
* @param abortSignal
|
|
130
|
+
*/
|
|
131
|
+
async getNodeInfo(url, abortSignal) {
|
|
132
|
+
const response = await (0, RetryUtils_1.tryWithRetries)(() => IntermediaryAPI_1.IntermediaryAPI.getIntermediaryInfo(url, this.httpRequestTimeout, abortSignal), { maxRetries: 3, delay: 100, exponential: true }, undefined, abortSignal, "debug");
|
|
133
|
+
abortSignal?.throwIfAborted();
|
|
134
|
+
const promises = [];
|
|
135
|
+
const addresses = {};
|
|
136
|
+
for (let chain in response.chains) {
|
|
137
|
+
if (this.swapContracts[chain] != null) {
|
|
138
|
+
promises.push((async () => {
|
|
139
|
+
const { signature, address } = response.chains[chain];
|
|
140
|
+
try {
|
|
141
|
+
await this.swapContracts[chain].isValidDataSignature(buffer_1.Buffer.from(response.envelope), signature, address);
|
|
142
|
+
addresses[chain] = address;
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
logger.warn("getNodeInfo(): Failed to verify " + chain + " signature for intermediary: " + url);
|
|
146
|
+
}
|
|
147
|
+
})());
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (abortSignal != null) {
|
|
151
|
+
await Promise.race([
|
|
152
|
+
Promise.all(promises),
|
|
153
|
+
new Promise(resolve => abortSignal.addEventListener("abort", resolve))
|
|
154
|
+
]);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
await Promise.all(promises);
|
|
158
|
+
}
|
|
159
|
+
//Handle legacy responses
|
|
160
|
+
const info = JSON.parse(response.envelope);
|
|
161
|
+
for (let swapType in info.services) {
|
|
162
|
+
const serviceData = info.services[swapType];
|
|
163
|
+
if (serviceData.chainTokens == null)
|
|
164
|
+
serviceData.chainTokens = {
|
|
165
|
+
[DEFAULT_CHAIN]: serviceData.tokens
|
|
166
|
+
};
|
|
167
|
+
for (let chain in serviceData.chainTokens) {
|
|
168
|
+
if (addresses[chain] == null)
|
|
169
|
+
delete serviceData.chainTokens[chain];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
addresses,
|
|
174
|
+
info
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Inherits abort signal logic from `getNodeInfo()`, check those function docs to better understand
|
|
179
|
+
*
|
|
180
|
+
* @param url
|
|
181
|
+
* @param abortSignal
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
async loadIntermediary(url, abortSignal) {
|
|
185
|
+
try {
|
|
186
|
+
const nodeInfo = await this.getNodeInfo(url, abortSignal);
|
|
187
|
+
const services = {};
|
|
188
|
+
for (let key in nodeInfo.info.services) {
|
|
189
|
+
services[swapHandlerTypeToSwapType(key)] = nodeInfo.info.services[key];
|
|
190
|
+
}
|
|
191
|
+
return new Intermediary_1.Intermediary(url, nodeInfo.addresses, services);
|
|
192
|
+
}
|
|
193
|
+
catch (e) {
|
|
194
|
+
logger.warn("fetchIntermediaries(): Intermediary " + url + ` is unreachable due to ${e.name ?? e.message} error, skipping...`);
|
|
195
|
+
logger.debug("fetchIntermediaries(): Error contacting intermediary " + url + ": ", e);
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Returns the intermediary at the provided URL, either from the already fetched list of LPs
|
|
201
|
+
* or fetches the data on-demand, by sending the handshake HTTP request (/info) to the LP.
|
|
202
|
+
*
|
|
203
|
+
* Doesn't save the fetched intermediary to the list of intermediaries if it isn't already
|
|
204
|
+
* part of the known intermediaries
|
|
205
|
+
*
|
|
206
|
+
* @param url Base URL of the intermediary, which accepts HTTP requests
|
|
207
|
+
* @param abortSignal
|
|
208
|
+
*/
|
|
209
|
+
getIntermediary(url, abortSignal) {
|
|
210
|
+
const foundLp = this.intermediaries.find(lp => lp.url === url);
|
|
211
|
+
if (foundLp != null)
|
|
212
|
+
return Promise.resolve(foundLp);
|
|
213
|
+
return this.loadIntermediary(url, abortSignal);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Reloads the saves a list of intermediaries
|
|
217
|
+
*
|
|
218
|
+
* @param abortSignal
|
|
219
|
+
*/
|
|
220
|
+
async reloadIntermediaries(abortSignal) {
|
|
221
|
+
//Get LP urls
|
|
222
|
+
const urls = await this.getIntermediaryUrls(abortSignal);
|
|
223
|
+
logger.debug("reloadIntermediaries(): Pinging intermediaries: ", urls.join());
|
|
224
|
+
const abortController = (0, Utils_1.extendAbortController)(abortSignal);
|
|
225
|
+
let timer;
|
|
226
|
+
const intermediaries = await Promise.all(urls.map(url => this.loadIntermediary(url, abortController.signal).then(lp => {
|
|
227
|
+
if (lp != null && timer == null)
|
|
228
|
+
timer = setTimeout(() => {
|
|
229
|
+
//Trigger abort through the abort controller, such that all underlying promises resolve instantly
|
|
230
|
+
abortController.abort();
|
|
231
|
+
}, this.maxWaitForOthersTimeout ?? 5 * 1000);
|
|
232
|
+
return lp;
|
|
233
|
+
})));
|
|
234
|
+
if (timer != null)
|
|
235
|
+
clearTimeout(timer);
|
|
236
|
+
const activeNodes = intermediaries.filter(intermediary => intermediary != null);
|
|
237
|
+
if (activeNodes.length === 0)
|
|
238
|
+
logger.error("reloadIntermediaries(): No online intermediary found! Swaps might not be possible!");
|
|
239
|
+
this.intermediaries = activeNodes;
|
|
240
|
+
this.emit("added", activeNodes);
|
|
241
|
+
logger.info("reloadIntermediaries(): Using active intermediaries: ", activeNodes.map(lp => lp.url).join());
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Initializes the discovery by fetching/reloading intermediaries
|
|
245
|
+
*
|
|
246
|
+
* @param abortSignal
|
|
247
|
+
*/
|
|
248
|
+
init(abortSignal) {
|
|
249
|
+
logger.info("init(): Initializing with registryUrl: " + this.registryUrl + " intermediary array: " + (this.overrideNodeUrls || []).join());
|
|
250
|
+
return this.reloadIntermediaries(abortSignal);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Returns known swap bounds (in satoshis - BTC) by aggregating values from all known intermediaries
|
|
254
|
+
*/
|
|
255
|
+
getMultichainSwapBounds() {
|
|
256
|
+
const bounds = {};
|
|
257
|
+
this.intermediaries.forEach(intermediary => {
|
|
258
|
+
for (let _swapType in intermediary.services) {
|
|
259
|
+
const swapType = parseInt(_swapType);
|
|
260
|
+
const swapService = intermediary.services[swapType];
|
|
261
|
+
const multichainBounds = (bounds[swapType] ??= {});
|
|
262
|
+
for (let chainId in swapService.chainTokens) {
|
|
263
|
+
multichainBounds[chainId] ??= {};
|
|
264
|
+
const tokenBounds = multichainBounds[chainId];
|
|
265
|
+
for (let token of swapService.chainTokens[chainId]) {
|
|
266
|
+
const tokenMinMax = tokenBounds[token];
|
|
267
|
+
if (tokenMinMax == null) {
|
|
268
|
+
tokenBounds[token] = {
|
|
269
|
+
min: BigInt(swapService.min),
|
|
270
|
+
max: BigInt(swapService.max)
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
tokenMinMax.min = (0, Utils_1.bigIntMin)(tokenMinMax.min, BigInt(swapService.min));
|
|
275
|
+
tokenMinMax.max = (0, Utils_1.bigIntMax)(tokenMinMax.max, BigInt(swapService.max));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
return bounds;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Returns aggregate swap bounds (in satoshis - BTC) as indicated by the intermediaries
|
|
285
|
+
*/
|
|
286
|
+
getSwapBounds(chainIdentifier) {
|
|
287
|
+
const bounds = {};
|
|
288
|
+
this.intermediaries.forEach(intermediary => {
|
|
289
|
+
for (let _swapType in intermediary.services) {
|
|
290
|
+
const swapType = parseInt(_swapType);
|
|
291
|
+
const swapService = intermediary.services[swapType];
|
|
292
|
+
const tokenBounds = (bounds[swapType] ??= {});
|
|
293
|
+
if (swapService.chainTokens != null && swapService.chainTokens[chainIdentifier] != null) {
|
|
294
|
+
for (let token of swapService.chainTokens[chainIdentifier]) {
|
|
295
|
+
const tokenMinMax = tokenBounds[token];
|
|
296
|
+
if (tokenMinMax == null) {
|
|
297
|
+
tokenBounds[token] = {
|
|
298
|
+
min: BigInt(swapService.min),
|
|
299
|
+
max: BigInt(swapService.max)
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
tokenMinMax.min = (0, Utils_1.bigIntMin)(tokenMinMax.min, BigInt(swapService.min));
|
|
304
|
+
tokenMinMax.max = (0, Utils_1.bigIntMax)(tokenMinMax.max, BigInt(swapService.max));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
return bounds;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Returns the aggregate swap minimum (in satoshis - BTC) for a specific swap type & token
|
|
314
|
+
* as indicated by the intermediaries
|
|
315
|
+
*
|
|
316
|
+
* @param chainIdentifier Chain identifier of the smart chain
|
|
317
|
+
* @param swapType Swap protocol type
|
|
318
|
+
* @param tokenAddress Token address
|
|
319
|
+
*/
|
|
320
|
+
getSwapMinimum(chainIdentifier, swapType, tokenAddress) {
|
|
321
|
+
const tokenStr = tokenAddress.toString();
|
|
322
|
+
return this.intermediaries.reduce((prevMin, intermediary) => {
|
|
323
|
+
const swapService = intermediary.services[swapType];
|
|
324
|
+
if (swapService == null)
|
|
325
|
+
return prevMin;
|
|
326
|
+
const chainTokens = swapService.chainTokens?.[chainIdentifier];
|
|
327
|
+
if (chainTokens == null)
|
|
328
|
+
return prevMin;
|
|
329
|
+
if (!chainTokens.includes(tokenStr))
|
|
330
|
+
return prevMin;
|
|
331
|
+
return prevMin == null ? swapService.min : Math.min(prevMin, swapService.min);
|
|
332
|
+
}, null);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Returns the aggregate swap maximum (in satoshis - BTC) for a specific swap type & token
|
|
336
|
+
* as indicated by the intermediaries
|
|
337
|
+
*
|
|
338
|
+
* @param chainIdentifier Chain identifier of the smart chain
|
|
339
|
+
* @param swapType Swap protocol type
|
|
340
|
+
* @param tokenAddress Token address
|
|
341
|
+
*/
|
|
342
|
+
getSwapMaximum(chainIdentifier, swapType, tokenAddress) {
|
|
343
|
+
const tokenStr = tokenAddress.toString();
|
|
344
|
+
return this.intermediaries.reduce((prevMax, intermediary) => {
|
|
345
|
+
const swapService = intermediary.services[swapType];
|
|
346
|
+
if (swapService == null)
|
|
347
|
+
return prevMax;
|
|
348
|
+
const chainTokens = swapService.chainTokens?.[chainIdentifier];
|
|
349
|
+
if (chainTokens == null)
|
|
350
|
+
return prevMax;
|
|
351
|
+
if (!chainTokens.includes(tokenStr))
|
|
352
|
+
return prevMax;
|
|
353
|
+
return prevMax == null ? swapService.max : Math.max(prevMax, swapService.max);
|
|
354
|
+
}, null);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Returns swap candidates for a specific swap type & token address
|
|
358
|
+
*
|
|
359
|
+
* @param chainIdentifier Chain identifier of the smart chain
|
|
360
|
+
* @param swapType Swap protocol type
|
|
361
|
+
* @param tokenAddress Token address
|
|
362
|
+
* @param amount Amount to be swapped in sats - BTC
|
|
363
|
+
* @param count How many intermediaries to return at most
|
|
364
|
+
*/
|
|
365
|
+
getSwapCandidates(chainIdentifier, swapType, tokenAddress, amount, count) {
|
|
366
|
+
const candidates = this.intermediaries.filter(e => {
|
|
367
|
+
const swapService = e.services[swapType];
|
|
368
|
+
if (swapService == null)
|
|
369
|
+
return false;
|
|
370
|
+
if (amount != null && amount < BigInt(swapService.min))
|
|
371
|
+
return false;
|
|
372
|
+
if (amount != null && amount > BigInt(swapService.max))
|
|
373
|
+
return false;
|
|
374
|
+
if (swapService.chainTokens == null)
|
|
375
|
+
return false;
|
|
376
|
+
if (swapService.chainTokens[chainIdentifier] == null)
|
|
377
|
+
return false;
|
|
378
|
+
if (!swapService.chainTokens[chainIdentifier].includes(tokenAddress.toString()))
|
|
379
|
+
return false;
|
|
380
|
+
return true;
|
|
381
|
+
});
|
|
382
|
+
candidates.sort(getIntermediaryComparator(swapType, tokenAddress, amount));
|
|
383
|
+
if (count == null) {
|
|
384
|
+
return candidates;
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
return candidates.slice(0, count);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Removes a specific intermediary from the list of active intermediaries (used for blacklisting)
|
|
392
|
+
*
|
|
393
|
+
* @param intermediary
|
|
394
|
+
*/
|
|
395
|
+
removeIntermediary(intermediary) {
|
|
396
|
+
const index = this.intermediaries.indexOf(intermediary);
|
|
397
|
+
if (index >= 0) {
|
|
398
|
+
logger.info("removeIntermediary(): Removing intermediary: " + intermediary.url);
|
|
399
|
+
this.intermediaries.splice(index, 1);
|
|
400
|
+
this.emit("removed", [intermediary]);
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
exports.IntermediaryDiscovery = IntermediaryDiscovery;
|