@sameepsi/sor
Advanced tools
+1
-1
@@ -6,3 +6,3 @@ import { BigNumber } from './utils/bignumber'; | ||
| export declare function processEpsOfInterestMultiHop(sortedPaths: Path[], swapType: string, maxPools: number): EffectivePrice[]; | ||
| export declare const smartOrderRouterMultiHopEpsOfInterest: (pools: PoolDictionary, paths: Path[], swapType: string, totalSwapAmount: BigNumber, maxPools: number, costReturnToken: BigNumber, pricesOfInterest: EffectivePrice[]) => [Swap[][], BigNumber]; | ||
| export declare const smartOrderRouterMultiHopEpsOfInterest: (pools: PoolDictionary, paths: Path[], swapType: string, totalSwapAmount: BigNumber, maxPools: number, costReturnToken: BigNumber, pricesOfInterest: EffectivePrice[]) => [Swap[][], BigNumber, BigNumber]; | ||
| export declare const calcTotalReturn: (pools: PoolDictionary, paths: Path[], swapType: string, pathIds: string[], swapAmounts: BigNumber[]) => BigNumber; |
+39
-29
@@ -56,8 +56,8 @@ "use strict"; | ||
| function processEpsOfInterestMultiHop(sortedPaths, swapType, maxPools) { | ||
| // Given sortedPaths, this function builds the list of prices of interest | ||
| // wich is composed of all the spot prices of each of the paths and also | ||
| // all the swap prices, i.e. prices where the chart of spot price after trade vs. | ||
| // amount traded of any two pools cross. This means that up until that swap price | ||
| // Given sortedPaths, this function builds the list of prices of interest | ||
| // wich is composed of all the spot prices of each of the paths and also | ||
| // all the swap prices, i.e. prices where the chart of spot price after trade vs. | ||
| // amount traded of any two pools cross. This means that up until that swap price | ||
| // it's better to trade with one pool, but after that swap price it's better to trade with | ||
| // the other. | ||
| // the other. | ||
| let pricesOfInterest = getPricesOfInterest(sortedPaths, swapType); | ||
@@ -68,9 +68,9 @@ // Sort all prices of interest in ascending order | ||
| }); | ||
| // For each price of interest we calculate the list of best paths. | ||
| // This list is built based on the information of prices of interest where | ||
| // paths cross (i.e. one becomes better that the other). We only keep a list | ||
| // of up to maxPools pathIds as we know we won't ever need more than that | ||
| // since each path has at least one pool | ||
| // For each price of interest we calculate the list of best paths. | ||
| // This list is built based on the information of prices of interest where | ||
| // paths cross (i.e. one becomes better that the other). We only keep a list | ||
| // of up to maxPools pathIds as we know we won't ever need more than that | ||
| // since each path has at least one pool | ||
| pricesOfInterest = calculateBestPathIdsForPricesOfInterest(pricesOfInterest, maxPools); | ||
| // For each price of interest and list of best path ids, calculate how much | ||
| // For each price of interest and list of best path ids, calculate how much | ||
| // each of these paths would trade in order to get to that price of interest | ||
@@ -111,8 +111,8 @@ pricesOfInterest.forEach(poi => { | ||
| // First get the optimal totalReturn to trade 'totalSwapAmount' with | ||
| // one path only (b=1). Then increase the number of pools as long as | ||
| // improvementCondition is true (see more information below) | ||
| // one path only (b=1). Then increase the number of pools as long as | ||
| // improvementCondition is true (see more information below) | ||
| for (let b = 1; b <= bmin; b++) { | ||
| totalReturn = 0; | ||
| let priceBefore, swapAmountsPriceBefore, swapAmountsPriceAfter; | ||
| // Sweep all pricesOfInterest until we reach the amount we aim for (totalSwapAmount) | ||
| // Sweep all pricesOfInterest until we reach the amount we aim for (totalSwapAmount) | ||
| for (let i = 0; i < pricesOfInterest.length; i++) { | ||
@@ -127,3 +127,3 @@ if (i === 0) { | ||
| .reduce((a, b) => a.plus(b)); | ||
| // If totalInputAmountAfter is greater than totalSwapAmount we know | ||
| // If totalInputAmountAfter is greater than totalSwapAmount we know | ||
| // we found a solution to trade, now all we need to do is interpolate | ||
@@ -157,6 +157,6 @@ // between swapAmountsPriceBefore and swapAmountsPriceAfter | ||
| }); | ||
| // improvementCondition is true if we are improving the totalReturn | ||
| // Notice that totalReturn has to be maximized for 'swapExactIn' | ||
| // improvementCondition is true if we are improving the totalReturn | ||
| // Notice that totalReturn has to be maximized for 'swapExactIn' | ||
| // and MINIMIZED for 'swapExactOut' | ||
| // This is because for the case of 'swapExactOut', totalReturn means the | ||
| // This is because for the case of 'swapExactOut', totalReturn means the | ||
| // amount of tokenIn needed to buy totalSwapAmount of tokenOut | ||
@@ -283,3 +283,13 @@ let improvementCondition = false; | ||
| } | ||
| return [swaps, bestTotalReturn]; | ||
| // totalReturnConsideringFees is used to compare V1 vs V2 liquidity | ||
| // To consider the fact that V1 uses the exchangeProxy we should add a constant initial 150k gas | ||
| // as we want for our UI to clearly choose V2 if both V1 and V2 have exactly the same liquidity and both are using a single pair swap | ||
| // We currently have a swap cost set to 100k for V1 and to take the fees into account we use costOutputToken which is gasPrice * swapCost * tokenPriceWei | ||
| // So we use 1.5 * costOutputToken as the extra 150k gas. | ||
| let totalReturnWithFeesAndExtra; | ||
| if (swapType === 'swapExactIn') | ||
| totalReturnWithFeesAndExtra = bestTotalReturnConsideringFees.minus(bmath_1.bmul(new bignumber_1.BigNumber(1.5).times(bmath_1.BONE), costReturnToken)); | ||
| else | ||
| totalReturnWithFeesAndExtra = bestTotalReturnConsideringFees.plus(bmath_1.bmul(new bignumber_1.BigNumber(1.5).times(bmath_1.BONE), costReturnToken)); | ||
| return [swaps, bestTotalReturn, totalReturnWithFeesAndExtra]; | ||
| }; | ||
@@ -300,12 +310,12 @@ function getPricesOfInterest(sortedPaths, swapType) { | ||
| pricesOfInterest.push(pi); | ||
| // slippagePriceFactor is the slope of the chart for this path. | ||
| // Slippage (SL) has to be multiplied by spotPrice (SP) because | ||
| // slippagePriceFactor is the slope of the chart for this path. | ||
| // Slippage (SL) has to be multiplied by spotPrice (SP) because | ||
| // we have defined the linearized spot price after trade (SPaT) as: | ||
| // SPaT (A) = SP * (1 + SL * A) so if we want the slope we do: | ||
| // SPaT (A) = SP + SL*SP * A the slope is therefore SL * SP | ||
| // SPaT (A) = SP + SL*SP * A the slope is therefore SL * SP | ||
| path.slippagePriceFactor = bmath_1.bmul(path.slippage, path.spotPrice); | ||
| // Now we have to check if this path we just added will cross with other | ||
| // previously added paths. For that we need to run a for loop with all the | ||
| // previously added paths. For that we need to run a for loop with all the | ||
| // previous paths and analyse all the different possibilities of them crossing. | ||
| // A detailed explanation of each of the cases can be found here: | ||
| // A detailed explanation of each of the cases can be found here: | ||
| // https://drive.google.com/file/d/1vNWyfAMGtieWK6Vksj4oUJcOKF7FqanV/view | ||
@@ -316,4 +326,4 @@ for (let k = 0; k < i; k++) { | ||
| let prevSlippageFactor = prevPath.slippagePriceFactor; | ||
| // If the slippagePriceFactor of this path is less than that of the | ||
| // previous than they will cross at amountCross: | ||
| // If the slippagePriceFactor of this path is less than that of the | ||
| // previous than they will cross at amountCross: | ||
| if (path.slippagePriceFactor.isLessThan(prevSlippageFactor)) { | ||
@@ -326,3 +336,3 @@ let amountCross = bmath_1.bdiv(path.spotPrice.minus(prevPath.spotPrice), prevSlippageFactor.minus(path.slippagePriceFactor)); | ||
| epiA.price = path.spotPrice.plus(bmath_1.bmul(amountCross, path.slippagePriceFactor)); | ||
| // Add price of interest with the information of the paths ids | ||
| // Add price of interest with the information of the paths ids | ||
| // that are crossing in the format [demoted path, promoted path], | ||
@@ -354,4 +364,4 @@ // which means the first pathId is the one that's becoming worse after | ||
| else { | ||
| // This means the paths won't normally cross, so only case where | ||
| // this could happen is if the limitAmount of the previous path | ||
| // This means the paths won't normally cross, so only case where | ||
| // this could happen is if the limitAmount of the previous path | ||
| // is lower than that of this path | ||
@@ -358,0 +368,0 @@ if (prevPath.limitAmount.isLessThan(path.limitAmount)) { |
@@ -24,4 +24,4 @@ import { BaseProvider } from '@ethersproject/providers'; | ||
| fetchOnChainPools(SubgraphPools: SubGraphPools): Promise<Pools>; | ||
| getSwaps(TokenIn: string, TokenOut: string, SwapType: string, SwapAmt: BigNumber): Promise<[Swap[][], BigNumber, BigNumber]>; | ||
| processSwaps(TokenIn: string, TokenOut: string, SwapType: string, SwapAmt: BigNumber, OnChainPools: Pools, UserProcessCache?: boolean): Promise<[Swap[][], BigNumber, BigNumber]>; | ||
| getSwaps(TokenIn: string, TokenOut: string, SwapType: string, SwapAmt: BigNumber): Promise<[Swap[][], BigNumber, BigNumber, BigNumber]>; | ||
| processSwaps(TokenIn: string, TokenOut: string, SwapType: string, SwapAmt: BigNumber, OnChainPools: Pools, UserProcessCache?: boolean): Promise<[Swap[][], BigNumber, BigNumber, BigNumber]>; | ||
| fetchFilteredPairPools(TokenIn: string, TokenOut: string): Promise<boolean>; | ||
@@ -28,0 +28,0 @@ processPairPools(TokenIn: string, TokenOut: string, poolsList: any): [PoolDictionary, Path[]]; |
+27
-12
@@ -107,6 +107,11 @@ "use strict"; | ||
| TokenOut = TokenOut.toLowerCase(); | ||
| let swaps, total, marketSp; | ||
| let swaps, total, marketSp, totalConsideringFees; | ||
| if (this.isAllFetched) { | ||
| // All Pools with OnChain Balances is already fetched so use that | ||
| [swaps, total, marketSp] = yield this.processSwaps(TokenIn, TokenOut, SwapType, SwapAmt, this.onChainCache); | ||
| [ | ||
| swaps, | ||
| total, | ||
| marketSp, | ||
| totalConsideringFees, | ||
| ] = yield this.processSwaps(TokenIn, TokenOut, SwapType, SwapAmt, this.onChainCache); | ||
| } | ||
@@ -116,6 +121,11 @@ else { | ||
| if (!this.poolsForPairsCache[this.createKey(TokenIn, TokenOut)]) | ||
| return [[[]], bmath_1.bnum(0), bmath_1.bnum(0)]; | ||
| [swaps, total, marketSp] = yield this.processSwaps(TokenIn, TokenOut, SwapType, SwapAmt, this.poolsForPairsCache[this.createKey(TokenIn, TokenOut)], false); | ||
| return [[[]], bmath_1.bnum(0), bmath_1.bnum(0), bmath_1.bnum(0)]; | ||
| [ | ||
| swaps, | ||
| total, | ||
| marketSp, | ||
| totalConsideringFees, | ||
| ] = yield this.processSwaps(TokenIn, TokenOut, SwapType, SwapAmt, this.poolsForPairsCache[this.createKey(TokenIn, TokenOut)], false); | ||
| } | ||
| return [swaps, total, marketSp]; | ||
| return [swaps, total, marketSp, totalConsideringFees]; | ||
| }); | ||
@@ -128,3 +138,3 @@ } | ||
| if (OnChainPools.pools.length === 0) | ||
| return [[[]], bmath_1.bnum(0), bmath_1.bnum(0)]; | ||
| return [[[]], bmath_1.bnum(0), bmath_1.bnum(0), bmath_1.bnum(0)]; | ||
| let pools, paths, epsOfInterest, marketSp; | ||
@@ -158,4 +168,5 @@ // If token pair has been processed before that info can be reused to speed up execution | ||
| } | ||
| // Use previously stored value if exists else default to 0 | ||
| let costOutputToken = this.tokenCost[TokenOut]; | ||
| let costOutputToken = this.tokenCost[TokenOut.toLowerCase()]; | ||
| if (SwapType === 'swapExactOut') | ||
| costOutputToken = this.tokenCost[TokenIn.toLowerCase()]; | ||
| if (costOutputToken === undefined) { | ||
@@ -167,6 +178,10 @@ costOutputToken = new bignumber_1.BigNumber(0); | ||
| // swapExactOut - total = total amount of TokenIn required for swap | ||
| let swaps, total; | ||
| [swaps, total] = sor.smartOrderRouterMultiHopEpsOfInterest(JSON.parse(JSON.stringify(pools)), // Need to keep original pools for cache | ||
| let swaps, total, totalConsideringFees; | ||
| [ | ||
| swaps, | ||
| total, | ||
| totalConsideringFees, | ||
| ] = sor.smartOrderRouterMultiHopEpsOfInterest(JSON.parse(JSON.stringify(pools)), // Need to keep original pools for cache | ||
| paths, SwapType, SwapAmt, this.maxPools, costOutputToken, epsOfInterest); | ||
| return [swaps, total, marketSp]; | ||
| return [swaps, total, marketSp, totalConsideringFees]; | ||
| }); | ||
@@ -216,3 +231,3 @@ } | ||
| // Use previously stored value if exists else default to 0 | ||
| let costOutputToken = this.tokenCost[TokenOut]; | ||
| let costOutputToken = this.tokenCost[TokenOut.toLowerCase()]; | ||
| if (costOutputToken === undefined) { | ||
@@ -219,0 +234,0 @@ costOutputToken = new bignumber_1.BigNumber(0); |
+1
-1
| { | ||
| "name": "@sameepsi/sor", | ||
| "version": "1.0.0", | ||
| "version": "1.0.1", | ||
| "license": "GPL-3.0-only", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
159993
0.93%4250
0.59%8
14.29%