У меня вопрос о том, как получить агрегированные токены WETH в Uniswap v3. В настоящее время я получаю объединенный WETH, читая `slot0.sqrtPriceX96` и `liquidity()` пула Uniswap V3, сопоставляя активную ликвидность (L) в текущем ценовом диапазоне с эквивалентной парой количества токенов/WETH, чтобы получить виртуальные резервы. Однако иногда значение отличается от фактического объединенного WETH. Есть ли другие способы получить это значение?
private void calculateV3ReservesAndPriceForMultiCall(Token token, BigInteger blockNumber, MultiCallPreResponse preResponse,String poolAddr) throws Exception {
Web3j web3j = Web3jFactory.getNeedHistoryWeb3j(token.getChainId(), blockNumber);
IUniswapV3Pool v3Pool = IUniswapV3Pool.load(poolAddr, web3j, new ReadonlyTransactionManager(web3j, poolAddr), new DefaultGasProvider());
Tuple7 slot0 = v3Pool.slot0().send();
BigInteger P = slot0.component1(); // sqrtPriceX96
BigInteger liquidity = v3Pool.liquidity().send();
if (P == null || P.signum() == 0 || liquidity == null || liquidity.signum() == 0) {
log.warn("V3 pool data is invalid.: sqrtPriceX96={}, liquidity={}", P, liquidity);
return;
}
BigDecimal L = new BigDecimal(liquidity);
BigDecimal Q96 = new BigDecimal(BigInteger.ONE.shiftLeft(96));
// ===== Correct V3 reserve calculation =====
// amount0 = L / sqrtPrice = L * Q96 / sqrtPriceX96
// amount1 = L * sqrtPrice = L * sqrtPriceX96 / Q96
BigDecimal amount0 = L.multiply(Q96).divide(new BigDecimal(P), 0, RoundingMode.DOWN);
BigDecimal amount1 = L.multiply(new BigDecimal(P)).divide(Q96, 0, RoundingMode.DOWN);
boolean isToken0 = Boolean.TRUE.equals(token.getIsToken0());
BigInteger tokenAmountAtoms;
BigInteger wethAmountAtoms;
if (isToken0) {
tokenAmountAtoms = amount0.toBigIntegerExact();
wethAmountAtoms = amount1.toBigIntegerExact();
} else {
tokenAmountAtoms = amount1.toBigIntegerExact();
wethAmountAtoms = amount0.toBigIntegerExact();
}
preResponse.setTokenReverse(tokenAmountAtoms, wethAmountAtoms);
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... uniswap-v3