Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add function to get amount of asset locked per tick in pool#283

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
TheBlueMastiff wants to merge4 commits intouniswap-python:master
base:master
Choose a base branch
Loading
fromTheBlueMastiff:asset_locked_per_tick
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletionstests/test_uniswap.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -377,6 +377,32 @@ def test_get_tvl_in_pool_on_chain(self, client: Uniswap, tokens, token0, token1)
assert tvl_0 > 0
assert tvl_1 > 0

@pytest.mark.parametrize("token0, token1", [("DAI", "USDC")])
def test_asset_locked_per_tick_sums_to_tvl(self, client: Uniswap, tokens, token0, token1):
if client.version != 3:
pytest.skip("Not supported in this version of Uniswap")

pool = client.get_pool_instance(tokens[token0], tokens[token1])
asset_locked_per_tick_dict = client.get_asset_locked_per_tick_in_pool(pool)

# check TVL adds up correctly
token0_total = 0
token1_total = 0
ticks = asset_locked_per_tick_dict['ticks']
token0_arr = asset_locked_per_tick_dict['token0']
token1_arr = asset_locked_per_tick_dict['token1']

for i, tick in enumerate(ticks):
token0_total += token0_arr[i]
token1_total += token1_arr[i]

tvl_0, tvl_1 = client.get_tvl_in_pool(pool)

# assert on values rounded to nearest million for now TODO: fix
assert round(tvl_0 / 1e6) == round(token0_total / 1e6)
assert round(tvl_1 / 1e6) == round(token1_total / 1e6)
assert round((tvl_0 + tvl_1) / 1e6) == round((token0_total + token1_total) / 1e6)

@pytest.mark.skip
@pytest.mark.parametrize(
"token, max_eth",
Expand Down
4 changes: 2 additions & 2 deletionsuniswap/constants.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -64,7 +64,7 @@
MAX_TICK = -MIN_TICK

# Source: https://github.com/Uniswap/v3-core/blob/v1.0.0/contracts/UniswapV3Factory.sol#L26-L31
_tick_spacing = {100:1, 500: 10, 3_000: 60, 10_000: 200}
_tick_spacing = {100:1, 500: 10, 3_000: 60, 10_000: 200}

# Derived from (MIN_TICK//tick_spacing) >> 8 and (MAX_TICK//tick_spacing) >> 8
_tick_bitmap_range = {100:(-3466, 3465), 500: (-347, 346), 3_000: (-58, 57), 10_000: (-18, 17)}
_tick_bitmap_range = {100:(-3466, 3465), 500: (-347, 346), 3_000: (-58, 57), 10_000: (-18, 17)}
95 changes: 95 additions & 0 deletionsuniswap/uniswap.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1385,6 +1385,101 @@ def get_tvl_in_pool(self, pool: Contract) -> Tuple[float, float]:
token1_liquidity = token1_liquidity // (10**token1_decimals)
return (token0_liquidity, token1_liquidity)

def get_asset_locked_per_tick_in_pool(self, pool: Contract) -> Dict:
"""
Iterate through each tick in a pool and calculate the amount of asset
locked on-chain per tick

Note: the output of this function may differ from what is returned by the
UniswapV3 subgraph api (https://github.com/Uniswap/v3-subgraph/issues/74)

Params
------
pool: Contract
pool contract instance to find TVL
"""
pool_tick_output_types = (
"uint128",
"int128",
"uint256",
"uint256",
"int56",
"uint160",
"uint32",
"bool",
)

pool_immutables = self.get_pool_immutables(pool)
pool_state = self.get_pool_state(pool)
fee = pool_immutables["fee"]
sqrtPrice = pool_state["sqrtPriceX96"] / (1 << 96)

TICK_SPACING = _tick_spacing[fee]
BITMAP_SPACING = _tick_bitmap_range[fee]

_max_tick = self.find_tick_from_bitmap(BITMAP_SPACING, pool, TICK_SPACING, fee, True)
_min_tick = self.find_tick_from_bitmap(BITMAP_SPACING, pool, TICK_SPACING, fee, False)

assert _max_tick != False, "Error finding max tick"
assert _min_tick != False, "Error finding min tick"

# # Correcting for each token's respective decimals
token0_decimals = (
_load_contract_erc20(self.w3, pool_immutables["token0"])
.functions.decimals()
.call()
)
token1_decimals = (
_load_contract_erc20(self.w3, pool_immutables["token1"])
.functions.decimals()
.call()
)
Batch = namedtuple("Batch", "ticks batchResults")
ticks = []
# Batching pool.functions.tick() calls as these are the major bottleneck to performance
for batch in list(chunks(range(_min_tick, _max_tick, TICK_SPACING), 1000)):
_batch = []
_ticks = []
for tick in batch:
_batch.append(
(
pool.address,
HexBytes(pool.functions.ticks(tick)._encode_transaction_data()),
)
)
_ticks.append(tick)
ticks.append(Batch(_ticks, self.multicall(_batch, pool_tick_output_types)))

liquidity_total = 0
liquidity_per_tick_dict: Dict = {
'ticks': [],
'token0': [],
'token1': []
}
for tickBatch in ticks:
tick_arr = tickBatch.ticks
for i in range(len(tick_arr)):
tick = tick_arr[i]
tickData = tickBatch.batchResults[i]
# source: https://stackoverflow.com/questions/71814845/how-to-calculate-uniswap-v3-pools-total-value-locked-tvl-on-chain
liquidityNet = tickData[1]
liquidity_total += liquidityNet
sqrtPriceLow = 1.0001 ** (tick // 2)
sqrtPriceHigh = 1.0001 ** ((tick + TICK_SPACING) // 2)
token0_liquidity = self.get_token0_in_pool(
liquidity_total, sqrtPrice, sqrtPriceLow, sqrtPriceHigh
)
token1_liquidity = self.get_token1_in_pool(
liquidity_total, sqrtPrice, sqrtPriceLow, sqrtPriceHigh
)
token0_liquidity = token0_liquidity // (10**token0_decimals)
token1_liquidity = token1_liquidity // (10**token1_decimals)
liquidity_per_tick_dict['ticks'].append(tick)
liquidity_per_tick_dict['token0'].append(token0_liquidity)
liquidity_per_tick_dict['token1'].append(token1_liquidity)

return liquidity_per_tick_dict

# ------ Approval Utils ------------------------------------------------------------
def approve(self, token: AddressLike, max_approval: Optional[int] = None) -> None:
"""Give an exchange/router max approval of a token."""
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp