The aim is to calculate the uniswap v3 pool’s total value locked (TVL).
import json from web3 import Web3 from collections import namedtuple infura_url = 'https://mainnet.infura.io/v3/******' web3 = Web3(Web3.HTTPProvider(infura_url)) def read_json_file(directory:str, file_name: str): try: file_path = directory + file_name f_ = open(file_path, 'r') except Exception as e: print(f"Unable to open the {file_path} file") raise e else: json_data = json.loads(f_.read()) return json_data # uniswap_ETH_USDT.v3 abi = read_json_file('./', 'abis/uniswapV3Pool.json') address = '0x4e68Ccd3E89f51C3074ca5072bbAC773960dFa36' exchange_contract = web3.eth.contract(address=Web3.toChecksumAddress(address), abi=abi) Tick = namedtuple("Tick", "liquidityGross liquidityNet feeGrowthOutside0X128 feeGrowthOutside1X128 tickCumulativeOutside secondsPerLiquidityOutsideX128 secondsOutside initialized") amounts0 = 0 amounts1 = 0 liquidity = 0 slot0 = exchange_contract.functions.slot0().call() sqrtPriceCurrent = slot0[0] / (1 << 96) MIN_TICK = -887272 MAX_TICK = 887272 TICK_SPACING = exchange_contract.functions.tickSpacing().call() def calculate_token0_amount(liquidity, sp, sa, sb): sp = max(min(sp, sb), sa) return liquidity * (sb - sp) / (sp * sb) def calculate_token1_amount(liquidity, sp, sa, sb): sp = max(min(sp, sb), sa) return liquidity * (sp - sa) for tick in range(MIN_TICK, MAX_TICK, TICK_SPACING): tickRange = Tick(*exchange_contract.functions.ticks(tick).call()) liquidity += tickRange.liquidityNet sqrtPriceLow = 1.0001 ** (tick // 2) sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2) amounts0 += calculate_token0_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh) amounts1 += calculate_token1_amount(liquidity, sqrtPriceCurrent, sqrtPriceLow, sqrtPriceHigh) print(amounts0, amounts1, tick) # for better output, should correct for the amount of decimals before printing
This does print liquidity in MIN_TICK and MAX_TICK but takes a lot of time and waste web3 calls as it is iterating on zero liquidity ticks also. Right now these are hardcoded, here I want to know what can be the value of min-max so that range does not contain any zero liquidity tick.
Advertisement
Answer
- Getting pair token balance of contracts
web3.eth.contract(address=token_address,abi=abi).functions.balanceOf(contract_address).call()
- and then get current price of each token / USDT by calling function slot0 in pool tokenA/USDT & tokenB/USDT
slot0 = contract.functions.slot0().call()
sqrtPriceCurrent = slot0[0] / (1 << 96)
priceCurrent = sqrtPriceCurrent ** 2
decimal_diff = USDT_decimal – TOKEN_A_decimal
token_price = 10**(-decimal_diff)/( priceCurrent) if token0_address == USDT_address else priceCurrent/(10**decimal_diff)
- Finally, TVL = sum(token_balance * token_price)
** Remember: check price from big pool