2

I'm trying to get the amount of each token currently held on a liquidity pool position on uniswap v3 (on pyhton) based on the token ID of the NFT. I was abble to get info about the position 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.

1 Answer 1

1

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 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).
    – Adrien G
    Jun 20 at 9:03
  • Was from somewhere else and i don't remember. Jun 20 at 19:35

Your Answer

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

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