@hikaru-fi/swap-router
Version:
Package for calculating optimal path for executing swaps
144 lines (131 loc) • 4.02 kB
JavaScript
const { toBN } = require("web3-utils");
const { WeightedPool } = require ("../poolMath/weightedPool/weightedPool");
const { SwapTypes } = require ("../utils/types");
const { getPoolsOfInterest } = require ("./filtering");
const ZERO = toBN(0);
/**
* @typedef SwapPath
* @property {String} poolAddress
* @property {String} vaultAddress
* @property {String} tokenIn
* @property {String} tokenOut
*/
/**
* @typedef SwapRoute
* @property {SwapPath[]} path
*/
/**
* @param {WeightedPool} pool
* @param {String} tokenIn
* @param {String} tokenOut
* @returns {SwapRoute}
*/
function getSwapPath(
pool,
tokenIn,
tokenOut
) {
return {
path: [{
poolAddress: pool.address,
vaultAddress: pool.vaultAddress,
tokenIn,
tokenOut
}]
}
}
/**
*
* @param {WeightedPool[]} pools
* @param {String[]} tokens
* @returns {SwapRoute}
*/
function createMultipleSwapsPath(
pools,
tokens
) {
const firstPool = pools[0]; const secondPool = pools[1];
const tokenIn = tokens[0]; const hopToken = tokens[1]; const tokenOut = tokens[2];
return {
path: [{
poolAddress: firstPool.address,
vaultAddress: firstPool.vaultAddress,
tokenIn,
tokenOut: hopToken
}, {
poolAddress: secondPool.address,
vaultAddress: secondPool.vaultAddress,
tokenIn: hopToken,
tokenOut
}]
}
}
/**
*
* @param {import("./poolCache").PoolDictionary} pools
* @param {String} tokenIn
* @param {String} tokenOut
* @param {BN} amountIn
* @returns {SwapRoute[][]}
*/
function producePaths(
pools,
tokenIn,
tokenOut
) {
const [direct, hopsIn, hopsOut] = getPoolsOfInterest(pools, tokenIn, tokenOut);
const directPaths = [];
for (const poolAddress in direct) {
directPaths.push(
getSwapPath(direct[poolAddress][0], tokenIn, tokenOut)
);
}
const hopPaths = [];
for (const hopToken in hopsIn) {
if (hopsOut[hopToken]) {
let highestNormalizedLiquidityFirst = ZERO;
let highestNormalizedLiquidityFirstPool = undefined;
let highestNormalizedLiqiuditySecond = ZERO;
let highestNormalizedLiquiditySecondPool = undefined;
for (const poolIn of hopsIn[hopToken]) {
const normalizedLiquidity = poolIn.getNormalizedLiquidity(tokenIn, hopToken);
if (
normalizedLiquidity.gte(
highestNormalizedLiquidityFirst
)
) {
highestNormalizedLiquidityFirst = normalizedLiquidity;
highestNormalizedLiquidityFirstPool = poolIn;
}
}
for (const poolOut of hopsOut[hopToken]) {
const normalizedLiquidity = poolOut.getNormalizedLiquidity(hopToken, tokenOut);
if (
normalizedLiquidity.gte(
highestNormalizedLiqiuditySecond
)
) {
highestNormalizedLiqiuditySecond = normalizedLiquidity;
highestNormalizedLiquiditySecondPool = poolOut;
}
}
if (
!!highestNormalizedLiquidityFirstPool &&
!!highestNormalizedLiquiditySecondPool
) {
hopPaths.push(
createMultipleSwapsPath(
[highestNormalizedLiquidityFirstPool, highestNormalizedLiquiditySecondPool],
[tokenIn, hopToken, tokenOut]
)
)
}
}
}
return [directPaths, hopPaths];
}
module.exports = {
getSwapPath,
createMultipleSwapsPath,
producePaths
}