@uniswap/smart-order-router
Version:
Uniswap Smart Order Router
140 lines • 14.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.V2Quoter = void 0;
const router_sdk_1 = require("@uniswap/router-sdk");
const sdk_core_1 = require("@uniswap/sdk-core");
const lodash_1 = __importDefault(require("lodash"));
const providers_1 = require("../../../providers");
const util_1 = require("../../../util");
const entities_1 = require("../entities");
const compute_all_routes_1 = require("../functions/compute-all-routes");
const gas_costs_1 = require("../gas-models/gas-costs");
const base_quoter_1 = require("./base-quoter");
class V2Quoter extends base_quoter_1.BaseQuoter {
constructor(v2SubgraphProvider, v2PoolProvider, v2QuoteProvider, v2GasModelFactory, tokenProvider, chainId, blockedTokenListProvider, tokenValidatorProvider, l2GasDataProvider) {
super(tokenProvider, chainId, router_sdk_1.Protocol.V2, blockedTokenListProvider, tokenValidatorProvider);
this.v2SubgraphProvider = v2SubgraphProvider;
this.v2PoolProvider = v2PoolProvider;
this.v2QuoteProvider = v2QuoteProvider;
this.v2GasModelFactory = v2GasModelFactory;
this.l2GasDataProvider = l2GasDataProvider;
}
async getRoutes(tokenIn, tokenOut, v2CandidatePools, _tradeType, routingConfig) {
const beforeGetRoutes = Date.now();
// 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 } = v2CandidatePools;
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 == providers_1.TokenValidationResult.STF &&
(token.equals(tokenIn) || token.equals(tokenOut))) {
return false;
}
return tokenValidation == providers_1.TokenValidationResult.STF;
});
// Given all our candidate pools, compute all the possible ways to route from tokenIn to tokenOut.
const { maxSwapsPerPath } = routingConfig;
const routes = (0, compute_all_routes_1.computeAllV2Routes)(tokenIn, tokenOut, pools, maxSwapsPerPath);
util_1.metric.putMetric('V2GetRoutesLoad', Date.now() - beforeGetRoutes, util_1.MetricLoggerUnit.Milliseconds);
return {
routes,
candidatePools,
};
}
async getQuotes(routes, amounts, percents, quoteToken, tradeType, _routingConfig, candidatePools, _gasModel, gasPriceWei) {
const beforeGetQuotes = Date.now();
util_1.log.info('Starting to get V2 quotes');
if (gasPriceWei === undefined) {
throw new Error('GasPriceWei for V2Routes is required to getQuotes');
}
// throw if we have no amounts or if there are different tokens in the amounts
if (amounts.length == 0 ||
!amounts.every((amount) => amount.currency.equals(amounts[0].currency))) {
throw new Error('Amounts must have at least one amount and must be same token');
}
// safe to force unwrap here because we throw if there are no amounts
const amountToken = amounts[0].currency;
const gasToken = _routingConfig.gasToken
? (await this.tokenProvider.getTokens([_routingConfig.gasToken])).getTokenByAddress(_routingConfig.gasToken)
: undefined;
if (routes.length == 0) {
return { routesWithValidQuotes: [], candidatePools };
}
// For all our routes, and all the fractional amounts, fetch quotes on-chain.
const quoteFn = tradeType == sdk_core_1.TradeType.EXACT_INPUT
? this.v2QuoteProvider.getQuotesManyExactIn.bind(this.v2QuoteProvider)
: this.v2QuoteProvider.getQuotesManyExactOut.bind(this.v2QuoteProvider);
const beforeQuotes = Date.now();
util_1.log.info(`Getting quotes for V2 for ${routes.length} routes with ${amounts.length} amounts per route.`);
const { routesWithQuotes } = await quoteFn(amounts, routes, _routingConfig);
const v2GasModel = await this.v2GasModelFactory.buildGasModel({
chainId: this.chainId,
gasPriceWei,
poolProvider: this.v2PoolProvider,
token: quoteToken,
l2GasDataProvider: this.l2GasDataProvider,
providerConfig: Object.assign(Object.assign({}, _routingConfig), { additionalGasOverhead: (0, gas_costs_1.NATIVE_OVERHEAD)(this.chainId, amountToken, quoteToken), gasToken }),
});
util_1.metric.putMetric('V2QuotesLoad', Date.now() - beforeQuotes, util_1.MetricLoggerUnit.Milliseconds);
util_1.metric.putMetric('V2QuotesFetched', (0, lodash_1.default)(routesWithQuotes)
.map(([, quotes]) => quotes.length)
.sum(), util_1.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) {
util_1.log.debug({
route: (0, util_1.routeToString)(route),
amountQuote,
}, 'Dropping a null V2 quote for route.');
continue;
}
const routeWithValidQuote = new entities_1.V2RouteWithValidQuote({
route,
rawQuote: quote,
amount,
percent,
gasModel: v2GasModel,
quoteToken,
tradeType,
v2PoolProvider: this.v2PoolProvider,
});
routesWithValidQuotes.push(routeWithValidQuote);
}
}
util_1.metric.putMetric('V2GetQuotesLoad', Date.now() - beforeGetQuotes, util_1.MetricLoggerUnit.Milliseconds);
return {
routesWithValidQuotes,
candidatePools,
};
}
async refreshRoutesThenGetQuotes(tokenIn, tokenOut, routes, amounts, percents, quoteToken, tradeType, routingConfig, gasPriceWei) {
const tokenPairs = [];
routes.forEach((route) => route.pairs.forEach((pair) => tokenPairs.push([pair.token0, pair.token1])));
return this.v2PoolProvider
.getPools(tokenPairs, routingConfig)
.then((poolAccesor) => {
const routes = (0, compute_all_routes_1.computeAllV2Routes)(tokenIn, tokenOut, poolAccesor.getAllPools(), routingConfig.maxSwapsPerPath);
return this.getQuotes(routes, amounts, percents, quoteToken, tradeType, routingConfig, undefined, undefined, gasPriceWei);
});
}
}
exports.V2Quoter = V2Quoter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidjItcXVvdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3JvdXRlcnMvYWxwaGEtcm91dGVyL3F1b3RlcnMvdjItcXVvdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBLG9EQUErQztBQUMvQyxnREFBd0U7QUFDeEUsb0RBQXVCO0FBRXZCLGtEQVE0QjtBQUs1Qix3Q0FNdUI7QUFHdkIsMENBQW9EO0FBQ3BELHdFQUFxRTtBQU1yRSx1REFBMEQ7QUFFMUQsK0NBQTJDO0FBSTNDLE1BQWEsUUFBUyxTQUFRLHdCQUE0QztJQU94RSxZQUNFLGtCQUF1QyxFQUN2QyxjQUErQixFQUMvQixlQUFpQyxFQUNqQyxpQkFBcUMsRUFDckMsYUFBNkIsRUFDN0IsT0FBZ0IsRUFDaEIsd0JBQTZDLEVBQzdDLHNCQUFnRCxFQUNoRCxpQkFBdUQ7UUFFdkQsS0FBSyxDQUNILGFBQWEsRUFDYixPQUFPLEVBQ1AscUJBQVEsQ0FBQyxFQUFFLEVBQ1gsd0JBQXdCLEVBQ3hCLHNCQUFzQixDQUN2QixDQUFDO1FBQ0YsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFDO1FBQzdDLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxlQUFlLEdBQUcsZUFBZSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztRQUMzQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsaUJBQWlCLENBQUM7SUFDN0MsQ0FBQztJQUVTLEtBQUssQ0FBQyxTQUFTLENBQ3ZCLE9BQWMsRUFDZCxRQUFlLEVBQ2YsZ0JBQWtDLEVBQ2xDLFVBQXFCLEVBQ3JCLGFBQWdDO1FBRWhDLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNuQyw2RUFBNkU7UUFDN0UsOEVBQThFO1FBQzlFLHlCQUF5QjtRQUN6QixNQUFNLEVBQUUsWUFBWSxFQUFFLGNBQWMs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