@xspswap/smart-order-router
Version:
XSwap Protocol V3 Smart Order Router
224 lines • 20.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StaticV3SubgraphProvider = exports.V3_XDC_ADDITIONAL_BASES = exports.ADDITIONAL_BASES = void 0;
const v3_sdk_1 = require("@x-swap-protocol/v3-sdk");
const jsbi_1 = __importDefault(require("jsbi"));
const lodash_1 = __importDefault(require("lodash"));
const amounts_1 = require("../../util/amounts");
const chains_1 = require("../../util/chains");
const log_1 = require("../../util/log");
const token_provider_1 = require("../token-provider");
const BASES_TO_CHECK_TRADES_AGAINST = {
[chains_1.ChainId.XDC]: [chains_1.WRAPPED_NATIVE_CURRENCY[chains_1.ChainId.XDC], token_provider_1.USDC_XDC],
[chains_1.ChainId.XDC_APOTHEM]: [
chains_1.WRAPPED_NATIVE_CURRENCY[chains_1.ChainId.XDC_APOTHEM],
token_provider_1.USDT_XDC_APOTHEM,
token_provider_1.WBTC_XDC_APOTHEM,
],
};
exports.ADDITIONAL_BASES = {
[chains_1.ChainId.XDC]: {
[chains_1.WRAPPED_NATIVE_CURRENCY[chains_1.ChainId.XDC].address]: [
[token_provider_1.DOPU_XDC, v3_sdk_1.FeeAmount.LOWEST],
[token_provider_1.USDC_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.GAMA_XDC, v3_sdk_1.FeeAmount.LOWEST],
[token_provider_1.LBT_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.CHUPAV2_XDC, v3_sdk_1.FeeAmount.HIGH],
[token_provider_1.BBB_XDC, v3_sdk_1.FeeAmount.LOWEST],
[token_provider_1.XSP_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.ROXN_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.GLL_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.PLI_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.FXD_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.PWM3_XDC, v3_sdk_1.FeeAmount.HIGH],
[token_provider_1.SRX_XDC, v3_sdk_1.FeeAmount.MEDIUM],
],
[token_provider_1.DOPU_XDC.address]: [
[token_provider_1.WXDC_XDC, v3_sdk_1.FeeAmount.LOWEST],
[token_provider_1.BBB_XDC, v3_sdk_1.FeeAmount.MEDIUM],
],
[token_provider_1.USDC_XDC.address]: [
[token_provider_1.WXDC_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.SRX_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.GAMA_XDC, v3_sdk_1.FeeAmount.LOWEST],
[token_provider_1.CGO_XDC, v3_sdk_1.FeeAmount.MEDIUM],
],
[token_provider_1.SRX_XDC.address]: [
[token_provider_1.USDC_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.WXDC_XDC, v3_sdk_1.FeeAmount.MEDIUM],
],
[token_provider_1.GAMA_XDC.address]: [
[token_provider_1.WXDC_XDC, v3_sdk_1.FeeAmount.LOWEST],
[token_provider_1.USDC_XDC, v3_sdk_1.FeeAmount.LOWEST],
],
[token_provider_1.BBB_XDC.address]: [
[token_provider_1.WXDC_XDC, v3_sdk_1.FeeAmount.LOWEST],
[token_provider_1.WXDC_XDC, v3_sdk_1.FeeAmount.HIGH],
],
[token_provider_1.CGO_XDC.address]: [
[token_provider_1.USDC_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.FXD_XDC, v3_sdk_1.FeeAmount.LOW],
],
[token_provider_1.XSP_XDC.address]: [
[token_provider_1.WXDC_XDC, v3_sdk_1.FeeAmount.MEDIUM],
[token_provider_1.USDC_XDC, v3_sdk_1.FeeAmount.MEDIUM],
],
},
[chains_1.ChainId.XDC_APOTHEM]: {},
};
exports.V3_XDC_ADDITIONAL_BASES = exports.ADDITIONAL_BASES[chains_1.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 = exports.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, Object.assign(Object.assign({}, 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
*/
class StaticV3SubgraphProvider {
constructor(chainId, poolProvider) {
this.chainId = chainId;
this.poolProvider = poolProvider;
}
async getPools(tokenIn, tokenOut) {
paths = [];
log_1.log.info('In static subgraph provider for V3');
const bases = BASES_TO_CHECK_TRADES_AGAINST[this.chainId];
const basePairs = lodash_1.default.flatMap(bases, (base) => bases.map((otherBase) => [base, otherBase]));
let pairs = [];
if (tokenIn && tokenOut) {
const additionalIn = exports.ADDITIONAL_BASES[this.chainId][tokenIn.address];
const additionalOut = exports.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 = (0, lodash_1.default)(basePairs)
.filter((tokens) => Boolean(tokens[0] && tokens[1]))
.filter(([tokenA, tokenB]) => tokenA.address !== tokenB.address && !tokenA.equals(tokenB))
.flatMap(([tokenA, tokenB]) => {
const additionalA = exports.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, v3_sdk_1.FeeAmount.LOWEST],
[tokenA, tokenB, v3_sdk_1.FeeAmount.LOW],
[tokenA, tokenB, v3_sdk_1.FeeAmount.MEDIUM],
[tokenA, tokenB, v3_sdk_1.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, v3_sdk_1.FeeAmount.LOWEST],
[tokenIn, tokenOut, v3_sdk_1.FeeAmount.LOW],
[tokenIn, tokenOut, v3_sdk_1.FeeAmount.MEDIUM],
[tokenIn, tokenOut, v3_sdk_1.FeeAmount.HIGH],
]
: [];
pairs = [...Object.values(uniquePairs), ...direct];
}
}
log_1.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 = (0, lodash_1.default)(pools)
.map((pool) => {
const { token0, token1, fee, liquidity } = pool;
const poolAddress = v3_sdk_1.Pool.getAddress(pool.token0, pool.token1, pool.fee);
if (poolAddressSet.has(poolAddress)) {
return undefined;
}
poolAddressSet.add(poolAddress);
const liquidityNumber = jsbi_1.default.toNumber(liquidity);
return {
id: poolAddress,
feeTier: (0, amounts_1.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;
}
}
exports.StaticV3SubgraphProvider = StaticV3SubgraphProvider;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLXN1YmdyYXBoLXByb3ZpZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3Byb3ZpZGVycy92My9zdGF0aWMtc3ViZ3JhcGgtcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBRUEsb0RBQTBEO0FBQzFELGdEQUF3QjtBQUN4QixvREFBdUI7QUFFdkIsZ0RBQXNEO0FBQ3RELDhDQUFxRTtBQUNyRSx3Q0FBcUM7QUFDckMsc0RBa0IyQjtBQVMzQixNQUFNLDZCQUE2QixHQUFtQjtJQUNwRCxDQUFDLGdCQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxnQ0FBdUIsQ0FBQyxnQkFBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLHlCQUFRLENBQUM7SUFDL0QsQ0FBQyxnQkFBTyxDQUFDLFdBQVcsQ0FBQyxFQUFFO1FBQ3JCLGdDQUF1QixDQUFDLGdCQUFPLENBQUMsV0FBVyxDQUFDO1FBQzVDLGlDQUFnQjtRQUNoQixpQ0FBZ0I7S0FDakI7Q0FDRixDQUFDO0FBRVcsUUFBQSxnQkFBZ0IsR0FFekI7SUFDRixDQUFDLGdCQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7UUFDYixDQUFDLGdDQUF1QixDQUFDLGdCQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDOUMsQ0FBQyx5QkFBUSxFQUFFLGtCQUFTLENBQUMsTUFBTSxDQUFDO1lBQzVCLENBQUMseUJBQVEsRUFBRSxrQkFBUyxDQUFDLE1BQU0sQ0FBQztZQUM1QixDQUFDLHlCQUFRLEVBQUUsa0JBQVMsQ0FBQyxNQUFNLENBQUM7WUFDNUIsQ0FBQyx3QkFBTyxFQUFFLGtCQUFTLENBQUMsTUFBTSxDQUFDO1lBQzNCLENBQUMsNEJBQVcsRUFBRSxrQkFBUyxDQUFDLElBQUksQ0FBQztZQUM3QixDQUFDLHdCQUFPLEVBQUUsa0JBQVMsQ0FBQyxNQUFNLENBQUM7WUFDM0IsQ0FBQyx3QkFBTyxFQUFFLGtCQUFTLENB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