如何获得非零流动性的所有tick范围以最终计算总价值锁定的UNISWAP V3?
目的是计算 uniswap v3 池的总锁定价值 (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
这确实会打印 MIN_TICK 和 MAX_TICK 中的流动性,但会花费大量时间并浪费 web3 调用,因为它也在零流动性刻度上进行迭代。现在这些都是硬编码的,在这里我想知道最小-最大的值是多少,以便该范围不包含任何零流动性刻度。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
** Remember: check price from big pool
** Remember: check price from big pool
这可以做到几种方法,即使用图形界面来抓取tick的几种方法,但根据您需要的流动性深度,您可能希望从RPC中获取最新信息。
我将向您展示如何从RPC
注:我仅使用5000块的原始用例来测试此代码。因此,如果请求RPC的完整范围,您可能会遇到查询限制,如果就是这样,您只需要将呼叫分解为较小的块,
如下:
则使用方式 代码太多,无法在一个答案中转储,但是大多数代码是从:
多校法用法在
“@uniswap/sdk-core”:“^3.1.0”,
“@uniswap/v3-sdk”:“^3.9.0”,
添加typechain并在项目中:
在
package.json
中添加脚本以将固体代码编译到Ethers Interfaces:“脚本”:{
“合同:compile:v3”:“ TypeChain -target Ethers-v5 --ot-out-dir types/v3” ./node_modules/@uniswap/< strong/pintrong>/artifacts/contracts/contracts/contracts/contracts/contracts/contracks/controng> /////// dhim [bgg] .json“”
},
运行一代,您现在应该在项目中具有新的接口
这是翻译的多键方法:
此方法将负责检索响应:
调用所需的其他几件事:
This can be done a few ways the uniswap interface grabs the ticks using the graph, but depending on what you need the liquidity depths for you may want to have the most recent information from the RPC.
I will show you how to grab this from the RPC
Note: I have only tested this code using chunks of 5000 due to its original use case. So you may run into query limitations if requesting the full range from the RPC, if thats the case you just need to break the calls into smaller chunks
The usage looks like so:
I've written a few methods to help out with this, there is too much code to dump in a single answer but the majority of the code was translated from:
Multicall usages in the uniswap interface
Add the following packages to your project:
"@uniswap/sdk-core": "^3.1.0",
"@uniswap/v3-sdk": "^3.9.0",
Add typechain and to the project:
Add a script in
package.json
to compile the solidity code to ethers interfaces:"scripts": {
"contracts:compile:v3": "typechain --target ethers-v5 --out-dir types/v3 "./node_modules/@uniswap//artifacts/contracts//*[!dbg].json""
},
Run the generation and you should now have new Interfaces in your project
This is the translated Multicall Method:
This Method will take care of retrieving the responses:
A few other things required for the call:
没有犯罪,但是您正在遵循一种艰难的方式,它需要使用
tickbitmap
获取下一个初始化的tick(请记住,除非必要,否则所有tick都会初始化。查询UNISWAP v3的
?如果您放置校验和地址)
或
No offense but you are following a hard way, which needs to use
TickBitmap
to get the next initialized tick (Remember not all ticks are initialized unless necessary.)Alternatively the easy way to get a pool's TVL is to query Uniswap V3's subgraph: like
(for some reason it doesn't show result if you put checksum address)
or