Skip to content

Curve

Field Value
Module almanak.connectors.curve
Protocol kind LP
Aliases N/A

Supported Chains And Intents

Chain Family Supported Intents
Arbitrum EVM LP_CLOSE, LP_OPEN, SWAP
Base EVM LP_CLOSE, LP_OPEN, SWAP
Ethereum EVM LP_CLOSE, LP_OPEN, SWAP
Optimism EVM LP_CLOSE, LP_OPEN, SWAP
Polygon EVM LP_CLOSE, LP_OPEN, SWAP

curve

Curve Finance Connector.

This module provides the Curve Finance adapter for executing swaps and managing liquidity positions on Curve pools across multiple chains.

Supported chains: - Ethereum - Arbitrum

Supported operations: - SWAP: Token swaps via Curve pools (StableSwap, CryptoSwap, Tricrypto) - LP_OPEN: Add liquidity to Curve pools - LP_CLOSE: Remove liquidity from Curve pools

Example
from almanak.connectors.curve import CurveAdapter, CurveConfig

config = CurveConfig(
    chain="ethereum",
    wallet_address="0x...",
)
adapter = CurveAdapter(config)

# Execute a swap
result = adapter.swap(
    pool_address="0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7",  # 3pool
    token_in="USDC",
    token_out="DAI",
    amount_in=Decimal("1000"),
)

# Add liquidity
lp_result = adapter.add_liquidity(
    pool_address="0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7",
    amounts=[Decimal("1000"), Decimal("1000"), Decimal("1000")],  # DAI, USDC, USDT
)

CurveAdapter

CurveAdapter(
    config: CurveConfig,
    token_resolver: TokenResolver | None = None,
)

Adapter for Curve Finance DEX protocol.

This adapter provides methods for: - Executing token swaps via Curve pools - Adding liquidity to pools (LP_OPEN) - Removing liquidity from pools (LP_CLOSE) - Handling ERC-20 approvals - Managing slippage protection

Example
config = CurveConfig(
    chain="ethereum",
    wallet_address="0x...",
)
adapter = CurveAdapter(config)

# Execute a swap on 3pool
result = adapter.swap(
    pool_address="0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7",
    token_in="USDC",
    token_out="DAI",
    amount_in=Decimal("1000"),
)

Initialize the adapter.

Parameters:

Name Type Description Default
config CurveConfig

Curve adapter configuration

required
token_resolver TokenResolver | None

Optional TokenResolver instance. If None, uses singleton.

None

get_pool_info

get_pool_info(
    pool_address: str, *, refresh: bool = True
) -> PoolInfo | None

Get information about a pool.

The deployment binding is the cold-start value; when a gateway or RPC is wired the registry is reconciled against live chain state (coins / coin_addresses / decimals / virtual_price / is_ng) before being returned — see _refresh_pool_info_from_chain (VIB-5423 / VIB-5424).

Parameters:

Name Type Description Default
pool_address str

Pool contract address

required
refresh bool

When True (default, calldata-producing paths) bound metadata is reconciled against chain truth. When False the read-only quote / pair-resolution path opts out of the network reconcile (VIB-5423) — a warm cache entry is still reused, but no new RPC reads are issued. is_ng / virtual_price are irrelevant to a get_dy quote, so paying for them on every slippage estimate (with a fresh per-quote adapter) is wasteful.

True

Returns:

Type Description
PoolInfo | None

PoolInfo if known, None otherwise

get_pool_by_name

get_pool_by_name(
    name: str, *, refresh: bool = True
) -> PoolInfo | None

Get pool info by name.

Same refresh-on-read reconciliation as get_pool_info (VIB-5423); refresh=False opts the read-only quote path out of the reconcile.

Parameters:

Name Type Description Default
name str

Deployment-scoped pool name, when one was explicitly supplied.

required
refresh bool

See get_pool_info.

True

Returns:

Type Description
PoolInfo | None

PoolInfo if found, None otherwise

swap

swap(
    pool_address: str,
    token_in: str,
    token_out: str,
    amount_in: Decimal,
    slippage_bps: int | None = None,
    recipient: str | None = None,
    price_ratio: Decimal | None = None,
    oracle_guard_bps: int | None = None,
    strict_oracle_guard: bool = False,
    oracle_prices_real: bool = True,
) -> SwapResult

Build a swap transaction on a Curve pool.

Parameters:

Name Type Description Default
pool_address str

Pool contract address

required
token_in str

Input token symbol or address

required
token_out str

Output token symbol or address

required
amount_in Decimal

Amount of input token (in token units, not wei)

required
slippage_bps int | None

Slippage tolerance in basis points (default from config)

None
recipient str | None

Address to receive output tokens (default: wallet_address)

None
price_ratio Decimal | None

Price of input token / price of output token (e.g., if swapping USDT at $1 for WETH at $2500, price_ratio = 1/2500 = 0.0004). Required for CryptoSwap/Tricrypto pools; StableSwap pools ignore it. When None and pool is CryptoSwap, the swap fails (fail-closed) rather than executing with inaccurate slippage protection. Also the independent oracle reference for the P0-8 min-out guard below.

None
oracle_guard_bps int | None

max bps the pool quote may sit below oracle-fair before the swap is blocked as pre-moved (VIB-5439). None uses DEFAULT_SWAP_ORACLE_DIVERGENCE_BPS. Separate from slippage_bps (which buffers the floor below the pool quote).

None
strict_oracle_guard bool

when no oracle price_ratio is available, fail closed instead of degrading open to pool-self-referential min-out.

False
oracle_prices_real bool

whether price_ratio is a real oracle reference. False (placeholder / offline-price mode) makes the guard treat the oracle as unmeasured so it never fires on a known-fake price, while price_ratio still feeds the CryptoSwap slippage estimate.

True

Returns:

Type Description
SwapResult

SwapResult with transaction data

add_liquidity

add_liquidity(
    pool_address: str,
    amounts: list[Decimal],
    slippage_bps: int | None = None,
    recipient: str | None = None,
) -> LiquidityResult

Build an add_liquidity transaction (LP_OPEN).

Parameters:

Name Type Description Default
pool_address str

Pool contract address

required
amounts list[Decimal]

List of token amounts to deposit (in token units)

required
slippage_bps int | None

Slippage tolerance for min LP tokens (default from config). For CryptoSwap/Tricrypto (volatile) pools the min_lp floor is the build-time on-chain quote × (1 − slippage); if the pool price drifts between build and execution by more than slippage_bps the add_liquidity reverts with "Slippage". A revert is fail-safe (no loss, vs the old min_lp=0 which could be sandwiched), but a volatile or large deposit may need a wider slippage_bps than the stable default to avoid a benign revert (VIB-5441).

None
recipient str | None

Address to receive LP tokens (default: wallet_address)

None

Returns:

Type Description
LiquidityResult

LiquidityResult with transaction data

remove_liquidity

remove_liquidity(
    pool_address: str,
    lp_amount: Decimal,
    slippage_bps: int | None = None,
    recipient: str | None = None,
) -> LiquidityResult

Build a remove_liquidity transaction (LP_CLOSE, proportional).

A proportional withdrawal mirrors the pool's current reserve composition: burning LP pays out each coin pro rata to the on-chain reserves. A skewed pool therefore returns skewed per-coin amounts even when the position was funded evenly. That output shape is expected. Callers that need a specific exit shape should use remove_liquidity_one_coin or remove_liquidity_imbalance.

Per-coin min_amounts floors are derived from the on-chain proportional estimate after applying slippage_bps. The build fails closed when no non-zero estimate is available.

Parameters:

Name Type Description Default
pool_address str

Pool contract address

required
lp_amount Decimal

Amount of LP tokens to burn

required
slippage_bps int | None

Slippage tolerance for min output (default from config)

None
recipient str | None

Address to receive tokens (default: wallet_address)

None

Returns:

Type Description
LiquidityResult

LiquidityResult with transaction data. amounts contains the

LiquidityResult

per-coin minimum-received floors in native token base units.

remove_liquidity_one_coin

remove_liquidity_one_coin(
    pool_address: str,
    lp_amount: Decimal,
    coin_index: int,
    slippage_bps: int | None = None,
    recipient: str | None = None,
) -> LiquidityResult

Build a remove_liquidity_one_coin transaction (LP_CLOSE, single-sided).

Parameters:

Name Type Description Default
pool_address str

Pool contract address

required
lp_amount Decimal

Amount of LP tokens to burn

required
coin_index int

Index of the coin to receive

required
slippage_bps int | None

Slippage tolerance (default from config)

None
recipient str | None

Address to receive tokens (default: wallet_address)

None

Returns:

Type Description
LiquidityResult

LiquidityResult with transaction data

remove_liquidity_imbalance

remove_liquidity_imbalance(
    pool_address: str,
    amounts: list[Decimal],
    lp_amount: Decimal,
    slippage_bps: int | None = None,
    recipient: str | None = None,
) -> LiquidityResult

Build a remove_liquidity_imbalance transaction (LP_CLOSE, imbalanced).

remove_liquidity_imbalance(uint256[N] amounts, uint256 max_burn_amount) works the OPPOSITE way to single-sided removal: the caller names the EXACT per-coin amounts to receive, and the pool burns however much LP is needed, capped at max_burn_amount. So the safety floor here is a MAX-BURN CEILING (the most LP we will spend), NOT a min-out (VIB-5438, audit P0-4).

The ceiling is derived from the pool's on-chain calc_token_amount(amounts, is_deposit=False) LP-burn quote, padded UP by slippage_bps (the inverse of the single-sided min-out, which pads DOWN). The slippage buffer absorbs the imbalance fee the legacy calc_token_amount excludes; if it is too tight the pool reverts on-chain ("Slippage screwed you") — safe.

Fail-closed: this NEVER emits max_burn_amount = MAX_UINT256 or any unbounded cap (that would let the pool burn the entire LP balance for a tiny withdrawal — a theft/sandwich vector). If the on-chain quote is unavailable/reverts, or the requested withdrawal would need more LP than the position holds, the compile fails loudly (mirrors the #3092 min-out and

3073 min_lp logic).

Parameters:

Name Type Description Default
pool_address str

Pool contract address

required
amounts list[Decimal]

EXACT per-coin amounts to withdraw, in human units, positional by pool-coin index (length MUST equal the pool's coin count).

required
lp_amount Decimal

LP tokens HELD by the position (human units), the upper bound on what may be burned. The derived max_burn is capped at this; a request needing more fails closed.

required
slippage_bps int | None

Max-burn buffer over the on-chain quote (default config).

None
recipient str | None

Address to receive tokens (default: wallet_address).

None

Returns:

Type Description
LiquidityResult

LiquidityResult with transaction data (operation

LiquidityResult

remove_liquidity_imbalance), or success=False on any guard.

swap_underlying

swap_underlying(
    pool_address: str,
    token_in: str,
    token_out: str,
    amount_in: Decimal,
    slippage_bps: int | None = None,
    recipient: str | None = None,
    price_ratio: Decimal | None = None,
    oracle_guard_bps: int | None = None,
    strict_oracle_guard: bool = False,
    oracle_prices_real: bool = True,
) -> SwapResult

Build a metapool underlying swap via exchange_underlying.

Routes a swap across the COMBINED coin space of a metapool (index 0 = meta coin, 1..N = base-pool coins) — e.g. FRAX -> USDC through a FRAX/3CRV metapool. exchange_underlying lives on the metapool contract itself (NOT the zap); the metapool transparently routes the leg through its base pool.

Stablecoin-only assumption: every coin on a 3CRV/FRAX-style metapool's combined space is a USD stable, so the 1:1 decimal-adjusted estimate (the same the StableSwap path uses) is the correct slippage floor, and the on-chain get_dy_underlying quote is preferred when a gateway / rpc is wired.

add_liquidity_underlying

add_liquidity_underlying(
    pool_address: str,
    underlying_amounts: list[Decimal],
    slippage_bps: int | None = None,
    recipient: str | None = None,
) -> LiquidityResult

Build a metapool deposit over the COMBINED coin space via the zap.

underlying_amounts is indexed in COMBINED order: index 0 = meta coin, indices 1..N = base-pool coins (DAI/USDC/USDT). The generic 3CRV DepositZap's ABI takes the metapool as the first argument: add_liquidity(address _pool, uint256[N+1] _deposit, uint256 _min_mint). It deposits the base coins into the base pool (minting the base-LP), then the base-LP plus the meta coin into the metapool — a user only has to hold/approve the underlying coins.

remove_liquidity_underlying

remove_liquidity_underlying(
    pool_address: str,
    lp_amount: Decimal,
    slippage_bps: int | None = None,
    recipient: str | None = None,
) -> LiquidityResult

Build a metapool proportional withdrawal to underlying coins via the zap.

Burns lp_amount metapool LP and returns the COMBINED underlying coins (meta coin + base-pool coins) using the generic zap's remove_liquidity(address _pool, uint256 _amount, uint256[N+1] _min_amounts). The min-amounts vector is derived from the metapool's native proportional split (meta coin + base-LP), then the base-LP leg is decomposed across the base pool's coins by its on-chain reserves. When the on-chain reads are unavailable, fails closed (no slippage floor) — mirrors the native remove_liquidity guard.

quote_swap_output

quote_swap_output(
    *,
    pool_address: str,
    token_in: str,
    token_out: str,
    amount_in_wei: int,
) -> int

Quote a Curve exact-input swap with the pool's on-chain quote method.

set_allowance

set_allowance(
    token: str, spender: str, amount: int
) -> None

Set cached allowance (for testing).

Parameters:

Name Type Description Default
token str

Token address

required
spender str

Spender address

required
amount int

Allowance amount

required

clear_allowance_cache

clear_allowance_cache() -> None

Clear the allowance cache.

clear_planned_allowance_cache

clear_planned_allowance_cache() -> None

Clear optimistic approvals emitted into the current bundle.

CurveConfig dataclass

CurveConfig(
    chain: str,
    wallet_address: str,
    default_slippage_bps: int = 50,
    deadline_seconds: int = 300,
    rpc_url: str | None = None,
    gateway_client: GatewayClient | None = None,
    permission_discovery: bool = False,
    force_is_ng: bool | None = None,
    permission_pool_overrides: dict[
        str, dict[str, Any]
    ] = dict(),
)

Configuration for CurveAdapter.

Attributes:

Name Type Description
chain str

Target blockchain (ethereum, arbitrum)

wallet_address str

Address executing transactions

default_slippage_bps int

Default slippage tolerance in basis points (default 50 = 0.5%)

deadline_seconds int

Transaction deadline in seconds (default 300 = 5 minutes)

rpc_url str | None

Optional JSON-RPC URL for on-chain state queries (e.g., pool balances for accurate remove_liquidity slippage estimates). When provided, the adapter queries pool.balances(i) and lp_token.totalSupply() to compute proportional min_amounts rather than returning zeros. When absent or on RPC failure, min_amounts fall back to [0, 0, ..., 0] with a warning.

LiquidityResult dataclass

LiquidityResult(
    success: bool,
    transactions: list[TransactionData] = list(),
    pool_address: str = "",
    operation: str = "",
    amounts: list[int] = list(),
    lp_amount: int = 0,
    error: str | None = None,
    gas_estimate: int = 0,
)

Result of a liquidity operation.

Attributes:

Name Type Description
success bool

Whether the operation was built successfully

transactions list[TransactionData]

List of transactions to execute

pool_address str

Pool address

operation str

Operation type (add_liquidity, remove_liquidity, remove_liquidity_one_coin)

amounts list[int]

Token amounts for the operation

lp_amount int

LP token amount (minted or burned)

error str | None

Error message if failed

gas_estimate int

Total gas estimate

PoolInfo dataclass

PoolInfo(
    address: str,
    lp_token: str,
    coins: list[str],
    coin_addresses: list[str],
    pool_type: PoolType,
    n_coins: int,
    name: str = "",
    virtual_price: Decimal = (lambda: Decimal("1.0"))(),
    use_underlying: bool = False,
    is_ng: bool = False,
    coin_decimals: list[int] | None = None,
    is_metapool: bool = False,
    base_pool: str | None = None,
    base_pool_coins: list[str] | None = None,
    base_pool_coin_addresses: list[str] | None = None,
    zap_address: str | None = None,
)

Information about a Curve pool.

Attributes:

Name Type Description
address str

Pool contract address

lp_token str

LP token address

coins list[str]

List of coin symbols

coin_addresses list[str]

List of coin addresses

pool_type PoolType

Type of pool (stableswap, cryptoswap, tricrypto)

n_coins int

Number of coins in pool

name str

Pool name

virtual_price Decimal

Pool virtual price (LP token value relative to underlying). Mature pools accumulate fees so virtual_price > 1.0. Used to adjust LP token estimates to prevent over-estimation that causes add_liquidity reverts.

underlying_coin_index

underlying_coin_index(coin: str) -> int | None

Return the COMBINED-space index of coin for a metapool, or None.

Combined index 0 is always the meta coin (coins[0]); indices 1..N map to base_pool_coins / base_pool_coin_addresses in order. coin may be a symbol or an address. Returns None when this is not a metapool or coin is neither the meta coin nor a base-pool coin — the caller then falls back to the native 2-coin path.

get_coin_index

get_coin_index(coin: str) -> int

Get the index of a coin in the pool.

Parameters:

Name Type Description Default
coin str

Coin symbol or address

required

Returns:

Type Description
int

Index of the coin

Raises:

Type Description
ValueError

If coin not found in pool

PoolType

Bases: Enum

Curve pool type.

SwapResult dataclass

SwapResult(
    success: bool,
    transactions: list[TransactionData] = list(),
    pool_address: str = "",
    amount_in: int = 0,
    amount_out_minimum: int = 0,
    amount_out_estimate: int = 0,
    token_out_decimals: int = 18,
    token_in: str = "",
    token_out: str = "",
    error: str | None = None,
    gas_estimate: int = 0,
)

Result of a swap operation.

Attributes:

Name Type Description
success bool

Whether the swap was built successfully

transactions list[TransactionData]

List of transactions to execute

pool_address str

Pool used for swap

amount_in int

Input amount in wei

amount_out_minimum int

Minimum output amount (with slippage)

token_in str

Input token address

token_out str

Output token address

error str | None

Error message if failed

gas_estimate int

Total gas estimate

TransactionData dataclass

TransactionData(
    to: str,
    value: int,
    data: str,
    gas_estimate: int,
    description: str,
    tx_type: str = "swap",
)

Transaction data for execution.

Attributes:

Name Type Description
to str

Target contract address

value int

Native token value to send

data str

Encoded calldata

gas_estimate int

Estimated gas

description str

Human-readable description

tx_type str

Type of transaction (approve, swap, add_liquidity, remove_liquidity)

CurvePoolPermissionBinding dataclass

CurvePoolPermissionBinding(
    chain: str,
    pool_address: str,
    coin_symbols: tuple[str, ...],
    coin_addresses: tuple[str, ...],
    coin_decimals: tuple[int, ...],
    lp_token: str,
    n_coins: int,
    pool_type: PoolTypeName,
    abi_families: tuple[str, ...],
    is_metapool: bool,
    base_pool: str | None = None,
    base_pool_coin_addresses: tuple[str, ...] | None = None,
)

Immutable identity of one deployment-selected Curve pool.

from_metadata classmethod

from_metadata(
    chain: str, metadata: Any
) -> CurvePoolPermissionBinding

Freeze a fully resolved CurvePoolMetadata value.

from_pool_data classmethod

from_pool_data(
    chain: str, pool_data: Mapping[str, Any]
) -> CurvePoolPermissionBinding

Freeze the compiler's canonical resolved pool shape as a candidate.

marker_params

marker_params() -> dict[str, Any]

Return connector-parameter fields for a bound synthetic intent.

pool_data

pool_data() -> dict[str, Any]

Return the registry-shaped subset needed to construct vectors.

assert_matches_pool_data

assert_matches_pool_data(
    *, chain: str, pool_data: Mapping[str, Any]
) -> None

Fail if runtime resolution differs from the admitted identity.

AddLiquidityEventData dataclass

AddLiquidityEventData(
    provider: str,
    token_amounts: list[int],
    fees: list[int],
    invariant: int,
    token_supply: int,
    pool_address: str,
)

Parsed data from AddLiquidity event.

CurveEvent dataclass

CurveEvent(
    event_type: CurveEventType,
    event_name: str,
    log_index: int,
    transaction_hash: str,
    block_number: int,
    contract_address: str,
    data: dict[str, Any],
    raw_topics: list[str] = list(),
    raw_data: str = "",
    timestamp: datetime = (lambda: datetime.now(UTC))(),
)

Parsed Curve event.

CurveEventType

Bases: Enum

Curve event types.

CurveReceiptParser

CurveReceiptParser(
    chain: str = "ethereum",
    *,
    pool_meta_lookup: PoolMetaLookup | None = None,
    **kwargs: Any,
)

Bases: FailClosedExtractMixin

Parser for Curve Finance transaction receipts.

Initialize with an optional live pool-metadata lookup.

parse_receipt

parse_receipt(receipt: dict[str, Any]) -> ParseResult

Parse a transaction receipt.

extract_swap_amounts

extract_swap_amounts(
    receipt: dict[str, Any],
    *,
    expected_out: Decimal | None = None,
) -> SwapAmounts | None

Extract swap amounts using Transfer addresses and resolved decimals.

expected_out is a human-unit pre-slippage quote used to calculate realized basis points. Unknown decimals fail closed instead of assuming 18.

extract_position_id

extract_position_id(
    receipt: dict[str, Any],
) -> int | str | None

Return the minted fungible LP token address as the position identifier.

extract_liquidity

extract_liquidity(
    receipt: dict[str, Any],
) -> Decimal | None

Return minted LP tokens in human units, not raw wei.

extract_lp_tokens_received

extract_lp_tokens_received(
    receipt: dict[str, Any],
) -> Decimal | None

Return a zero-address mint Transfer in human LP-token units.

extract_lp_open_data

extract_lp_open_data(
    receipt: dict[str, Any],
) -> LPOpenData | None

Extract an AddLiquidity event for a fungible, tickless Curve position.

The emitter is the canonical pool address and position_id=0 denotes no per-position discriminator. Absent amount slots remain unmeasured None; emitted zero amounts remain measured zero.

extract_primitive_money_legs

extract_primitive_money_legs(
    receipt: dict[str, Any],
) -> PrimitiveMoneyLegs | None

Declare one input leg per funded pool-ordered AddLiquidity amount.

Unknown or incomplete coin metadata, no funded coins, and extraction failures return None for the legacy path rather than guessing identity.

extract_lp_close_data

extract_lp_close_data(
    receipt: dict[str, Any],
) -> LPCloseData | None

Extract pool-ordered proceeds from any supported liquidity removal.

extract_protocol_fees

extract_protocol_fees(
    receipt: dict[str, Any],
) -> ProtocolFees

Report Curve receipt-level protocol fees as unavailable.

Curve NG pools encode fees arrays in AddLiquidity/RemoveLiquidity events, but those are token-unit LP fees. The admin fee is not emitted, and this layer has no price oracle for USD conversion.

extract_swap_amounts_result

extract_swap_amounts_result(
    receipt: dict[str, Any],
    *,
    expected_out: Decimal | None = None,
) -> ExtractResult[SwapAmounts]

Extract swap amounts, treating failure on a present swap as an error.

expected_out is forwarded for realized slippage calculation.

extract_position_id_result

extract_position_id_result(
    receipt: dict[str, Any],
) -> ExtractResult[Any]

Extract position ID, treating failure on a present mint as an error.

extract_liquidity_result

extract_liquidity_result(
    receipt: dict[str, Any],
) -> ExtractResult[Decimal]

Extract liquidity, treating failure on a present mint as an error.

extract_lp_tokens_received_result

extract_lp_tokens_received_result(
    receipt: dict[str, Any],
) -> ExtractResult[Decimal]

Extract received LP tokens, failing closed when a mint is present.

extract_lp_open_data_result

extract_lp_open_data_result(
    receipt: dict[str, Any],
) -> ExtractResult[LPOpenData]

Extract LP-open data, failing closed when AddLiquidity is present.

extract_primitive_money_legs_result

extract_primitive_money_legs_result(
    receipt: dict[str, Any],
) -> ExtractResult[PrimitiveMoneyLegs]

Extract declared legs while preserving the intentional legacy fallback.

Unlike other fields, None with AddLiquidity present is benign when coin metadata cannot safely bind amounts; LP-open extraction guards decode failure.

extract_lp_close_data_result

extract_lp_close_data_result(
    receipt: dict[str, Any],
) -> ExtractResult[LPCloseData]

Extract LP-close data, failing closed when a removal is present.

extract_protocol_fees_result

extract_protocol_fees_result(
    receipt: dict[str, Any],
) -> ExtractResult[ProtocolFees]

Return unavailable fee metadata unless extraction itself fails.

is_curve_event

is_curve_event(topic: str | bytes) -> bool

Return whether a bytes or hex-string topic is a known Curve event.

get_event_type

get_event_type(topic: str | bytes) -> CurveEventType

Return the Curve event type for a bytes or hex-string topic.

ParseResult dataclass

ParseResult(
    success: bool,
    events: list[CurveEvent] = list(),
    swap_events: list[SwapEventData] = list(),
    error: str | None = None,
    transaction_hash: str = "",
    block_number: int = 0,
    transaction_success: bool = True,
)

Result of parsing a receipt.

RemoveLiquidityEventData dataclass

RemoveLiquidityEventData(
    provider: str,
    token_amounts: list[int],
    fees: list[int],
    token_supply: int,
    pool_address: str,
)

Parsed data from RemoveLiquidity event.

SwapEventData dataclass

SwapEventData(
    buyer: str,
    sold_id: int,
    tokens_sold: int,
    bought_id: int,
    tokens_bought: int,
    pool_address: str,
)

Parsed data from TokenExchange event.