7

I'm trying to get the amount of each token currently held in a liquidity pool position on Uniswap V3 (in Pyhton) based on the token ID of the NFT. I was able to get info about the position by calling :

contract = web3.eth.contract(address=addr_uni_nft_pos,abi=abi_uni_pos)    
contract.functions.positions(nft_token_id).call() 

from which I'm getting:

    {'nonce': 0,
     'operator': '0x0000000000000000000000000000000000000000',
     'token0': '0x4d224452801ACEd8B2F0aebE155379bb5D594381',
     'token1': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
     'fee': 3000,
     'tickLower': -56700,
     'tickUpper': -55740,
     'liquidity': 0,
     'feeGrowthInside0LastX128': 115792089237316195423570985008687907853246859851719844967496612553656335272574,
     'feeGrowthInside1LastX128': 115792089237316195423570985008687907853269894723013691862125737150933929444085,
     'tokensOwed0': 0,
     'tokensOwed1': 0}

However I want to get the total amount (deposited + rewards) of each token currently held on the pool, independently if the position is or not on range. Is there a way to do this? I was thinking in simply looking at the minting event of the NFT itself, but surely there is a simpler way.

Thanks in advance.

2 Answers 2

3

I wrote a function that perform a static call passing the maximum collectable value in other to see how much is pending to be collected.


export const calculatePendingFees = async (
  tokenId: number,
  recipient: string,
  amount0Max: BigNumber,
  amount1Max: BigNumber,
  chainId: number
) => {
  try {
    const params = {
      tokenId: tokenId,
      recipient: recipient,
      amount0Max: amount0Max,
      amount1Max: amount1Max,
    }

    const nonfungible = new ethers.Contract(
      NONFUNGIBLE_POSITION_MANAGER_ADDRESS[chainId],
      Nonfungiblepositionmanager.abi,
      PROVIDER[chainId]
    )

    const feesGenerated = await nonfungible.callStatic.collect(params)
    return feesGenerated
  } catch (error) {
    console.log(error.message, "calculate fees error")
  }
}

For amount0Maxand amount1Maxyou can use this:

const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1)

This function will return to you the uncollected fees :)

The number of token0and token1can be retrieved through these functions:


export const calcAmount0 = (
  liquidity: number,
  currentPrice: number,
  priceUpper: number,
  token0Decimals: number,
  token1Decimals: number
) => {
  const decimalAdjustment = 10 ** (token0Decimals - token1Decimals)
  const mathCurrentPrice = currentPrice / decimalAdjustment
  const mathPriceUpper = priceUpper / decimalAdjustment

  const math =
    liquidity *
    ((Math.sqrt(mathPriceUpper) - Math.sqrt(mathCurrentPrice)) /
      (Math.sqrt(mathCurrentPrice) * Math.sqrt(mathPriceUpper)))
  const adjustedMath = math > 0 ? math : 0
  return adjustedMath
}

export const calcAmount1 = (
  liquidity: number,
  currentPrice: number,
  priceLower: number,
  token0Decimals: number,
  token1Decimals: number
) => {
  const decimalAdjustment = 10 ** (token0Decimals - token1Decimals)
  const mathCurrentPrice = currentPrice / decimalAdjustment
  const mathPriceLower = priceLower / decimalAdjustment

  const math =
    liquidity * (Math.sqrt(mathCurrentPrice) - Math.sqrt(mathPriceLower))
  const adjustedMath = math > 0 ? math : 0
  return adjustedMath
}

The price lower and price upper can be retrieved through this:

  const priceLower = tickToPrice(tickLower, decimalsA, decimalsB)
  const priceUpper = tickToPrice(tickUpper, decimalsA, decimalsB)

Till i know unfortunatelly we only have V3-SDK on npm so you will have plenty work writing anything.

3
  • Thanks for your response Rodrigo. However I need to do this on python (not js). I will revise your answer and try to implement it on python. Cheers :) Jan 23, 2023 at 4:32
  • Hello @Rodrigo Burgos, did you find the math formula in the uniswap v3 whitepaper ? I could not find any info regarding the way to compute those amounts (from the position data returned by the positions() method).
    – miko7358
    Jun 20, 2023 at 9:03
  • Was from somewhere else and i don't remember. Jun 20, 2023 at 19:35
0

The math needed to calculate all of this can be found on the Uniswap blog, particularly in the second part of the article Uniswap V3 math. It is also on this file by Elsts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.