degenbot.uniswap.v4_liquidity_pool¶
UniswapV4Pool: concentrated liquidity AMM companion over a Pool handle.
ADR-005 slice 9b — the V4 companion rewritten over the same Pool handle topology as the V3 companion. Rust BotState is the single source of truth for V4 mutable state (scalars, tick data, reorg journal); this companion reads it through self._py_pool (atomic snapshot_v3() for scalars — already V3/V4-generic via get_v3_or_v4_pool — + tick_data_snapshot()/ tick_bitmap_snapshot() for the tick maps) and delegates external_update (Swap) / update_liquidity_map (ModifyLiquidity) / update_tick_data (sparse-map backfill) / discard / restore to the handle.
_state_mgr / _state_cache / state_cache_depth are dropped — the StateCache temporal-navigation layer lives in Rust now (journal + discard/restore). V3 already has none; V4 follows.
V4-specific identity (pool_id, pool_manager_address, pool_key, hook_address, protocol_fee, lp_fee, state_view_address) stays Python-side — matches V3 keeping tokens/factory/fee Python-side. The hook admission floor (reject amount-modifying hooks + dynamic fees) lives in Rust (BotState::register_v4_pool), surfaced at Bot.register_v4_pool (ADR-005 slice 9a) so the companion never holds a hooked pool.
Checked words (a tick-data fetcher probed tickBitmap(word) and the on-chain bitmap was zero) are tracked in Rust known_bitmap_words (Sparse only — see the V3 companion’s sparse-map note); tick_bitmap_snapshot() surfaces a checked-but-empty word as (0, block) so the fetch loop breaks with no client-side bitmap shadow.
Module Contents¶
- class degenbot.uniswap.v4_liquidity_pool.SwapResult¶
SwapResult class.
- class degenbot.uniswap.v4_liquidity_pool.SwapDelta¶
SwapDelta class.
- class degenbot.uniswap.v4_liquidity_pool.ProtocolFee¶
ProtocolFee class.
- class degenbot.uniswap.v4_liquidity_pool.Slot0¶
Slot0 class.
- protocol_fee: ProtocolFee¶
- degenbot.uniswap.v4_liquidity_pool.NATIVE_CURRENCY_ADDRESS¶
- class degenbot.uniswap.v4_liquidity_pool.Hooks(*args, **kwds)¶
Bases:
enum.EnumHooks class.
- BEFORE_INITIALIZE = 8192¶
- AFTER_INITIALIZE = 4096¶
- BEFORE_ADD_LIQUIDITY = 2048¶
- AFTER_ADD_LIQUIDITY = 1024¶
- BEFORE_REMOVE_LIQUIDITY = 512¶
- AFTER_REMOVE_LIQUIDITY = 256¶
- BEFORE_SWAP = 128¶
- AFTER_SWAP = 64¶
- BEFORE_DONATE = 32¶
- AFTER_DONATE = 16¶
- BEFORE_SWAP_RETURNS_DELTA = 8¶
- AFTER_SWAP_RETURNS_DELTA = 4¶
- AFTER_ADD_LIQUIDITY_RETURNS_DELTA = 2¶
- AFTER_REMOVE_LIQUIDITY_RETURNS_DELTA = 1¶
- class degenbot.uniswap.v4_liquidity_pool.UniswapV4Pool(*args: Any, **kwargs: Any)¶
Bases:
degenbot.uniswap.v4_pool_state.V4PoolState,degenbot.uniswap.v4_pool_calc.UniswapV4PoolCalc,degenbot.uniswap.cl_companion.ConcentratedLiquidityCompanionA Uniswap V4 concentrated-liquidity pool companion over a
Poolhandle.Rust owns the mutable state (scalars + tick data + reorg journal) as
V4PoolState; this companion reads it throughself._py_pool(one atomicsnapshot_v3()for scalars — already V3/V4-generic viaget_v3_or_v4_pool— +tick_data_snapshot()/tick_bitmap_snapshot()for the tick maps) and delegatesexternal_update(Swap) /update_liquidity_map(ModifyLiquidity) /update_tick_data(sparse-map backfill) / discard / restore to the handle. V4-specific identity (pool_id, pool_manager, pool_key, hooks, protocol_fee, lp_fee, state_view_address) stays Python-side — matches V3.Construct via the V4 builder (which registers in Rust and hands the handle here); tests use
make_v4_pool.Hook admission floor: pools with amount-modifying hooks (hook_flags & 0xCC != 0) or dynamic fees (fee == 0x100000) are rejected in Rust (BotState::register_v4_pool), surfaced at Bot.register_v4_pool as typed exceptions — so this companion never holds a hooked/dynamic-fee pool.
- type PoolState = UniswapV4PoolState¶
- hook_address: degenbot.types.chain.ChecksummedAddress¶
- protocol_fee: ProtocolFee¶
- classmethod from_handle(py_pool: degenbot.types.Pool) Self¶
Wrap a Rust-owned
Poolhandle as a Python companion.Internal seam (ADR-005, Polars-style
_from_pydfpattern). The handle is self-describing: every identity field (pool_manager, pool_id, pool_key, hooks, tokens, fee, tick_spacing) is read off it — no identity is passed as constructor args. Rust owns the mutable state (slot0 + tick_data + reorg journal) asV4PoolStateand the immutable registration metadata asV4PoolIdentity; this companion reads both throughself._py_pool.Protocol fee / LP fee / state_view_address are builder-supplied values the seam defaults; the builder overrides them after
from_handle(matches V3’s deployer/init_hash override).- Returns:
A
clsinstance wrappingpy_pool.- Raises:
DegenbotValueError – If the handle is not a V4-family pool.
- calculate_tokens_in_from_tokens_out(token_out: degenbot.erc20.Erc20Token, token_out_quantity: int, override_state: degenbot.uniswap.v4_types.UniswapV4PoolState | None = None) int¶
Calculate tokens in from tokens out.
- Returns:
The required input token amount.
- Raises:
DegenbotValueError – If token_out is not held by this pool.
HookedPoolResult – If the pool has active hooks that affect the swap.
IncompleteSwap – If the swap cannot fulfill the full output amount.
LiquidityPoolError – If the simulated execution reverts.
- calculate_tokens_out_from_tokens_in(token_in: degenbot.erc20.Erc20Token, token_in_quantity: int, override_state: degenbot.uniswap.v4_types.UniswapV4PoolState | None = None) int¶
Calculate tokens out from tokens in.
- Returns:
The expected output token amount.
- Raises:
DegenbotValueError – If token_in is not held by this pool.
HookedPoolResult – If the pool has active hooks that affect the swap.
IncompleteSwap – If the swap cannot fulfill the full input amount.
LiquidityPoolError – If the simulated execution reverts.
- property address: degenbot.types.chain.ChecksummedAddress¶
Address.
- Returns:
The pool manager address.
- property pool_key: degenbot.uniswap.v4_types.UniswapV4PoolKey¶
Pool key.
- Returns:
The V4 pool key struct.
- property sqrt_price_x96: int¶
Sqrt price x96.
- Returns:
The current sqrt price as a Q64.96 value (from Rust).
- property state: degenbot.uniswap.v4_types.UniswapV4PoolState¶
State.
- Returns:
The current pool state, built from one atomic Rust scalar snapshot (
_py_pool.snapshot_v3()— V3/V4-generic — ) + the tick-map snapshots.- Raises:
DegenbotValueError – If the pool is not registered in Rust.