@xspswap/smart-order-router
Version:
XSwap Protocol V3 Smart Order Router
129 lines • 12.5 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.V3Quoter = void 0;
const router_sdk_1 = require("@x-swap-protocol/router-sdk");
const sdk_core_1 = require("@x-swap-protocol/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 get_candidate_pools_1 = require("../functions/get-candidate-pools");
const base_quoter_1 = require("./base-quoter");
class V3Quoter extends base_quoter_1.BaseQuoter {
constructor(v3SubgraphProvider, v3PoolProvider, onChainQuoteProvider, tokenProvider, chainId, protocol, blockedTokenListProvider, tokenValidatorProvider) {
super(tokenProvider, chainId, protocol, blockedTokenListProvider, tokenValidatorProvider);
this.v3SubgraphProvider = v3SubgraphProvider;
this.v3PoolProvider = v3PoolProvider;
this.onChainQuoteProvider = onChainQuoteProvider;
}
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 (0, get_candidate_pools_1.getV3CandidatePools)({
tokenIn,
tokenOut,
tokenProvider: this.tokenProvider,
blockedTokenListProvider: this.blockedTokenListProvider,
poolProvider: this.v3PoolProvider,
routeType: tradeType,
subgraphProvider: this.v3SubgraphProvider,
routingConfig,
chainId: this.chainId,
protocol: this.protocol === router_sdk_1.Protocol.V3 ? router_sdk_1.Protocol.V3 : router_sdk_1.Protocol.UNI_V3,
});
const poolsRaw = poolAccessor.getAllPools();
// Drop any pools that contain fee on transfer tokens (not supported by v3) or have issues with being transferred.
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.FOT ||
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.computeAllV3Routes)(tokenIn, tokenOut, pools, maxSwapsPerPath, this.protocol === router_sdk_1.Protocol.V3 ? router_sdk_1.Protocol.V3 : router_sdk_1.Protocol.UNI_V3);
return {
routes,
candidatePools,
};
}
async getQuotes(_routes, amounts, percents, quoteToken, tradeType, routingConfig, candidatePools, gasModel) {
const routes = _routes.filter((route) => route.protocol === this.protocol);
util_1.log.info('Starting to get V3 quotes');
if (gasModel === undefined) {
throw new Error('GasModel for V3RouteWithValidQuote 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 == sdk_core_1.TradeType.EXACT_INPUT
? this.onChainQuoteProvider.getQuotesManyExactIn.bind(this.onChainQuoteProvider)
: this.onChainQuoteProvider.getQuotesManyExactOut.bind(this.onChainQuoteProvider);
const beforeQuotes = Date.now();
util_1.log.info(`Getting quotes for V3 for ${routes.length} routes with ${amounts.length} amounts per route.`);
const { routesWithQuotes } = await quoteFn(amounts, routes, {
blockNumber: routingConfig.blockNumber,
});
util_1.metric.putMetric('V3QuotesLoad', Date.now() - beforeQuotes, util_1.MetricLoggerUnit.Milliseconds);
util_1.metric.putMetric('V3QuotesFetched', (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, sqrtPriceX96AfterList, initializedTicksCrossedList, gasEstimate, } = amountQuote;
if (!quote ||
!sqrtPriceX96AfterList ||
!initializedTicksCrossedList ||
!gasEstimate) {
util_1.log.debug({
route: (0, util_1.routeToString)(route),
amountQuote,
}, 'Dropping a null V3 quote for route.');
continue;
}
const routeWithValidQuote = new entities_1.V3RouteWithValidQuote({
route,
rawQuote: quote,
amount,
percent,
sqrtPriceX96AfterList,
initializedTicksCrossedList,
quoterGasEstimate: gasEstimate,
gasModel,
quoteToken,
tradeType,
v3PoolProvider: this.v3PoolProvider,
protocol: this.protocol === router_sdk_1.Protocol.V3 ? router_sdk_1.Protocol.V3 : router_sdk_1.Protocol.UNI_V3,
});
routesWithValidQuotes.push(routeWithValidQuote);
}
}
return {
routesWithValidQuotes,
candidatePools,
};
}
}
exports.V3Quoter = V3Quoter;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidjMtcXVvdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3JvdXRlcnMvYWxwaGEtcm91dGVyL3F1b3RlcnMvdjMtcXVvdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDREQUF1RDtBQUN2RCx3REFBZ0Y7QUFDaEYsb0RBQXVCO0FBRXZCLGtEQVE0QjtBQUM1Qix3Q0FNdUI7QUFHdkIsMENBQW9EO0FBQ3BELHdFQUFxRTtBQUNyRSwwRUFHMEM7QUFHMUMsK0NBQTJDO0FBSTNDLE1BQWEsUUFBUyxTQUFRLHdCQUFtQjtJQUsvQyxZQUNFLGtCQUF1QyxFQUN2QyxjQUErQixFQUMvQixvQkFBMkMsRUFDM0MsYUFBNkIsRUFDN0IsT0FBZ0IsRUFDaEIsUUFBdUMsRUFDdkMsd0JBQTZDLEVBQzdDLHNCQUFnRDtRQUVoRCxLQUFLLENBQ0gsYUFBYSxFQUNiLE9BQU8sRUFDUCxRQUFRLEVBQ1Isd0JBQXdCLEVBQ3hCLHNCQUFzQixDQUN2QixDQUFDO1FBQ0YsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFDO1FBQzdDLElBQUksQ0FBQyxjQUFjLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxvQkFBb0IsQ0FBQztJQUNuRCxDQUFDO0lBRVMsS0FBSyxDQUFDLFNBQVMsQ0FDdkIsT0FBYyxFQUNkLFFBQWUsRUFDZixTQUFvQixFQUNwQixhQUFnQztRQUVoQyw2RUFBNkU7UUFDN0UsOEVBQThFO1FBQzlFLHlCQUF5QjtRQUN6QixNQUFNLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxHQUFHLE1BQU0sSUFBQSx5Q0FBbUIsRUFBQztZQUNqRSxPQUFPO1lBQ1AsUUFBUTtZQUNSLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtZQUNqQyx3QkFBd0IsRUFBRSxJQUFJLENBQUMsd0JBQXdCO1lBQ3ZELFlBQVksRUFBRSxJQUFJLENBQUMsY0FBYztZQUNqQyxTQUFT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