@marko00/routing-finder-mare 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/copilot.data.migration.agent.xml +6 -0
- package/.idea/copilot.data.migration.ask.xml +6 -0
- package/.idea/copilot.data.migration.ask2agent.xml +6 -0
- package/.idea/copilot.data.migration.edit.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/php.xml +19 -0
- package/.idea/ratex-sdk.iml +8 -0
- package/.idea/vcs.xml +6 -0
- package/LICENSE-MIT +21 -0
- package/README.md +209 -0
- package/contracts/abi/BalancerHelperAbi.ts +1 -0
- package/contracts/abi/CamelotHelperAbi.ts +1 -0
- package/contracts/abi/RateXAbi.ts +482 -0
- package/contracts/abi/SushiSwapHelperAbi.ts +1 -0
- package/contracts/abi/UniswapHelperAbi.ts +1 -0
- package/contracts/abi/UniswapV2HelperAbi.ts +1 -0
- package/contracts/addresses-arbitrum.ts +8 -0
- package/contracts/addresses-mainnet.ts +7 -0
- package/contracts/addresses-polkadot.ts +9 -0
- package/contracts/addresses-sei.ts +9 -0
- package/contracts/rateX/BalancerHelper.ts +13 -0
- package/contracts/rateX/CamelotHelper.ts +13 -0
- package/contracts/rateX/SushiSwapHelper.ts +13 -0
- package/contracts/rateX/UniswapHelper.ts +19 -0
- package/contracts/rateX/UniswapV2Helper.ts +19 -0
- package/dexes/dexIdsList.ts +9 -0
- package/dexes/graph_queries/BalancerV2.ts +150 -0
- package/dexes/graph_queries/CamelotV2.ts +202 -0
- package/dexes/graph_queries/SushiSwapV2.ts +283 -0
- package/dexes/graph_queries/UniswapV2.ts +252 -0
- package/dexes/graph_queries/UniswapV3.ts +229 -0
- package/dexes/graph_queries/graphQueryFilters.ts +41 -0
- package/dexes/graph_queries/x_template.ts +67 -0
- package/dexes/pools/Balancer/BalancerState.ts +34 -0
- package/dexes/pools/Balancer/BalancerWeightedPool.ts +96 -0
- package/dexes/pools/Camelot.ts +164 -0
- package/dexes/pools/SushiSwapV2.ts +35 -0
- package/dexes/pools/UniswapV2.ts +36 -0
- package/dexes/pools/uniswap/UniswapV3.ts +40 -0
- package/dexes/pools/uniswap/testUniswapOffchainQuoter.ts +169 -0
- package/dexes/pools/uniswap/types.ts +174 -0
- package/dexes/pools/uniswap/uniswapOffchainQuoter.ts +173 -0
- package/dexes/pools/uniswap/uniswapState.ts +56 -0
- package/dexes/pools/uniswap/utils.ts +71 -0
- package/dist/contracts/abi/BalancerHelperAbi.d.ts +25 -0
- package/dist/contracts/abi/BalancerHelperAbi.js +4 -0
- package/dist/contracts/abi/CamelotHelperAbi.d.ts +45 -0
- package/dist/contracts/abi/CamelotHelperAbi.js +4 -0
- package/dist/contracts/abi/RateXAbi.d.ts +71 -0
- package/dist/contracts/abi/RateXAbi.js +485 -0
- package/dist/contracts/abi/SushiSwapHelperAbi.d.ts +45 -0
- package/dist/contracts/abi/SushiSwapHelperAbi.js +4 -0
- package/dist/contracts/abi/UniswapHelperAbi.d.ts +39 -0
- package/dist/contracts/abi/UniswapHelperAbi.js +4 -0
- package/dist/contracts/abi/UniswapV2HelperAbi.d.ts +45 -0
- package/dist/contracts/abi/UniswapV2HelperAbi.js +4 -0
- package/dist/contracts/addresses-arbitrum.d.ts +6 -0
- package/dist/contracts/addresses-arbitrum.js +10 -0
- package/dist/contracts/addresses-mainnet.d.ts +6 -0
- package/dist/contracts/addresses-mainnet.js +10 -0
- package/dist/contracts/addresses-polkadot.d.ts +6 -0
- package/dist/contracts/addresses-polkadot.js +10 -0
- package/dist/contracts/addresses-sei.d.ts +6 -0
- package/dist/contracts/addresses-sei.js +10 -0
- package/dist/contracts/rateX/BalancerHelper.d.ts +26 -0
- package/dist/contracts/rateX/BalancerHelper.js +14 -0
- package/dist/contracts/rateX/CamelotHelper.d.ts +46 -0
- package/dist/contracts/rateX/CamelotHelper.js +14 -0
- package/dist/contracts/rateX/SushiSwapHelper.d.ts +46 -0
- package/dist/contracts/rateX/SushiSwapHelper.js +14 -0
- package/dist/contracts/rateX/UniswapHelper.d.ts +40 -0
- package/dist/contracts/rateX/UniswapHelper.js +22 -0
- package/dist/contracts/rateX/UniswapV2Helper.d.ts +46 -0
- package/dist/contracts/rateX/UniswapV2Helper.js +22 -0
- package/dist/dexes/dexIdsList.d.ts +9 -0
- package/dist/dexes/dexIdsList.js +12 -0
- package/dist/dexes/graph_queries/BalancerV2.d.ts +14 -0
- package/dist/dexes/graph_queries/BalancerV2.js +141 -0
- package/dist/dexes/graph_queries/CamelotV2.d.ts +14 -0
- package/dist/dexes/graph_queries/CamelotV2.js +183 -0
- package/dist/dexes/graph_queries/SushiSwapV2.d.ts +14 -0
- package/dist/dexes/graph_queries/SushiSwapV2.js +263 -0
- package/dist/dexes/graph_queries/UniswapV2.d.ts +14 -0
- package/dist/dexes/graph_queries/UniswapV2.js +217 -0
- package/dist/dexes/graph_queries/UniswapV3.d.ts +14 -0
- package/dist/dexes/graph_queries/UniswapV3.js +198 -0
- package/dist/dexes/graph_queries/graphQueryFilters.d.ts +19 -0
- package/dist/dexes/graph_queries/graphQueryFilters.js +40 -0
- package/dist/dexes/graph_queries/x_template.d.ts +12 -0
- package/dist/dexes/graph_queries/x_template.js +57 -0
- package/dist/dexes/pools/Balancer/BalancerState.d.ts +6 -0
- package/dist/dexes/pools/Balancer/BalancerState.js +32 -0
- package/dist/dexes/pools/Balancer/BalancerWeightedPool.d.ts +12 -0
- package/dist/dexes/pools/Balancer/BalancerWeightedPool.js +109 -0
- package/dist/dexes/pools/Camelot.d.ts +12 -0
- package/dist/dexes/pools/Camelot.js +135 -0
- package/dist/dexes/pools/SushiSwapV2.d.ts +9 -0
- package/dist/dexes/pools/SushiSwapV2.js +34 -0
- package/dist/dexes/pools/UniswapV2.d.ts +9 -0
- package/dist/dexes/pools/UniswapV2.js +34 -0
- package/dist/dexes/pools/uniswap/UniswapV3.d.ts +7 -0
- package/dist/dexes/pools/uniswap/UniswapV3.js +36 -0
- package/dist/dexes/pools/uniswap/types.d.ts +76 -0
- package/dist/dexes/pools/uniswap/types.js +111 -0
- package/dist/dexes/pools/uniswap/uniswapOffchainQuoter.d.ts +13 -0
- package/dist/dexes/pools/uniswap/uniswapOffchainQuoter.js +121 -0
- package/dist/dexes/pools/uniswap/uniswapState.d.ts +14 -0
- package/dist/dexes/pools/uniswap/uniswapState.js +51 -0
- package/dist/dexes/pools/uniswap/utils.d.ts +3 -0
- package/dist/dexes/pools/uniswap/utils.js +41 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +41 -0
- package/dist/routes.d.ts +1 -0
- package/dist/routes.js +20 -0
- package/dist/routing/iterative_spliting/main.d.ts +3 -0
- package/dist/routing/iterative_spliting/main.js +104 -0
- package/dist/routing/iterative_spliting/multiHopSwap.d.ts +4 -0
- package/dist/routing/iterative_spliting/multiHopSwap.js +83 -0
- package/dist/routing/main.d.ts +2 -0
- package/dist/routing/main.js +22 -0
- package/dist/routing/uni_like_algo/algo_config.d.ts +2 -0
- package/dist/routing/uni_like_algo/algo_config.js +8 -0
- package/dist/routing/uni_like_algo/amount_distribution.d.ts +2 -0
- package/dist/routing/uni_like_algo/amount_distribution.js +17 -0
- package/dist/routing/uni_like_algo/compute_routes_backtrack.d.ts +3 -0
- package/dist/routing/uni_like_algo/compute_routes_backtrack.js +44 -0
- package/dist/routing/uni_like_algo/main.d.ts +2 -0
- package/dist/routing/uni_like_algo/main.js +49 -0
- package/dist/routing/uni_like_algo/routes_quoter.d.ts +21 -0
- package/dist/routing/uni_like_algo/routes_quoter.js +53 -0
- package/dist/routing/uni_like_algo/swap_finder.d.ts +25 -0
- package/dist/routing/uni_like_algo/swap_finder.js +154 -0
- package/dist/routing/uni_like_algo/types.d.ts +40 -0
- package/dist/routing/uni_like_algo/types.js +12 -0
- package/dist/swap/graph_communication.d.ts +5 -0
- package/dist/swap/graph_communication.js +187 -0
- package/dist/swap/my_local_storage.d.ts +8 -0
- package/dist/swap/my_local_storage.js +16 -0
- package/dist/utils/addresses.d.ts +24 -0
- package/dist/utils/addresses.js +60 -0
- package/dist/utils/math/fixed-points.d.ts +14 -0
- package/dist/utils/math/fixed-points.js +123 -0
- package/dist/utils/math/log-exp.d.ts +5 -0
- package/dist/utils/math/log-exp.js +385 -0
- package/dist/utils/math/math.d.ts +12 -0
- package/dist/utils/math/math.js +50 -0
- package/dist/utils/types/types.d.ts +51 -0
- package/dist/utils/types/types.js +25 -0
- package/dist/utils/utils.d.ts +20 -0
- package/dist/utils/utils.js +72 -0
- package/images/decenter_logo.png +0 -0
- package/index.ts +50 -0
- package/package.json +39 -0
- package/routes.ts +27 -0
- package/routing/iterative_spliting/main.ts +131 -0
- package/routing/iterative_spliting/multiHopSwap.ts +98 -0
- package/routing/main.ts +22 -0
- package/routing/uni_like_algo/algo_config.ts +7 -0
- package/routing/uni_like_algo/amount_distribution.ts +16 -0
- package/routing/uni_like_algo/compute_routes_backtrack.ts +81 -0
- package/routing/uni_like_algo/main.ts +65 -0
- package/routing/uni_like_algo/routes_quoter.ts +63 -0
- package/routing/uni_like_algo/swap_finder.ts +185 -0
- package/routing/uni_like_algo/types.ts +54 -0
- package/swap/graph_communication.ts +212 -0
- package/swap/my_local_storage.ts +27 -0
- package/tsconfig.json +26 -0
- package/utils/addresses.ts +64 -0
- package/utils/math/fixed-points.ts +88 -0
- package/utils/math/log-exp.ts +469 -0
- package/utils/math/math.ts +46 -0
- package/utils/types/types.ts +100 -0
- package/utils/utils.ts +125 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
export class PoolInfo {
|
|
2
|
+
pool: string;
|
|
3
|
+
token0: string;
|
|
4
|
+
token1: string;
|
|
5
|
+
tick: bigint;
|
|
6
|
+
tickLiquidityNet: bigint;
|
|
7
|
+
tickSpacing: bigint;
|
|
8
|
+
fee: bigint;
|
|
9
|
+
sqrtPriceX96: bigint;
|
|
10
|
+
liquidity: bigint;
|
|
11
|
+
|
|
12
|
+
constructor(pool: string, token0: string, token1: string, tick: bigint, tickLiquidityNet: bigint, tickSpacing: bigint, fee: bigint, sqrtPriceX96: bigint, liquidity: bigint) {
|
|
13
|
+
this.pool = pool;
|
|
14
|
+
this.token0 = token0;
|
|
15
|
+
this.token1 = token1;
|
|
16
|
+
this.tick = tick;
|
|
17
|
+
this.tickLiquidityNet = tickLiquidityNet
|
|
18
|
+
this.tickSpacing = tickSpacing;
|
|
19
|
+
this.fee = fee;
|
|
20
|
+
this.sqrtPriceX96 = sqrtPriceX96;
|
|
21
|
+
this.liquidity = liquidity;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class TickData {
|
|
26
|
+
tick: bigint;
|
|
27
|
+
initialized: boolean;
|
|
28
|
+
liquidityNet: bigint;
|
|
29
|
+
|
|
30
|
+
clone() {
|
|
31
|
+
return new TickData(this.tick, this.initialized, this.liquidityNet);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
constructor(tick: bigint, initialized: boolean, liquidityNet: bigint) {
|
|
35
|
+
this.tick = tick;
|
|
36
|
+
this.initialized = initialized;
|
|
37
|
+
this.liquidityNet = liquidityNet;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class PoolData {
|
|
42
|
+
info: PoolInfo;
|
|
43
|
+
zeroForOneTicks: TickData[];
|
|
44
|
+
oneForZeroTicks: TickData[];
|
|
45
|
+
|
|
46
|
+
constructor(info: PoolInfo, zeroForOneTicks: TickData[], oneForZeroTicks: TickData[]) {
|
|
47
|
+
this.info = info;
|
|
48
|
+
this.zeroForOneTicks = zeroForOneTicks;
|
|
49
|
+
this.oneForZeroTicks = oneForZeroTicks;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type SwapState = {
|
|
54
|
+
amountSpecifiedRemaining: bigint,
|
|
55
|
+
amountCalculated: bigint,
|
|
56
|
+
sqrtPriceX96: bigint,
|
|
57
|
+
tick: bigint,
|
|
58
|
+
liquidity: bigint
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type StepComputations = {
|
|
62
|
+
sqrtPriceStartX96: bigint,
|
|
63
|
+
tickNext: bigint,
|
|
64
|
+
initialized: boolean,
|
|
65
|
+
sqrtPriceNextX96: bigint,
|
|
66
|
+
amountIn: bigint,
|
|
67
|
+
amountOut: bigint,
|
|
68
|
+
feeAmount: bigint
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
// helper used for test
|
|
73
|
+
export class TradeInfo {
|
|
74
|
+
pool: string;
|
|
75
|
+
tokenIn: string;
|
|
76
|
+
tokenOut: string;
|
|
77
|
+
amountIn: bigint;
|
|
78
|
+
fee: bigint;
|
|
79
|
+
|
|
80
|
+
constructor(pool: string, tokenIn: string, tokenOut: string, amountIn: bigint, fee: bigint) {
|
|
81
|
+
this.pool = pool;
|
|
82
|
+
this.tokenIn = tokenIn;
|
|
83
|
+
this.tokenOut = tokenOut;
|
|
84
|
+
this.amountIn = amountIn;
|
|
85
|
+
this.fee = fee;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class AdaptedPoolData {
|
|
90
|
+
pool: string;
|
|
91
|
+
token0: string;
|
|
92
|
+
token1: string;
|
|
93
|
+
tickSpacing: bigint;
|
|
94
|
+
fee: bigint;
|
|
95
|
+
currentLiquidity: bigint;
|
|
96
|
+
currentSqrtPriceX96: bigint;
|
|
97
|
+
ticks: TickData[];
|
|
98
|
+
|
|
99
|
+
currentTickIndex: number; // currenTick info is at ticks[currentTickIndex]
|
|
100
|
+
|
|
101
|
+
clone() {
|
|
102
|
+
const newData = new AdaptedPoolData(null);
|
|
103
|
+
newData.pool = this.pool;
|
|
104
|
+
newData.token0 = this.token0;
|
|
105
|
+
newData.token1 = this.token1;
|
|
106
|
+
newData.tickSpacing = this.tickSpacing;
|
|
107
|
+
newData.fee = this.fee;
|
|
108
|
+
newData.currentLiquidity = this.currentLiquidity;
|
|
109
|
+
newData.currentSqrtPriceX96 = this.currentSqrtPriceX96;
|
|
110
|
+
newData.ticks = this.ticks.map(e => e.clone());
|
|
111
|
+
newData.currentTickIndex = this.currentTickIndex;
|
|
112
|
+
return newData;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
constructor(poolData: PoolData | null) {
|
|
116
|
+
if (!poolData) {
|
|
117
|
+
this.pool = '';
|
|
118
|
+
this.token0 = '';
|
|
119
|
+
this.token1 = '';
|
|
120
|
+
this.tickSpacing = BigInt(0);
|
|
121
|
+
this.fee = BigInt(0);
|
|
122
|
+
this.currentLiquidity = BigInt(0);
|
|
123
|
+
this.currentSqrtPriceX96 = BigInt(0);
|
|
124
|
+
this.ticks = []
|
|
125
|
+
this.currentTickIndex = 0
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
this.pool = poolData.info.pool;
|
|
129
|
+
this.token0 = poolData.info.token0;
|
|
130
|
+
this.token1 = poolData.info.token1;
|
|
131
|
+
this.tickSpacing = poolData.info.tickSpacing;
|
|
132
|
+
this.fee = poolData.info.fee;
|
|
133
|
+
this.currentLiquidity = poolData.info.liquidity;
|
|
134
|
+
this.currentSqrtPriceX96 = poolData.info.sqrtPriceX96;
|
|
135
|
+
|
|
136
|
+
const currentTickData = new TickData(poolData.info.tick, true, poolData.info.tickLiquidityNet);
|
|
137
|
+
this.ticks = poolData.zeroForOneTicks.reverse().concat(currentTickData).concat(poolData.oneForZeroTicks);
|
|
138
|
+
this.currentTickIndex = poolData.zeroForOneTicks.length;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public getCurrTickData(): TickData {
|
|
142
|
+
return this.ticks[this.currentTickIndex];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export class LastQuote {
|
|
147
|
+
newLiquidity: bigint;
|
|
148
|
+
newSqrtPriceX96: bigint;
|
|
149
|
+
newTickIndex: number; // index in array of ticks
|
|
150
|
+
|
|
151
|
+
clone() {
|
|
152
|
+
return new LastQuote(this.newLiquidity, this.newSqrtPriceX96, this.newTickIndex)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
constructor(newLiquidity: bigint, newSqrtPriceX96: bigint, newTickIndex: number) {
|
|
156
|
+
this.newLiquidity = newLiquidity;
|
|
157
|
+
this.newSqrtPriceX96 = newSqrtPriceX96;
|
|
158
|
+
this.newTickIndex = newTickIndex;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export class PoolState {
|
|
163
|
+
data: AdaptedPoolData;
|
|
164
|
+
lastQuote: LastQuote;
|
|
165
|
+
|
|
166
|
+
clone() {
|
|
167
|
+
return new PoolState(this.data.clone(), this.lastQuote.clone())
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
constructor(currData: AdaptedPoolData, lastQuote: LastQuote) {
|
|
171
|
+
this.data = currData;
|
|
172
|
+
this.lastQuote = lastQuote;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { FeeAmount, LiquidityMath, SwapMath, TickMath } from "@uniswap/v3-sdk";
|
|
2
|
+
import JSBI from "jsbi";
|
|
3
|
+
import { LastQuote, PoolState, StepComputations, SwapState, TickData } from "./types";
|
|
4
|
+
|
|
5
|
+
export class UniswapOffchainQuoter {
|
|
6
|
+
|
|
7
|
+
public quote(
|
|
8
|
+
poolState: PoolState,
|
|
9
|
+
tokenIn: string,
|
|
10
|
+
tokenOut: string,
|
|
11
|
+
amountIn: bigint
|
|
12
|
+
): [bigint, bigint] {
|
|
13
|
+
|
|
14
|
+
if (amountIn <= BigInt(0)) {
|
|
15
|
+
return [BigInt(0), BigInt(0)];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const zeroForOne: boolean = tokenIn < tokenOut;
|
|
20
|
+
const sqrtPriceLimitX96 = this.getSqrtPriceLimitX96(zeroForOne);
|
|
21
|
+
|
|
22
|
+
let state: SwapState = this.initSwapState(poolState, amountIn);
|
|
23
|
+
|
|
24
|
+
let tickDataIndex = zeroForOne
|
|
25
|
+
? poolState.data.currentTickIndex - 1
|
|
26
|
+
: poolState.data.currentTickIndex + 1;
|
|
27
|
+
|
|
28
|
+
while (
|
|
29
|
+
state.amountSpecifiedRemaining !== BigInt(0) &&
|
|
30
|
+
state.sqrtPriceX96 !== sqrtPriceLimitX96 &&
|
|
31
|
+
tickDataIndex >= 0 &&
|
|
32
|
+
tickDataIndex < poolState.data.ticks.length
|
|
33
|
+
) {
|
|
34
|
+
const tickData = poolState.data.ticks[tickDataIndex];
|
|
35
|
+
|
|
36
|
+
let step: StepComputations = this.initStepComputations(state, tickData);
|
|
37
|
+
|
|
38
|
+
this.updateSwapIteration(state, step, tickData, poolState.data.fee, sqrtPriceLimitX96, zeroForOne);
|
|
39
|
+
|
|
40
|
+
tickDataIndex = zeroForOne ? tickDataIndex - 1 : tickDataIndex + 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// remember where we left off, so we can update pool later
|
|
44
|
+
poolState.lastQuote = new LastQuote(state.liquidity, state.sqrtPriceX96, zeroForOne ? tickDataIndex + 2 : tickDataIndex - 2)
|
|
45
|
+
|
|
46
|
+
const amountOut = state.amountCalculated > BigInt(0) ? state.amountCalculated : -state.amountCalculated;
|
|
47
|
+
return [amountOut, state.amountSpecifiedRemaining];
|
|
48
|
+
} catch (e) {
|
|
49
|
+
return [BigInt(0), BigInt(0)];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private initSwapState(poolState: PoolState, amountIn: bigint): SwapState {
|
|
54
|
+
return {
|
|
55
|
+
amountSpecifiedRemaining: amountIn,
|
|
56
|
+
amountCalculated: BigInt(0),
|
|
57
|
+
sqrtPriceX96: poolState.data.currentSqrtPriceX96,
|
|
58
|
+
tick: poolState.data.getCurrTickData().tick,
|
|
59
|
+
liquidity: poolState.data.currentLiquidity
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private initStepComputations(state: SwapState, tickData: TickData): StepComputations {
|
|
64
|
+
return {
|
|
65
|
+
sqrtPriceStartX96: state.sqrtPriceX96,
|
|
66
|
+
tickNext: tickData.tick,
|
|
67
|
+
initialized: tickData.initialized,
|
|
68
|
+
sqrtPriceNextX96: BigInt(TickMath.getSqrtRatioAtTick(Number(tickData.tick)).toString()),
|
|
69
|
+
amountIn: BigInt(0),
|
|
70
|
+
amountOut: BigInt(0),
|
|
71
|
+
feeAmount: BigInt(0)
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private convertToFeeAmount(fee: bigint): FeeAmount {
|
|
76
|
+
switch (fee.toString()) {
|
|
77
|
+
case "100":
|
|
78
|
+
return FeeAmount.LOWEST;
|
|
79
|
+
case "500":
|
|
80
|
+
return FeeAmount.LOW;
|
|
81
|
+
case "3000":
|
|
82
|
+
return FeeAmount.MEDIUM;
|
|
83
|
+
case "10000":
|
|
84
|
+
return FeeAmount.HIGH;
|
|
85
|
+
default:
|
|
86
|
+
throw new Error("Invalid fee amount");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private updateSwapIteration(
|
|
91
|
+
state: SwapState,
|
|
92
|
+
step: StepComputations,
|
|
93
|
+
tickData: TickData,
|
|
94
|
+
fee: bigint,
|
|
95
|
+
sqrtPriceLimitX96: bigint,
|
|
96
|
+
zeroForOne: boolean
|
|
97
|
+
) {
|
|
98
|
+
this.updateSwapStep(state, step, fee, sqrtPriceLimitX96, zeroForOne);
|
|
99
|
+
this.calculateAmount(state, step);
|
|
100
|
+
this.updateTickWithLiquidity(state, step, tickData, zeroForOne);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private updateSwapStep(
|
|
104
|
+
state: SwapState,
|
|
105
|
+
step: StepComputations,
|
|
106
|
+
fee: bigint,
|
|
107
|
+
sqrtPriceLimitX96: bigint,
|
|
108
|
+
zeroForOne: boolean
|
|
109
|
+
) {
|
|
110
|
+
const [sqrtPriceX96, amountIn, amountOut, feeAmount] =
|
|
111
|
+
SwapMath.computeSwapStep(
|
|
112
|
+
JSBI.BigInt(state.sqrtPriceX96.toString()),
|
|
113
|
+
this.calculateRatioTargetX96(zeroForOne, step.sqrtPriceNextX96, sqrtPriceLimitX96),
|
|
114
|
+
JSBI.BigInt(state.liquidity.toString()),
|
|
115
|
+
JSBI.BigInt(state.amountSpecifiedRemaining.toString()),
|
|
116
|
+
this.convertToFeeAmount(fee)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
state.sqrtPriceX96 = BigInt(sqrtPriceX96.toString());
|
|
120
|
+
step.amountIn = BigInt(amountIn.toString());
|
|
121
|
+
step.amountOut = BigInt(amountOut.toString());
|
|
122
|
+
step.feeAmount = BigInt(feeAmount.toString());
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private calculateAmount(state: SwapState, step: StepComputations) {
|
|
126
|
+
state.amountSpecifiedRemaining -= (step.amountIn + step.feeAmount);
|
|
127
|
+
state.amountCalculated -= step.amountOut;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private updateTickWithLiquidity(
|
|
131
|
+
state: SwapState,
|
|
132
|
+
step: StepComputations,
|
|
133
|
+
tickData: TickData,
|
|
134
|
+
zeroForOne: boolean
|
|
135
|
+
) {
|
|
136
|
+
if (state.sqrtPriceX96 === step.sqrtPriceNextX96) {
|
|
137
|
+
// if the tick is initialized, run the tick transition
|
|
138
|
+
if (step.initialized) {
|
|
139
|
+
let liquidityNet = tickData.liquidityNet;
|
|
140
|
+
// if we're moving leftward, we interpret liquidityNet as the opposite sign
|
|
141
|
+
if (zeroForOne) {
|
|
142
|
+
liquidityNet = -liquidityNet;
|
|
143
|
+
}
|
|
144
|
+
const finalLiquidity = LiquidityMath.addDelta(
|
|
145
|
+
JSBI.BigInt(state.liquidity.toString()),
|
|
146
|
+
JSBI.BigInt(liquidityNet.toString())
|
|
147
|
+
);
|
|
148
|
+
state.liquidity = BigInt(finalLiquidity.toString());
|
|
149
|
+
}
|
|
150
|
+
state.tick = zeroForOne ? step.tickNext - BigInt(1) : step.tickNext;
|
|
151
|
+
} else if (state.sqrtPriceX96 !== step.sqrtPriceStartX96) {
|
|
152
|
+
// recompute unless we're on a lower tick boundary (i.e. already transitioned ticks), and haven't moved
|
|
153
|
+
const tick = TickMath.getTickAtSqrtRatio(JSBI.BigInt(state.sqrtPriceX96.toString()));
|
|
154
|
+
state.tick = BigInt(tick.toString());
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private calculateRatioTargetX96(
|
|
159
|
+
zeroForOne: boolean,
|
|
160
|
+
sqrtPriceNextX96: bigint,
|
|
161
|
+
sqrtPriceLimitX96: bigint
|
|
162
|
+
): JSBI {
|
|
163
|
+
return (zeroForOne ? sqrtPriceNextX96 < sqrtPriceLimitX96 : sqrtPriceNextX96 > sqrtPriceLimitX96)
|
|
164
|
+
? JSBI.BigInt(sqrtPriceLimitX96.toString())
|
|
165
|
+
: JSBI.BigInt(sqrtPriceNextX96.toString());
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private getSqrtPriceLimitX96(zeroForOne: boolean): bigint {
|
|
169
|
+
return zeroForOne ?
|
|
170
|
+
BigInt(JSBI.add(TickMath.MIN_SQRT_RATIO, JSBI.BigInt("1")).toString()) :
|
|
171
|
+
BigInt(JSBI.subtract(TickMath.MAX_SQRT_RATIO, JSBI.BigInt("1")).toString());
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { PoolData, PoolState } from './types'
|
|
2
|
+
import { convertInitialPoolDataToPoolState, convertRowPoolData } from './utils'
|
|
3
|
+
import { UniswapOffchainQuoter } from './uniswapOffchainQuoter'
|
|
4
|
+
import { CreateUniswapHelperContract } from '../../../contracts/rateX/UniswapHelper'
|
|
5
|
+
import Web3 from 'web3'
|
|
6
|
+
|
|
7
|
+
export class UniswapState {
|
|
8
|
+
private static poolStateMap: Map<string, PoolState> = new Map<string, PoolState>()
|
|
9
|
+
private static startingPoolStateMap: Map<string, PoolState> = new Map<string, PoolState>()
|
|
10
|
+
public static quoter: UniswapOffchainQuoter = new UniswapOffchainQuoter()
|
|
11
|
+
private static batch_size = 3
|
|
12
|
+
|
|
13
|
+
private constructor() { }
|
|
14
|
+
|
|
15
|
+
public static getPoolState(poolAddress: string): PoolState | undefined {
|
|
16
|
+
return this.poolStateMap.get(poolAddress.toLowerCase())
|
|
17
|
+
}
|
|
18
|
+
public static resetPoolState(poolAddress: string): void {
|
|
19
|
+
const poolState = this.startingPoolStateMap.get(poolAddress.toLowerCase())
|
|
20
|
+
if (poolState) {
|
|
21
|
+
this.poolStateMap.set(poolAddress.toLowerCase(), poolState.clone())
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private static async getPoolsDataFromContract(pools: string[], chainId: number, rpcProvider: Web3): Promise<PoolData[]> {
|
|
26
|
+
//@ts-ignore
|
|
27
|
+
try {
|
|
28
|
+
const UniswapHelperContract = CreateUniswapHelperContract(chainId, rpcProvider)
|
|
29
|
+
const rawPoolsData: any[] = await UniswapHelperContract.methods.fetchData(pools, 15).call()
|
|
30
|
+
return rawPoolsData.map((rawPoolData: any) => convertRowPoolData(rawPoolData))
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.log('Error while fetching additional data from the smart contracts: ', err)
|
|
33
|
+
throw err
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public static async initializeFreshPoolsData(pools: string[], chainId: number, rpcProvider: Web3) {
|
|
38
|
+
const poolsSize = pools.length
|
|
39
|
+
const numberOfBatches = Math.ceil(poolsSize / this.batch_size)
|
|
40
|
+
|
|
41
|
+
const promises: Promise<PoolData[]>[] = []
|
|
42
|
+
|
|
43
|
+
for (let i = 0; i < numberOfBatches; i++) {
|
|
44
|
+
const batch = pools.slice(i * this.batch_size, (i + 1) * this.batch_size)
|
|
45
|
+
promises.push(this.getPoolsDataFromContract(batch, chainId, rpcProvider))
|
|
46
|
+
}
|
|
47
|
+
const allPoolsData = await Promise.all(promises)
|
|
48
|
+
|
|
49
|
+
allPoolsData.flat().forEach((poolData: PoolData) => {
|
|
50
|
+
let poolState = convertInitialPoolDataToPoolState(poolData)
|
|
51
|
+
// we will store keys as lowercase addresses
|
|
52
|
+
this.poolStateMap.set(poolData.info.pool.toLowerCase(), poolState)
|
|
53
|
+
this.startingPoolStateMap.set(poolData.info.pool.toLowerCase(), poolState.clone())
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {AdaptedPoolData, LastQuote, PoolData, PoolInfo, PoolState, TickData} from "./types";
|
|
2
|
+
|
|
3
|
+
export function convertRowPoolData(poolData: any): PoolData {
|
|
4
|
+
|
|
5
|
+
const getPoolInfo = (poolInfoRaw: any): PoolInfo => {
|
|
6
|
+
const pool: string = poolInfoRaw[0];
|
|
7
|
+
const token0: string = poolInfoRaw[1];
|
|
8
|
+
const token1: string = poolInfoRaw[2];
|
|
9
|
+
const tick: bigint = poolInfoRaw[3];
|
|
10
|
+
const tickLiquidityNet: bigint = poolInfoRaw[4];
|
|
11
|
+
const tickSpacing: bigint = poolInfoRaw[5];
|
|
12
|
+
const fee: bigint = poolInfoRaw[6];
|
|
13
|
+
const sqrtPriceX96: bigint = poolInfoRaw[7];
|
|
14
|
+
const liquidity: bigint = poolInfoRaw[8];
|
|
15
|
+
|
|
16
|
+
return new PoolInfo(
|
|
17
|
+
pool,
|
|
18
|
+
token0,
|
|
19
|
+
token1,
|
|
20
|
+
tick,
|
|
21
|
+
tickLiquidityNet,
|
|
22
|
+
tickSpacing,
|
|
23
|
+
fee,
|
|
24
|
+
sqrtPriceX96,
|
|
25
|
+
liquidity
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getTickData = (tickDataRaw: any): TickData => {
|
|
30
|
+
const tick: bigint = tickDataRaw[0];
|
|
31
|
+
const initialized: boolean = tickDataRaw[1];
|
|
32
|
+
const liquidityNet: bigint = tickDataRaw[2];
|
|
33
|
+
|
|
34
|
+
return new TickData(
|
|
35
|
+
tick,
|
|
36
|
+
initialized,
|
|
37
|
+
liquidityNet
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const zeroForOneTicksRaw = poolData[1];
|
|
42
|
+
const zeroForOneTicks: TickData[] = [];
|
|
43
|
+
for (let i = 0; i < zeroForOneTicksRaw.length; i++) {
|
|
44
|
+
zeroForOneTicks.push(getTickData(zeroForOneTicksRaw[i]));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const oneForZeroTicksRaw = poolData[2];
|
|
48
|
+
const oneForZeroTicks: TickData[] = [];
|
|
49
|
+
for (let i = 0; i < oneForZeroTicksRaw.length; i++) {
|
|
50
|
+
oneForZeroTicks.push(getTickData(oneForZeroTicksRaw[i]));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return new PoolData(
|
|
54
|
+
getPoolInfo(poolData[0]),
|
|
55
|
+
zeroForOneTicks,
|
|
56
|
+
oneForZeroTicks
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function convertInitialPoolDataToPoolState(poolData: PoolData): PoolState {
|
|
61
|
+
const adaptedPoolData = new AdaptedPoolData(poolData);
|
|
62
|
+
const lastQuote = new LastQuote(
|
|
63
|
+
adaptedPoolData.currentLiquidity,
|
|
64
|
+
adaptedPoolData.currentSqrtPriceX96,
|
|
65
|
+
adaptedPoolData.currentTickIndex
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
return new PoolState(adaptedPoolData, lastQuote);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const BalancerHelperAbi: ({
|
|
2
|
+
inputs: {
|
|
3
|
+
internalType: string;
|
|
4
|
+
name: string;
|
|
5
|
+
type: string;
|
|
6
|
+
}[];
|
|
7
|
+
stateMutability: string;
|
|
8
|
+
type: string;
|
|
9
|
+
name?: undefined;
|
|
10
|
+
outputs?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
inputs: {
|
|
13
|
+
internalType: string;
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
}[];
|
|
17
|
+
name: string;
|
|
18
|
+
outputs: {
|
|
19
|
+
internalType: string;
|
|
20
|
+
name: string;
|
|
21
|
+
type: string;
|
|
22
|
+
}[];
|
|
23
|
+
stateMutability: string;
|
|
24
|
+
type: string;
|
|
25
|
+
})[];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BalancerHelperAbi = void 0;
|
|
4
|
+
exports.BalancerHelperAbi = [{ "inputs": [{ "internalType": "address", "name": "_balancerVault", "type": "address" }], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [{ "internalType": "bytes32", "name": "_poolId", "type": "bytes32" }], "name": "getWeightedPoolInfo", "outputs": [{ "internalType": "uint8", "name": "decimals", "type": "uint8" }, { "internalType": "address[]", "name": "tokens", "type": "address[]" }, { "internalType": "uint256[]", "name": "balances", "type": "uint256[]" }, { "internalType": "uint256[]", "name": "weights", "type": "uint256[]" }, { "internalType": "uint256", "name": "feePercentage", "type": "uint256" }], "stateMutability": "view", "type": "function" }];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const CamelotHelperAbi: {
|
|
2
|
+
inputs: {
|
|
3
|
+
components: ({
|
|
4
|
+
internalType: string;
|
|
5
|
+
name: string;
|
|
6
|
+
type: string;
|
|
7
|
+
components?: undefined;
|
|
8
|
+
} | {
|
|
9
|
+
components: {
|
|
10
|
+
internalType: string;
|
|
11
|
+
name: string;
|
|
12
|
+
type: string;
|
|
13
|
+
}[];
|
|
14
|
+
internalType: string;
|
|
15
|
+
name: string;
|
|
16
|
+
type: string;
|
|
17
|
+
})[];
|
|
18
|
+
internalType: string;
|
|
19
|
+
name: string;
|
|
20
|
+
type: string;
|
|
21
|
+
}[];
|
|
22
|
+
name: string;
|
|
23
|
+
outputs: {
|
|
24
|
+
components: ({
|
|
25
|
+
internalType: string;
|
|
26
|
+
name: string;
|
|
27
|
+
type: string;
|
|
28
|
+
components?: undefined;
|
|
29
|
+
} | {
|
|
30
|
+
components: {
|
|
31
|
+
internalType: string;
|
|
32
|
+
name: string;
|
|
33
|
+
type: string;
|
|
34
|
+
}[];
|
|
35
|
+
internalType: string;
|
|
36
|
+
name: string;
|
|
37
|
+
type: string;
|
|
38
|
+
})[];
|
|
39
|
+
internalType: string;
|
|
40
|
+
name: string;
|
|
41
|
+
type: string;
|
|
42
|
+
}[];
|
|
43
|
+
stateMutability: string;
|
|
44
|
+
type: string;
|
|
45
|
+
}[];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamelotHelperAbi = void 0;
|
|
4
|
+
exports.CamelotHelperAbi = [{ "inputs": [{ "components": [{ "internalType": "address", "name": "poolId", "type": "address" }, { "internalType": "string", "name": "dexId", "type": "string" }, { "components": [{ "internalType": "address", "name": "_address", "type": "address" }, { "internalType": "uint256", "name": "decimals", "type": "uint256" }], "internalType": "struct IHelperState.Token[]", "name": "tokens", "type": "tuple[]" }], "internalType": "struct IHelperState.PoolInfo[]", "name": "poolsInfo", "type": "tuple[]" }], "name": "getPoolsData", "outputs": [{ "components": [{ "internalType": "address", "name": "poolId", "type": "address" }, { "internalType": "string", "name": "dexId", "type": "string" }, { "components": [{ "internalType": "address", "name": "_address", "type": "address" }, { "internalType": "uint256", "name": "decimals", "type": "uint256" }], "internalType": "struct IHelperState.Token[]", "name": "tokens", "type": "tuple[]" }, { "internalType": "uint112[2]", "name": "reserves", "type": "uint112[2]" }, { "internalType": "uint16[2]", "name": "fees", "type": "uint16[2]" }, { "internalType": "bool", "name": "stableSwap", "type": "bool" }], "internalType": "struct CamelotHelper.CamelotPool[]", "name": "pools", "type": "tuple[]" }], "stateMutability": "view", "type": "function" }];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export declare const RateXAbi: ({
|
|
2
|
+
inputs: {
|
|
3
|
+
components: {
|
|
4
|
+
internalType: string;
|
|
5
|
+
name: string;
|
|
6
|
+
type: string;
|
|
7
|
+
}[];
|
|
8
|
+
internalType: string;
|
|
9
|
+
name: string;
|
|
10
|
+
type: string;
|
|
11
|
+
}[];
|
|
12
|
+
stateMutability: string;
|
|
13
|
+
type: string;
|
|
14
|
+
name?: undefined;
|
|
15
|
+
anonymous?: undefined;
|
|
16
|
+
outputs?: undefined;
|
|
17
|
+
} | {
|
|
18
|
+
inputs: never[];
|
|
19
|
+
name: string;
|
|
20
|
+
type: string;
|
|
21
|
+
stateMutability?: undefined;
|
|
22
|
+
anonymous?: undefined;
|
|
23
|
+
outputs?: undefined;
|
|
24
|
+
} | {
|
|
25
|
+
anonymous: boolean;
|
|
26
|
+
inputs: {
|
|
27
|
+
indexed: boolean;
|
|
28
|
+
internalType: string;
|
|
29
|
+
name: string;
|
|
30
|
+
type: string;
|
|
31
|
+
}[];
|
|
32
|
+
name: string;
|
|
33
|
+
type: string;
|
|
34
|
+
stateMutability?: undefined;
|
|
35
|
+
outputs?: undefined;
|
|
36
|
+
} | {
|
|
37
|
+
inputs: ({
|
|
38
|
+
components: ({
|
|
39
|
+
components: {
|
|
40
|
+
internalType: string;
|
|
41
|
+
name: string;
|
|
42
|
+
type: string;
|
|
43
|
+
}[];
|
|
44
|
+
internalType: string;
|
|
45
|
+
name: string;
|
|
46
|
+
type: string;
|
|
47
|
+
} | {
|
|
48
|
+
internalType: string;
|
|
49
|
+
name: string;
|
|
50
|
+
type: string;
|
|
51
|
+
components?: undefined;
|
|
52
|
+
})[];
|
|
53
|
+
internalType: string;
|
|
54
|
+
name: string;
|
|
55
|
+
type: string;
|
|
56
|
+
} | {
|
|
57
|
+
internalType: string;
|
|
58
|
+
name: string;
|
|
59
|
+
type: string;
|
|
60
|
+
components?: undefined;
|
|
61
|
+
})[];
|
|
62
|
+
name: string;
|
|
63
|
+
outputs: {
|
|
64
|
+
internalType: string;
|
|
65
|
+
name: string;
|
|
66
|
+
type: string;
|
|
67
|
+
}[];
|
|
68
|
+
stateMutability: string;
|
|
69
|
+
type: string;
|
|
70
|
+
anonymous?: undefined;
|
|
71
|
+
})[];
|