UNPKG

@xspswap/smart-order-router

Version:
277 lines 24.8 kB
import { FeeAmount, Pool } from '@x-swap-protocol/v3-sdk'; import JSBI from 'jsbi'; import _ from 'lodash'; import { unparseFeeAmount } from '../../util/amounts'; import { ChainId, WRAPPED_NATIVE_CURRENCY } from '../../util/chains'; import { log } from '../../util/log'; import { BBB_XDC, BIC_XDC, BTCx_XDC, CGO_XDC, CHUPAV2_XDC, CIFI_XDC, DOPU_XDC, EURS_XDC, FTHM_XDC, FXD_XDC, GAMA_XDC, LBT_XDC, PLI_XDC, PRNT_XDC, pstXDC_XDC, PWM3_XDC, REFI_XDC, SRX_XDC, USDC_XDC, USDT_XDC, USDT_XDC_APOTHEM, WBTC_XDC_APOTHEM, WTK_XDC, WXDC_XDC, XSP_XDC, XTT_XDC, XZO_XDC, } from '../token-provider'; const BASES_TO_CHECK_TRADES_AGAINST = { [ChainId.XDC]: [WRAPPED_NATIVE_CURRENCY[ChainId.XDC], USDC_XDC], [ChainId.XDC_APOTHEM]: [ WRAPPED_NATIVE_CURRENCY[ChainId.XDC_APOTHEM], USDT_XDC_APOTHEM, WBTC_XDC_APOTHEM, ], }; export const ADDITIONAL_BASES = { [ChainId.XDC]: { [WRAPPED_NATIVE_CURRENCY[ChainId.XDC].address]: [ [USDC_XDC, FeeAmount.MEDIUM], [pstXDC_XDC, FeeAmount.HIGH], [GAMA_XDC, FeeAmount.LOWEST], [GAMA_XDC, FeeAmount.MEDIUM], [BBB_XDC, FeeAmount.MEDIUM], [DOPU_XDC, FeeAmount.LOWEST], [BTCx_XDC, FeeAmount.HIGH], [FXD_XDC, FeeAmount.MEDIUM], [PLI_XDC, FeeAmount.MEDIUM], [CHUPAV2_XDC, FeeAmount.HIGH], [CIFI_XDC, FeeAmount.HIGH], [WTK_XDC, FeeAmount.HIGH], [LBT_XDC, FeeAmount.MEDIUM], [XSP_XDC, FeeAmount.MEDIUM], [EURS_XDC, FeeAmount.MEDIUM], [USDT_XDC, FeeAmount.MEDIUM], [SRX_XDC, FeeAmount.MEDIUM], [PWM3_XDC, FeeAmount.HIGH], [PRNT_XDC, FeeAmount.HIGH], [XZO_XDC, FeeAmount.MEDIUM], [BIC_XDC, FeeAmount.MEDIUM], [FTHM_XDC, FeeAmount.MEDIUM], [XTT_XDC, FeeAmount.MEDIUM], [REFI_XDC, FeeAmount.HIGH], ], [FXD_XDC.address]: [ [USDC_XDC, FeeAmount.MEDIUM], [EURS_XDC, FeeAmount.LOWEST], [USDT_XDC, FeeAmount.LOW], [WXDC_XDC, FeeAmount.MEDIUM], [SRX_XDC, FeeAmount.LOWEST], [CGO_XDC, FeeAmount.LOWEST], [EURS_XDC, FeeAmount.LOW], [CGO_XDC, FeeAmount.LOW], ], [USDC_XDC.address]: [ [FXD_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.MEDIUM], ], [EURS_XDC.address]: [ [FXD_XDC, FeeAmount.LOWEST], [WXDC_XDC, FeeAmount.MEDIUM], [SRX_XDC, FeeAmount.MEDIUM], [FXD_XDC, FeeAmount.LOW], ], [USDT_XDC.address]: [ [FXD_XDC, FeeAmount.LOW], [SRX_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.MEDIUM], ], [DOPU_XDC.address]: [ [WXDC_XDC, FeeAmount.LOWEST], [BBB_XDC, FeeAmount.MEDIUM], ], [SRX_XDC.address]: [ [FXD_XDC, FeeAmount.LOWEST], [USDT_XDC, FeeAmount.MEDIUM], [EURS_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.MEDIUM], [PLI_XDC, FeeAmount.HIGH], ], [PLI_XDC.address]: [ [WXDC_XDC, FeeAmount.MEDIUM], [CIFI_XDC, FeeAmount.HIGH], [FXD_XDC, FeeAmount.HIGH], ], [CIFI_XDC.address]: [ [WXDC_XDC, FeeAmount.HIGH], [PLI_XDC, FeeAmount.HIGH], [REFI_XDC, FeeAmount.HIGH], ], [CHUPAV2_XDC.address]: [[WXDC_XDC, FeeAmount.HIGH]], [XSP_XDC.address]: [ [XTT_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.MEDIUM], [BIC_XDC, FeeAmount.MEDIUM], ], [CGO_XDC.address]: [ [FXD_XDC, FeeAmount.LOWEST], [FXD_XDC, FeeAmount.LOW], ], [WTK_XDC.address]: [ [WXDC_XDC, FeeAmount.HIGH], [PLI_XDC, FeeAmount.HIGH], ], [XTT_XDC.address]: [ [XSP_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.MEDIUM], ], [LBT_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [BIC_XDC.address]: [ [WXDC_XDC, FeeAmount.MEDIUM], [USDT_XDC, FeeAmount.HIGH], ], [PRNT_XDC.address]: [ [WXDC_XDC, FeeAmount.HIGH], [WXDC_XDC, FeeAmount.MEDIUM], ], [BBB_XDC.address]: [ [DOPU_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.HIGH], ], [FTHM_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [XZO_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], }, [ChainId.XDC_APOTHEM]: {}, }; export const V3_XDC_ADDITIONAL_BASES = ADDITIONAL_BASES[ChainId.XDC]; let paths = []; const recFinder = (path, used, lastToken, dest, hops) => { const hop = path.length; // if (hop > 0) { // lastToken = path[hop - 1]![1]; // } if (hop < hops) { if (!lastToken) { return; } const additional = V3_XDC_ADDITIONAL_BASES[lastToken.address]; if (additional) { for (const ad of additional) { const adToken = ad; const newPair = [lastToken, ...adToken]; const newPath = [...path, newPair]; if (adToken[0].address === dest.address) { paths.push(newPath); continue; } if (!used[adToken[0].address]) { recFinder(newPath, { ...used, [adToken[0].address]: true }, adToken[0], dest, hops); } } } } }; /** * Provider that uses a hardcoded list of V3 pools to generate a list of subgraph pools. * * Since the pools are hardcoded and the data does not come from the Subgraph, the TVL values * are dummys and should not be depended on. * * Useful for instances where other data sources are unavailable. E.g. Subgraph not available. * * @export * @class StaticV3SubgraphProvider */ export class StaticV3SubgraphProvider { constructor(chainId, poolProvider) { this.chainId = chainId; this.poolProvider = poolProvider; } async getPools(tokenIn, tokenOut) { paths = []; log.info('In static subgraph provider for V3'); const bases = BASES_TO_CHECK_TRADES_AGAINST[this.chainId]; const basePairs = _.flatMap(bases, (base) => bases.map((otherBase) => [base, otherBase])); let pairs = []; if (tokenIn && tokenOut) { const additionalIn = ADDITIONAL_BASES[this.chainId][tokenIn.address]; const additionalOut = ADDITIONAL_BASES[this.chainId][tokenOut.address]; if (!additionalIn || !additionalOut) { basePairs.push([tokenIn, tokenOut]); if (additionalIn) { basePairs.push(...additionalIn.map((v) => [tokenIn, v[0]])); } else { basePairs.push(...bases.map((base) => [tokenIn, base])); } if (additionalOut) { basePairs.push(...additionalOut.map((v) => [tokenOut, v[0]])); } else { basePairs.push(...bases.map((base) => [tokenOut, base])); } pairs = _(basePairs) .filter((tokens) => Boolean(tokens[0] && tokens[1])) .filter(([tokenA, tokenB]) => tokenA.address !== tokenB.address && !tokenA.equals(tokenB)) .flatMap(([tokenA, tokenB]) => { const additionalA = ADDITIONAL_BASES[this.chainId][tokenA.address]; // const additionalB = ADDITIONAL_BASES[this.chainId][tokenB.address]; if (additionalA) { const additionalPool = additionalA.filter((v) => v[0].address.toLowerCase() === tokenB.address.toLowerCase()); const res = additionalPool.map((v) => { return [tokenA, v[0], v[1]]; }); return res; } return [ [tokenA, tokenB, FeeAmount.LOWEST], [tokenA, tokenB, FeeAmount.LOW], [tokenA, tokenB, FeeAmount.MEDIUM], [tokenA, tokenB, FeeAmount.HIGH], ]; }) .value(); } else { recFinder([], { [tokenIn.address]: true }, tokenIn, tokenOut, 5); // console.log( // paths.map((path) => // path // .map( // (p) => `(${p[0].symbol} - ${p[1].symbol} : ${p[2] / 10000}% )` // ) // .join(' --> ') // ) // ); const uniquePairs = {}; paths.forEach((path) => { path.forEach((pool) => { const id = `${pool[0].address}-${pool[1].address}-${pool[2]}`; uniquePairs[id] = pool; }); }); const direct = tokenIn && tokenOut ? [ [tokenIn, tokenOut, FeeAmount.LOWEST], [tokenIn, tokenOut, FeeAmount.LOW], [tokenIn, tokenOut, FeeAmount.MEDIUM], [tokenIn, tokenOut, FeeAmount.HIGH], ] : []; pairs = [...Object.values(uniquePairs), ...direct]; } } log.info(`V3 Static subgraph provider about to get ${pairs.length} pools on-chain`); const poolAccessor = await this.poolProvider.getPools(pairs); const pools = poolAccessor.getAllPools(); const poolAddressSet = new Set(); const subgraphPools = _(pools) .map((pool) => { const { token0, token1, fee, liquidity } = pool; const poolAddress = Pool.getAddress(pool.token0, pool.token1, pool.fee); if (poolAddressSet.has(poolAddress)) { return undefined; } poolAddressSet.add(poolAddress); const liquidityNumber = JSBI.toNumber(liquidity); return { id: poolAddress, feeTier: unparseFeeAmount(fee), liquidity: liquidity.toString(), token0: { id: token0.address, }, token1: { id: token1.address, }, // As a very rough proxy we just use liquidity for TVL. tvlETH: liquidityNumber, tvlUSD: liquidityNumber, }; }) .compact() .value(); return subgraphPools; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLXN1YmdyYXBoLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy92My9zdGF0aWMtc3ViZ3JhcGgtcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMxRCxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckMsT0FBTyxFQUNMLE9BQU8sRUFDUCxPQUFPLEVBQ1AsUUFBUSxFQUNSLE9BQU8sRUFDUCxXQUFXLEVBQ1gsUUFBUSxFQUNSLFFBQVEsRUFDUixRQUFRLEVBQ1IsUUFBUSxFQUNSLE9BQU8sRUFDUCxRQUFRLEVBQ1IsT0FBTyxFQUNQLE9BQU8sRUFDUCxRQUFRLEVBQ1IsVUFBVSxFQUNWLFFBQVEsRUFDUixRQUFRLEVBQ1IsT0FBTyxFQUNQLFFBQVEsRUFDUixRQUFRLEVBQ1IsZ0JBQWdCLEVBQ2hCLGdCQUFnQixFQUNoQixPQUFPLEVBQ1AsUUFBUSxFQUNSLE9BQU8sRUFDUCxPQUFPLEVBQ1AsT0FBTyxHQUNSLE1BQU0sbUJBQW1CLENBQUM7QUFTM0IsTUFBTSw2QkFBNkIsR0FBbUI7SUFDcEQsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsUUFBUSxDQUFDO0lBQy9ELENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxFQUFFO1FBQ3JCLHVCQUF1QixDQUFDLE9BQU8sQ0FB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