UNPKG

@xspswap/smart-order-router

Version:
229 lines 21 kB
/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { ChainId, WETH9 } from '@x-swap-protocol/sdk-core'; import { FeeAmount, Pool } from '@x-swap-protocol/v3-sdk'; import JSBI from 'jsbi'; import _ from 'lodash'; import { unparseFeeAmount } from '../../util/amounts'; import { log } from '../../util/log'; import { AVR_XDC, BBB_XDC, CGO_XDC, CHUPAV2_XDC, DOPU_XDC, EEG_XDC, FXD_XDC, GAMA_XDC, GLL_XDC, LBT_XDC, PLI_XDC, PWM3_XDC, ROXN_XDC, SRX_XDC, TIVO_XDC, USDC_XDC, USDT_XDC_APOTHEM, WBTC_XDC_APOTHEM, WXDC_XDC, XSP_XDC, } from '../token-provider'; const BASES_TO_CHECK_TRADES_AGAINST = { [ChainId.XDC]: [WETH9[ChainId.XDC], USDC_XDC], [ChainId.APOTHEM]: [ WETH9[ChainId.APOTHEM], USDT_XDC_APOTHEM, WBTC_XDC_APOTHEM, ], }; export const ADDITIONAL_BASES = { [ChainId.XDC]: { [WETH9[ChainId.XDC].address]: [ [USDC_XDC, FeeAmount.MEDIUM], [DOPU_XDC, FeeAmount.LOWEST], [GAMA_XDC, FeeAmount.LOWEST], [EEG_XDC, FeeAmount.MEDIUM], [BBB_XDC, FeeAmount.LOWEST], [XSP_XDC, FeeAmount.MEDIUM], [CHUPAV2_XDC, FeeAmount.HIGH], [AVR_XDC, FeeAmount.MEDIUM], [ROXN_XDC, FeeAmount.MEDIUM], [PLI_XDC, FeeAmount.MEDIUM], [LBT_XDC, FeeAmount.MEDIUM], [GLL_XDC, FeeAmount.MEDIUM], [SRX_XDC, FeeAmount.MEDIUM], [PWM3_XDC, FeeAmount.HIGH], ], [USDC_XDC.address]: [ [WXDC_XDC, FeeAmount.MEDIUM], [CGO_XDC, FeeAmount.MEDIUM], [SRX_XDC, FeeAmount.MEDIUM], [GAMA_XDC, FeeAmount.LOWEST], [XSP_XDC, FeeAmount.MEDIUM], ], [GAMA_XDC.address]: [ [WXDC_XDC, FeeAmount.LOWEST], [USDC_XDC, FeeAmount.LOWEST], ], [EEG_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [BBB_XDC.address]: [ [WXDC_XDC, FeeAmount.LOWEST], [WXDC_XDC, FeeAmount.HIGH], ], [DOPU_XDC.address]: [ [WXDC_XDC, FeeAmount.LOWEST], [BBB_XDC, FeeAmount.MEDIUM], ], [CGO_XDC.address]: [ [USDC_XDC, FeeAmount.MEDIUM], [FXD_XDC, FeeAmount.LOW], ], [SRX_XDC.address]: [ [USDC_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.MEDIUM], ], [XSP_XDC.address]: [ [WXDC_XDC, FeeAmount.MEDIUM], [WXDC_XDC, FeeAmount.LOWEST], [USDC_XDC, FeeAmount.MEDIUM], ], [CHUPAV2_XDC.address]: [[WXDC_XDC, FeeAmount.HIGH]], [AVR_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [PLI_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [ROXN_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [LBT_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [GLL_XDC.address]: [[WXDC_XDC, FeeAmount.MEDIUM]], [TIVO_XDC.address]: [[WXDC_XDC, FeeAmount.LOWEST]], }, [ChainId.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-XSWAP 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLXN1YmdyYXBoLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy92My9zdGF0aWMtc3ViZ3JhcGgtcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsNkRBQTZEO0FBQzdELE9BQU8sRUFBRSxPQUFPLEVBQVMsS0FBSyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMxRCxPQUFPLElBQUksTUFBTSxNQUFNLENBQUM7QUFDeEIsT0FBTyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyQyxPQUFPLEVBQ0wsT0FBTyxFQUNQLE9BQU8sRUFDUCxPQUFPLEVBQ1AsV0FBVyxFQUNYLFFBQVEsRUFDUixPQUFPLEVBQ1AsT0FBTyxFQUNQLFFBQVEsRUFDUixPQUFPLEVBQ1AsT0FBTyxFQUNQLE9BQU8sRUFDUCxRQUFRLEVBQ1IsUUFBUSxFQUNSLE9BQU8sRUFDUCxRQUFRLEVBQ1IsUUFBUSxFQUNSLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsUUFBUSxFQUNSLE9BQU8sR0FDUixNQUFNLG1CQUFtQixDQUFDO0FBUzNCLE1BQU0sNkJBQTZCLEdBQW1CO0lBQ3BELENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxRQUFRLENBQUM7SUFDN0MsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7UUFDakIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDdEIsZ0JBQWdCO1FBQ2hCLGdCQUFnQjtLQUNqQjtDQUNGLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FFekI7SUFDRixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRTtRQUNiLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUM1QixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDNUIsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQztZQUM1QixDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzNCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDM0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQztZQUMzQixDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQzdCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDM0IsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQztZQUM1QixDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzNCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDM0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQztZQUMzQixDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzNCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUM7U0FDM0I7UUFDRCxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNsQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDM0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQztZQUMzQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7U0FDNUI7UUFDRCxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNsQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7U0FDN0I7UUFDRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNqRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNqQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUM7U0FDM0I7UUFDRCxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNsQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7U0FDNUI7UUFDRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNqQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxHQUFHLENBQUM7U0FDekI7UUFDRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNqQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7U0FDN0I7UUFDRCxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNqQixDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUM7WUFDNUIsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLE1BQU0sQ0FBQztT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