UNPKG

@atomiqlabs/sdk

Version:

atomiq labs SDK for cross-chain swaps between smart chains and bitcoin

167 lines (166 loc) 7.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Intermediary = void 0; const SwapType_1 = require("../enums/SwapType"); const RetryUtils_1 = require("../utils/RetryUtils"); /** * Represents an intermediary (liquidity provider) * * @category LPs */ class Intermediary { constructor(url, addresses, services, reputation = {}, contractVersions = {}) { /** * Reputation of the intermediary on different smart chains, this is only fetched * on-demand when creating a swap where reputation is checked */ this.reputation = {}; /** * Liquidity of the intermediary across different smart chains, this is only fetched * on-demand when creating a swap where intermediary's liquidity is checked */ this.liquidity = {}; this.url = url; this.addresses = addresses; this.services = services; this.reputation = reputation; this.contractVersions = contractVersions; this.swapBounds = {}; for (let _swapType in this.services) { const swapType = parseInt(_swapType); const serviceInfo = this.services[swapType]; const btcBounds = { min: BigInt(serviceInfo.min), max: BigInt(serviceInfo.max) }; const isSend = swapType === SwapType_1.SwapType.TO_BTC || swapType === SwapType_1.SwapType.TO_BTCLN; this.swapBounds[swapType] = {}; for (let chainIdentifier in serviceInfo.chainTokens) { this.swapBounds[swapType][chainIdentifier] = {}; for (let tokenAddress of serviceInfo.chainTokens[chainIdentifier]) { this.swapBounds[swapType][chainIdentifier][tokenAddress] = { input: isSend ? {} : btcBounds, output: !isSend ? {} : btcBounds, }; } } } } /** * Returns the input/output swap limit for given swap type, chain and token * * @param swapType Swap protocol service to check * @param chainId Chain identifier of the smart chain to check * @param tokenAddress Address of the token to check */ getSwapLimits(swapType, chainId, tokenAddress) { return this.swapBounds[swapType]?.[chainId]?.[tokenAddress]; } /** * Returns tokens supported by the intermediary, optionally constrained to the specific swap types * * @param chainIdentifier Chain identifier of the smart chain to check * @param swapTypesArr An array of swap type services to check * @private */ getSupportedTokens(chainIdentifier, swapTypesArr = [ SwapType_1.SwapType.TO_BTC, SwapType_1.SwapType.TO_BTCLN, SwapType_1.SwapType.FROM_BTC, SwapType_1.SwapType.FROM_BTCLN, SwapType_1.SwapType.SPV_VAULT_FROM_BTC, SwapType_1.SwapType.FROM_BTCLN_AUTO ]) { const swapTypes = new Set(swapTypesArr); let tokens = new Set(); swapTypes.forEach((swapType) => { const supportedTokens = this.services[swapType]?.chainTokens?.[chainIdentifier]; if (supportedTokens != null) supportedTokens.forEach(token => tokens.add(token)); }); return tokens; } /** * Fetches, returns and saves the reputation of the intermediary, either for all or just for a single token * * @param chainIdentifier Chain identifier of the chain on which to fetch the reputation * @param swapContract Swap contract for the requested smart chain * @param tokens An optional array of tokens to fetch the data for (by default it uses all tokens supported * by the intermediary) * @param abortSignal */ async getReputation(chainIdentifier, swapContract, tokens, abortSignal) { const checkReputationTokens = tokens == null ? this.getSupportedTokens(chainIdentifier, [SwapType_1.SwapType.TO_BTC, SwapType_1.SwapType.TO_BTCLN]) : new Set(tokens); const promises = []; const reputation = {}; for (let token of checkReputationTokens) { promises.push((0, RetryUtils_1.tryWithRetries)(() => swapContract.getIntermediaryReputation(this.getAddress(chainIdentifier), token), undefined, undefined, abortSignal).then(result => { if (result != null) reputation[token] = result; })); } await Promise.all(promises); this.reputation ??= {}; this.reputation[chainIdentifier] ??= {}; for (let key in reputation) { this.reputation[chainIdentifier][key] = reputation[key]; } return reputation; } /** * Fetches, returns and saves the liquidity of the intermediary for a specific token * * @param chainIdentifier Chain identifier of the chain on which to fetch the reputation * @param swapContract Swap contract for the requested smart chain * @param token Token address of the token to fetch the liquidity for * @param abortSignal */ async getLiquidity(chainIdentifier, swapContract, token, abortSignal) { const result = await (0, RetryUtils_1.tryWithRetries)(() => swapContract.getBalance(this.getAddress(chainIdentifier), token, true), undefined, undefined, abortSignal); this.liquidity ??= {}; this.liquidity[chainIdentifier] ??= {}; this.liquidity[chainIdentifier][token] = result; return result; } /** * Checks whether the intermediary supports swaps of any tokens on the smart chain * * @param chainIdentifier Chain identifier of the smart chain */ supportsChain(chainIdentifier) { if (this.addresses[chainIdentifier] == null) return false; return this.getSupportedTokens(chainIdentifier).size !== 0; } /** * Returns intermediary's address on a given smart chain * * @param chainIdentifier Chain identifier of the smart chain */ getAddress(chainIdentifier) { return this.addresses[chainIdentifier]; } /** * Returns the contract version used by the intermediary for a given chain * * @param chainIdentifier */ getContractVersion(chainIdentifier) { return this.contractVersions[chainIdentifier] ?? "v1"; } /** * Returns the range of contract versions used by the LPs * * @param chainIdentifier * @param lps */ static getContractVersionsForLps(chainIdentifier, lps) { const versions = []; lps.forEach((lp) => { const lpVersion = lp.getContractVersion(chainIdentifier); if (!versions.includes(lpVersion)) versions.push(lpVersion); }); return versions; } } exports.Intermediary = Intermediary;