UNPKG

@hikaru-fi/swap-router

Version:

Package for calculating optimal path for executing swaps

150 lines (134 loc) 4.14 kB
const BN = require("bn.js"); const { toBN } = require("web3-utils"); const { WeightedPool } = require("../poolMath/weightedPool/weightedPool"); const { SwapTypes, getSwapType } = require("../utils/types"); const MAX_UINT256 = toBN(2).pow(toBN(256)).sub(toBN(1)) /** * @typedef VirtualSwapInfo * @property {String} pool * @property {String} tokenIn * @property {String} tokenOut */ /** * @typedef RouteInfo * @property {String} vault * @property {VirtualSwapInfo[]} swapRoute * @property {Number} swapType * @property {String} swapAmount * @property {String} minMaxAmount * @property {String} receiver * @property {String} deadline */ /** * @typedef SwapData * @property {BN} expectedResult * @property {RouteInfo} swapRoute */ /** * @param {Record<String, WeightedPool>} pools * @param {import("./pathCalculation").SwapRoute} swap * @param {BN} swapAmount * @param {String} swapType * @param {BN} expectedResult * @returns {SwapData} */ function createSwapData( pools, swap, swapAmount, swapType, expectedResult ) { swapAmount = swapAmount.toString(10); expectedResult = expectedResult.toString(10); /** * @type {RouteInfo} */ const swapRoute = { vault: pools[swap.path[0].poolAddress].vaultAddress, swapRoute: swap.path.map((val) => {return {pool: val.poolAddress, tokenIn: val.tokenIn, tokenOut: val.tokenOut}}), swapType: getSwapType(swapType), swapAmount, minMaxAmount: '0', receiver: '', deadline: '' } return { expectedResult, swapRoute } } /** * @typedef BestSwapResults * @property {BN} expectedResult * @property {import("./pathCalculation").SwapRoute} path */ /** * @param {Record<String, WeightedPool>} pools * @param {import("./pathCalculation").SwapRoute[]} suitableSwaps * @param {BN} swapAmount * @param {String} swapType * @returns {BestSwapResults} */ function getBestSwap(pools, suitableSwaps, swapAmount, swapType) { const sell = swapType == SwapTypes.Sell; /** * @type {BN} */ let resultAmount = sell ? toBN(0) : MAX_UINT256; /** * @type {import("./pathCalculation").SwapRoute} */ let resultPath; for (const route of suitableSwaps) { switch (swapType) { case (SwapTypes.Sell): { let amountIn = swapAmount.clone(); let amountOut = toBN(0); for (const swap of route.path) { const pool = pools[swap.poolAddress];; amountOut = pool.getSwapResult( swap.tokenIn, swap.tokenOut, amountIn, swapType ) amountIn = amountOut.clone(); } if (amountOut.gt(resultAmount)) { resultAmount = amountOut.clone(); resultPath = route; } break; } case (SwapTypes.Buy): { let amountIn = toBN(0); let amountOut = swapAmount.clone(); for (let swapId = route.path.length - 1; swapId >= 0; swapId--) { const swap = route.path[swapId]; const pool = pools[swap.poolAddress]; amountIn = pool.getSwapResult( swap.tokenIn, swap.tokenOut, amountOut, swapType ) amountOut = amountIn.clone(); } if (amountIn.lt(resultAmount)) { resultAmount = amountIn.clone(); resultPath = route; } break; } } } return { expectedResult: resultAmount, path: resultPath }; } module.exports = { createSwapData, getBestSwap }