UNPKG

@xspswap/smart-order-router

Version:
115 lines 10.9 kB
import { TradeType } from '@x-swap-protocol/sdk-core'; import _ from 'lodash'; import { TokenValidationResult, } from '../../../providers'; import { log, metric, MetricLoggerUnit, routeToString, } from '../../../util'; import { V2RouteWithValidQuote } from '../entities'; import { computeAllV2Routes } from '../functions/compute-all-routes'; import { getV2CandidatePools, } from '../functions/get-candidate-pools'; import { BaseQuoter } from './base-quoter'; export class V2Quoter extends BaseQuoter { constructor(v2SubgraphProvider, v2PoolProvider, v2QuoteProvider, v2GasModelFactory, tokenProvider, chainId, blockedTokenListProvider, tokenValidatorProvider) { super(tokenProvider, chainId, blockedTokenListProvider, tokenValidatorProvider); this.v2SubgraphProvider = v2SubgraphProvider; this.v2PoolProvider = v2PoolProvider; this.v2QuoteProvider = v2QuoteProvider; this.v2GasModelFactory = v2GasModelFactory; } async getRoutes(tokenIn, tokenOut, tradeType, routingConfig) { // Fetch all the pools that we will consider routing via. There are thousands // of pools, so we filter them to a set of candidate pools that we expect will // result in good prices. const { poolAccessor, candidatePools } = await getV2CandidatePools({ tokenIn, tokenOut, tokenProvider: this.tokenProvider, blockedTokenListProvider: this.blockedTokenListProvider, poolProvider: this.v2PoolProvider, routeType: tradeType, subgraphProvider: this.v2SubgraphProvider, routingConfig, chainId: this.chainId, }); const poolsRaw = poolAccessor.getAllPools(); // Drop any pools that contain tokens that can not be transferred according to the token validator. const pools = await this.applyTokenValidatorToPools(poolsRaw, (token, tokenValidation) => { // If there is no available validation result we assume the token is fine. if (!tokenValidation) { return false; } // Only filters out *intermediate* pools that involve tokens that we detect // cant be transferred. This prevents us trying to route through tokens that may // not be transferrable, but allows users to still swap those tokens if they // specify. if (tokenValidation == TokenValidationResult.STF && (token.equals(tokenIn) || token.equals(tokenOut))) { return false; } return tokenValidation == TokenValidationResult.STF; }); // Given all our candidate pools, compute all the possible ways to route from tokenIn to tokenOut. const { maxSwapsPerPath } = routingConfig; const routes = computeAllV2Routes(tokenIn, tokenOut, pools, maxSwapsPerPath); return { routes, candidatePools, }; } async getQuotes(routes, amounts, percents, quoteToken, tradeType, _routingConfig, candidatePools, _gasModel, gasPriceWei) { log.info('Starting to get V2 quotes'); if (gasPriceWei === undefined) { throw new Error('GasPriceWei for V2Routes is required to getQuotes'); } if (routes.length == 0) { return { routesWithValidQuotes: [], candidatePools }; } // For all our routes, and all the fractional amounts, fetch quotes on-chain. const quoteFn = tradeType == TradeType.EXACT_INPUT ? this.v2QuoteProvider.getQuotesManyExactIn.bind(this.v2QuoteProvider) : this.v2QuoteProvider.getQuotesManyExactOut.bind(this.v2QuoteProvider); const beforeQuotes = Date.now(); log.info(`Getting quotes for V2 for ${routes.length} routes with ${amounts.length} amounts per route.`); const { routesWithQuotes } = await quoteFn(amounts, routes); const v2GasModel = await this.v2GasModelFactory.buildGasModel({ chainId: this.chainId, gasPriceWei, poolProvider: this.v2PoolProvider, token: quoteToken, }); metric.putMetric('V2QuotesLoad', Date.now() - beforeQuotes, MetricLoggerUnit.Milliseconds); metric.putMetric('V2QuotesFetched', _(routesWithQuotes) .map(([, quotes]) => quotes.length) .sum(), MetricLoggerUnit.Count); const routesWithValidQuotes = []; for (const routeWithQuote of routesWithQuotes) { const [route, quotes] = routeWithQuote; for (let i = 0; i < quotes.length; i++) { const percent = percents[i]; const amountQuote = quotes[i]; const { quote, amount } = amountQuote; if (!quote) { log.debug({ route: routeToString(route), amountQuote, }, 'Dropping a null V2 quote for route.'); continue; } const routeWithValidQuote = new V2RouteWithValidQuote({ route, rawQuote: quote, amount, percent, gasModel: v2GasModel, quoteToken, tradeType, v2PoolProvider: this.v2PoolProvider, }); routesWithValidQuotes.push(routeWithValidQuote); } } return { routesWithValidQuotes, candidatePools, }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidjItcXVvdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3JvdXRlcnMvYWxwaGEtcm91dGVyL3F1b3RlcnMvdjItcXVvdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBbUIsU0FBUyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDdkUsT0FBTyxDQUFDLE1BQU0sUUFBUSxDQUFDO0FBRXZCLE9BQU8sRUFPTCxxQkFBcUIsR0FDdEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBR0wsR0FBRyxFQUNILE1BQU0sRUFDTixnQkFBZ0IsRUFDaEIsYUFBYSxHQUNkLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNwRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNyRSxPQUFPLEVBRUwsbUJBQW1CLEdBQ3BCLE1BQU0sa0NBQWtDLENBQUM7QUFHMUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUkzQyxNQUFNLE9BQU8sUUFBUyxTQUFRLFVBQW1CO0lBTS9DLFlBQ0Usa0JBQXVDLEVBQ3ZDLGNBQStCLEVBQy9CLGVBQWlDLEVBQ2pDLGlCQUFxQyxFQUNyQyxhQUE2QixFQUM3QixPQUFnQixFQUNoQix3QkFBNkMsRUFDN0Msc0JBQWdEO1FBRWhELEtBQUssQ0FDSCxhQUFhLEVBQ2IsT0FBTyxFQUNQLHdCQUF3QixFQUN4QixzQkFBc0IsQ0FDdkIsQ0FBQztRQUNGLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztRQUM3QyxJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUNyQyxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsaUJBQWlCLENBQUM7SUFDN0MsQ0FBQztJQUVTLEtBQUssQ0FBQyxT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