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.

sqrt_price_x96: int¶
tick: int¶
liquidity: int¶
class degenbot.uniswap.v4_liquidity_pool.SwapDelta¶

SwapDelta class.

currency0: int¶
currency1: int¶
property amount_in: int¶

The deposited token amount.

property amount_out: int¶

The withdrawn token amount.

class degenbot.uniswap.v4_liquidity_pool.ProtocolFee¶

ProtocolFee class.

zero_for_one: int¶
one_for_zero: int¶
class degenbot.uniswap.v4_liquidity_pool.Slot0¶

Slot0 class.

sqrt_price_x96: int¶
tick: int¶
protocol_fee: ProtocolFee¶
lp_fee: int¶
degenbot.uniswap.v4_liquidity_pool.NATIVE_CURRENCY_ADDRESS¶
class degenbot.uniswap.v4_liquidity_pool.Hooks(*args, **kwds)¶

Bases: enum.Enum

Hooks 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.ConcentratedLiquidityCompanion

A Uniswap V4 concentrated-liquidity pool companion over a Pool handle.

Rust owns the mutable state (scalars + tick data + reorg journal) as V4PoolState; this companion reads it through self._py_pool (one 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. 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¶
active_hooks: frozenset[Hooks]¶
name: str¶
protocol_fee: ProtocolFee¶
lp_fee: int¶
classmethod from_handle(py_pool: degenbot.types.Pool) → Self¶

Wrap a Rust-owned Pool handle as a Python companion.

Internal seam (ADR-005, Polars-style _from_pydf pattern). 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) as V4PoolState and the immutable registration metadata as V4PoolIdentity; this companion reads both through self._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 cls instance wrapping py_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:
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:
property address: degenbot.types.chain.ChecksummedAddress¶

Address.

Returns:

The pool manager address.

property pool_id: bytes¶

Pool id.

Returns:

The pool ID bytes.

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.

property tick_spacing: int¶

Tick spacing.

Returns:

The tick spacing for the pool (Python-side identity).

property fee: int¶

Fee.

Returns:

The fee in pips (Python-side identity).