Skip to content

Commit 1deccfb

Browse files
authored
Revert "Fix solidlyv3 pool tvl, add more chains"
1 parent 32bf548 commit 1deccfb

File tree

4 files changed

+618
-582
lines changed

4 files changed

+618
-582
lines changed
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
// forked from uniswap.fish chads (see https://github.com/chunza2542/uniswap.fish)
2+
// modified univ3 adapter to just return the active liq fraction
3+
const bn = require('bignumber.js');
4+
const axios = require('axios');
5+
6+
bn.config({ EXPONENTIAL_AT: 999999, DECIMAL_PLACES: 40 });
7+
8+
const Q96 = new bn(2).pow(96);
9+
10+
const getTickFromPrice = (price, token0Decimal, token1Decimal) => {
11+
const token0 = expandDecimals(price, Number(token0Decimal));
12+
const token1 = expandDecimals(1, Number(token1Decimal));
13+
const sqrtPrice = encodeSqrtPriceX96(token1).div(encodeSqrtPriceX96(token0));
14+
15+
return Math.log(sqrtPrice.toNumber()) / Math.log(Math.sqrt(1.0001));
16+
};
17+
18+
const getTokensAmountFromDepositAmountUSD = (
19+
P,
20+
Pl,
21+
Pu,
22+
priceUSDX,
23+
priceUSDY,
24+
depositAmountUSD
25+
) => {
26+
const deltaL =
27+
depositAmountUSD /
28+
((Math.sqrt(P) - Math.sqrt(Pl)) * priceUSDY +
29+
(1 / Math.sqrt(P) - 1 / Math.sqrt(Pu)) * priceUSDX);
30+
31+
let deltaY = deltaL * (Math.sqrt(P) - Math.sqrt(Pl));
32+
if (deltaY * priceUSDY < 0) deltaY = 0;
33+
if (deltaY * priceUSDY > depositAmountUSD)
34+
deltaY = depositAmountUSD / priceUSDY;
35+
36+
let deltaX = deltaL * (1 / Math.sqrt(P) - 1 / Math.sqrt(Pu));
37+
if (deltaX * priceUSDX < 0) deltaX = 0;
38+
if (deltaX * priceUSDX > depositAmountUSD)
39+
deltaX = depositAmountUSD / priceUSDX;
40+
41+
return { amount0: deltaX, amount1: deltaY };
42+
};
43+
44+
// for calculation detail, please visit README.md (Section: Calculation Breakdown, No. 2)
45+
const getLiquidityForAmount0 = (sqrtRatioAX96, sqrtRatioBX96, amount0) => {
46+
// amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) - sqrt(lower))
47+
const intermediate = mulDiv(sqrtRatioBX96, sqrtRatioAX96, Q96);
48+
return mulDiv(amount0, intermediate, sqrtRatioBX96.minus(sqrtRatioAX96));
49+
};
50+
51+
const getLiquidityForAmount1 = (sqrtRatioAX96, sqrtRatioBX96, amount1) => {
52+
// amount1 / (sqrt(upper) - sqrt(lower))
53+
return mulDiv(amount1, Q96, sqrtRatioBX96.minus(sqrtRatioAX96));
54+
};
55+
56+
const getSqrtPriceX96 = (price, token0Decimal, token1Decimal) => {
57+
const token0 = expandDecimals(price, token0Decimal);
58+
const token1 = expandDecimals(1, token1Decimal);
59+
60+
return token0.div(token1).sqrt().multipliedBy(Q96);
61+
};
62+
63+
const getLiquidityDelta = (
64+
P,
65+
lowerP,
66+
upperP,
67+
amount0,
68+
amount1,
69+
token0Decimal,
70+
token1Decimal
71+
) => {
72+
const amt0 = expandDecimals(amount0, token1Decimal);
73+
const amt1 = expandDecimals(amount1, token0Decimal);
74+
75+
const sqrtRatioX96 = getSqrtPriceX96(P, token0Decimal, token1Decimal);
76+
const sqrtRatioAX96 = getSqrtPriceX96(lowerP, token0Decimal, token1Decimal);
77+
const sqrtRatioBX96 = getSqrtPriceX96(upperP, token0Decimal, token1Decimal);
78+
79+
let liquidity;
80+
if (sqrtRatioX96.lte(sqrtRatioAX96)) {
81+
liquidity = getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amt0);
82+
} else if (sqrtRatioX96.lt(sqrtRatioBX96)) {
83+
const liquidity0 = getLiquidityForAmount0(
84+
sqrtRatioX96,
85+
sqrtRatioBX96,
86+
amt0
87+
);
88+
const liquidity1 = getLiquidityForAmount1(
89+
sqrtRatioAX96,
90+
sqrtRatioX96,
91+
amt1
92+
);
93+
94+
liquidity = bn.min(liquidity0, liquidity1);
95+
} else {
96+
liquidity = getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amt1);
97+
}
98+
99+
return liquidity;
100+
};
101+
102+
/// get the percentage of active liquidity from the price assumption
103+
const liquidityPercentage = (liquidityDelta, liquidity) => {
104+
// console.log("DELTA", liquidityDelta, "LIQ", liquidity)
105+
const liquidityPercentage = liquidityDelta
106+
.div(liquidity.plus(liquidityDelta))
107+
.toNumber();
108+
return liquidityPercentage;
109+
};
110+
111+
// get 'active' liquidity
112+
const getLiquidityFromTick = (poolTicks, tick) => {
113+
// calculate a cumulative of liquidityNet from all ticks that poolTicks[i] <= tick
114+
let liquidity = new bn(0);
115+
for (let i = 0; i < poolTicks.length - 1; ++i) {
116+
liquidity = liquidity.plus(new bn(poolTicks[i].liquidityNet));
117+
118+
const lowerTick = Number(poolTicks[i].tickIdx);
119+
const upperTick = Number(poolTicks[i + 1]?.tickIdx);
120+
121+
if (lowerTick <= tick && tick <= upperTick) {
122+
break;
123+
}
124+
}
125+
126+
return liquidity;
127+
};
128+
129+
// private helper functions
130+
const encodeSqrtPriceX96 = (price) => {
131+
return new bn(price).sqrt().multipliedBy(Q96).integerValue(3);
132+
};
133+
134+
const expandDecimals = (n, exp) => {
135+
return new bn(n).multipliedBy(new bn(10).pow(exp));
136+
};
137+
138+
const mulDiv = (a, b, multiplier) => {
139+
return a.multipliedBy(b).div(multiplier);
140+
};
141+
142+
const getPoolTicks = async (poolAddress, url) => {
143+
const PAGE_SIZE = 3;
144+
let result = [];
145+
let page = 0;
146+
while (true) {
147+
const pool1 = await _getPoolTicksByPage(poolAddress, page, url);
148+
const pool2 = await _getPoolTicksByPage(poolAddress, page + 1, url);
149+
const pool3 = await _getPoolTicksByPage(poolAddress, page + 2, url);
150+
151+
result = [...result, ...pool1, ...pool2, ...pool3];
152+
if (pool1.length === 0 || pool2.length === 0 || pool3.length === 0) {
153+
break;
154+
}
155+
page += PAGE_SIZE;
156+
}
157+
return result;
158+
};
159+
160+
const _getPoolTicksByPage = async (poolAddress, page, url) => {
161+
let res;
162+
try {
163+
res = await _queryUniswap(
164+
`{
165+
ticks(first: 1000, skip: ${
166+
page * 1000
167+
}, where: { poolAddress: "${poolAddress}" }, orderBy: tickIdx) {
168+
tickIdx
169+
liquidityNet
170+
price0
171+
price1
172+
}
173+
}`,
174+
url
175+
);
176+
} catch (e) {
177+
console.log('_getPoolTicksByPage failed for', poolAddress);
178+
return [];
179+
}
180+
181+
return res === undefined ? [] : res.ticks;
182+
};
183+
184+
const _queryUniswap = async (query, url) => {
185+
const { data } = await axios({
186+
url,
187+
method: 'post',
188+
data: {
189+
query,
190+
},
191+
});
192+
193+
return data.data;
194+
};
195+
196+
module.exports.EstimateActiveLiq = async (
197+
poolAddress,
198+
priceAssumptionValue,
199+
priceRangeValue,
200+
currentPriceUSDToken1,
201+
currentPriceUSDToken0,
202+
depositAmountUSD,
203+
decimalsToken0,
204+
decimalsToken1,
205+
url
206+
) => {
207+
const P = priceAssumptionValue;
208+
let Pl = priceRangeValue[0];
209+
let Pu = priceRangeValue[1];
210+
const priceUSDX = currentPriceUSDToken1 || 1;
211+
const priceUSDY = currentPriceUSDToken0 || 1;
212+
213+
const { amount0, amount1 } = getTokensAmountFromDepositAmountUSD(
214+
P,
215+
Pl,
216+
Pu,
217+
priceUSDX,
218+
priceUSDY,
219+
depositAmountUSD
220+
);
221+
222+
const deltaL = getLiquidityDelta(
223+
P,
224+
Pl,
225+
Pu,
226+
amount0,
227+
amount1,
228+
Number(decimalsToken0 || 18),
229+
Number(decimalsToken1 || 18)
230+
);
231+
232+
let currentTick = getTickFromPrice(
233+
P,
234+
decimalsToken0 || '18',
235+
decimalsToken1 || '18'
236+
);
237+
const poolTicks = await getPoolTicks(poolAddress, url);
238+
239+
if (!poolTicks.length) {
240+
console.log(`No pool ticks found for ${poolAddress}`);
241+
return { poolAddress, estimatedFee: 0 };
242+
}
243+
244+
const L = getLiquidityFromTick(poolTicks, currentTick);
245+
246+
const liq_percentage =
247+
P >= Pl && P <= Pu ? liquidityPercentage(deltaL, L) : 0;
248+
249+
return liq_percentage;
250+
};

0 commit comments

Comments
 (0)