degenbot.uniswap.cl_companion ============================= .. py:module:: degenbot.uniswap.cl_companion .. autoapi-nested-parse:: Shared concentrated-liquidity (CL) companion surface. ``UniswapV3Pool`` and ``UniswapV4Pool`` carried duplicated copies of the same CL write-back surface — the tick-map reads, the 3-format ``update_tick_data`` normalisation, ``external_update``, ``update_liquidity_map`` and the discard/restore delegation. This module collapses that surface into one base so "CL state write-back + the sparse backfill gate" is written once. What stays on the subclasses: identity (address/factory/tokens/fee/ pool_key/hook/protocol-fees), the family calc mixins, and ``__eq__``/ ``__hash__``. This base does no family math (ADR-005: the driver shell is not a co-implementation) and adds no cross-family Rust seam (ADR-014); the companions stay Python (ADR-023). Module Contents --------------- .. py:class:: ConcentratedLiquidityCompanion Bases: :py:obj:`degenbot.types.abstract.AbstractLiquidityPool` Shared CL companion surface over a Rust-owned ``Pool`` handle. Subclasses: ``UniswapV3Pool`` / ``UniswapV4Pool`` (and anything built over the CL handle, e.g. ``AerodromeV3Pool``). The subclass state mixins supply ``tick_spacing`` and the identity; this base supplies the Rust-owned scalar/tick-map reads + the write-back delegation + the unified sparse-word backfill gate. .. py:attribute:: name :type: str .. py:attribute:: address :type: degenbot.types.chain.ChecksummedAddress .. py:property:: tick_spacing :type: int V3 state mixin, V4 pool key). :type: Tick spacing (overridden .. py:property:: liquidity :type: int The current active liquidity (from Rust via the handle). :type: Liquidity. Returns .. py:property:: sqrt_price_x96 :type: int The current sqrt price as a Q64.96 value (from Rust). :type: Sqrt price x96. Returns .. py:property:: tick :type: int The current tick (from Rust via the handle). :type: Tick. Returns .. py:property:: tick_bitmap :type: dict[int, degenbot.uniswap.concentrated.types.BitmapAtWord] Tick bitmap. A deep-copy snapshot of the Rust-side tick bitmap: derived from ``tick_data`` keys, + for Sparse pools the checked-but-empty words from Rust ``known_bitmap_words`` as ``(0, block)`` entries (a word checked via ``update_tick_data``/fetch-merge survives as present-but-zero — the fetch loop breaks). Tracked pools return the pure derivation (absent word = known-empty; the map is complete). .. py:property:: tick_data :type: dict[int, degenbot.uniswap.concentrated.types.LiquidityAtTick] Tick data. Returns a deep-copy snapshot of the Rust-side tick data (``{tick: (liquidity_gross, liquidity_net, block)}`` lifted into immutable ``LiquidityAtTick`` rows). .. py:property:: update_block :type: degenbot.types.aliases.BlockNumber The block number of the most recent state update (from Rust). :type: Update block. Returns .. py:property:: initial_state_block :type: int Block number at which the pool's initial state was captured. :returns: The block number from construction (DB snapshot or RPC fetch). .. py:method:: swap_is_viable(state: CLState, vector: degenbot.uniswap.types.UniswapPoolSwapVector) -> bool Swap is viable. :returns: True if a swap can proceed with the given state, False otherwise. .. py:method:: update_tick_data(tick_bitmap: dict[int, Any], tick_data: dict[int, Any], block: int) -> None Apply updated tick bitmap and data from the tick data fetcher. Delegates to ``Pool.update_tick_data`` (replaces the Rust-side ``tick_data`` HashMap; scalars unchanged). The ``tick_bitmap`` KEYS are the checked words: for Sparse pools the FFI records them in Rust ``known_bitmap_words`` (a checked word is never re-fetched); the VALUES are NOT stored (the bitmap derives from the tick rows). Tracked pools record nothing (their bitmap is complete). .. py:method:: external_update(update: degenbot.uniswap.v3_types.UniswapV3PoolExternalUpdate | degenbot.uniswap.v4_types.UniswapV4PoolExternalUpdate) -> bool Process a family-external update (Swap event). Delegates the scalar write to ``Pool.apply_swap`` (journals the priors then lands the new ``sqrt_price_x96``/``liquidity``/ ``tick`` at ``block_number`` in one write guard). :returns: True if any updated state value was recorded, False otherwise. :raises ExternalUpdateError: If the update is for an invalid block. .. py:method:: update_liquidity_map(update: degenbot.uniswap.v3_types.UniswapV3PoolLiquidityMappingUpdate | degenbot.uniswap.v4_types.UniswapV4PoolLiquidityMappingUpdate) -> None Apply an update to the liquidity map (Mint/Burn/ModifyLiquidity). Delegates the tick mutation to ``Pool.apply_liquidity_update`` (Rust does the tick bitmap + tick_data mutation under one write guard). The active ``liquidity`` scalar adjustment (when ``current_tick`` is in range) is then landed via a separate ``apply_swap`` carrying the new scalar. :raises LiquidityMapWordMissing: A Sparse boundary word could not be backfilled (no stored fetcher or the fetch failed) — the event is NOT applied (a silent apply over an unknown word would corrupt the reorg journal's tick priors). .. py:method:: discard_states_before_block(block: degenbot.types.aliases.BlockNumber) -> None Discard cached states earlier than the given block. :raises NoPoolStateAvailable: If the target is past the newest delta. .. py:method:: restore_state_before_block(block: degenbot.types.aliases.BlockNumber) -> None Restore the last pool state recorded prior to a target block. Delegates to ``Pool.restore_v3_before_block`` (V3/V4-generic). :raises NoPoolStateAvailable: If no state exists prior to the target block.