Skip to content
Advertisement

How to get all tick ranges with non-zero liquidity to finally calculate Total Value Locked Uniswap V3?

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

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement