Saltar a contenido

Fluid DEX LP (SmartLending)

Connector for Fluid's DEX LP surface (protocol="fluid_dex_lp"): fungible ERC-20-share, two-token liquidity positions over Fluid DEX pools via the SmartLending wrappers on Arbitrum. There is no NFT and no tick range — the wrapper share balance is the position. Direct pool LP is whitelist-gated on-chain, so the wrapper (the whitelisted supplier) is the only retail route; the compiler pre-flights deposit-enabled and refuses a disabled pool at compile. The fToken lending surface (protocol="fluid") is documented under Fluid and the vault borrow surface under Fluid Vault.

almanak.connectors.fluid_dex_lp

Fluid DEX LP (SmartLending) — thin third manifest over the fluid package.

Phase 4 (VIB-5032): Fluid SmartLending wrappers are fungible ERC-20-share, two-token DEX-LP positions (no NFT, no tick range). Direct pool LP is whitelist-gated (DexT1__UserSupplyInNotOn 51013, Phase-0 §V4) — the wrapper IS the whitelisted supplier, so an EOA/Safe LPs through it. Valued resolver-side (SmartLendingResolver.getSmartLendingEntireData → per-share token0/token1).

Distinct protocol key (fluid_dex_lp) keeps LP accounting keys (lp:fluid_dex_lp:{chain}:{wallet}:{wrapper}) separate from the fToken lending (fluid) and vault borrow (fluid_vault) surfaces. One codebase (all implementation in almanak.connectors.fluid), three manifests.

Example

from decimal import Decimal

from almanak.framework.intents import LPOpenIntent

intent = LPOpenIntent( protocol="fluid_dex_lp", pool="0x1F0bFd9862ae58208d26db0d80797974434EC013", # arbitrum fSL9 sUSDai/USDC amount0=Decimal("0"), # token0 (sUSDai) amount1=Decimal("2000"), # token1 (USDC) — single-sided OK range_lower=Decimal("0.5"), # dummy positive bounds (fungible: no range) range_upper=Decimal("2"), chain="arbitrum", )

FluidDexLpCompiler

Bases: BaseProtocolCompiler[BaseCompilerContext]

Compiler for Fluid SmartLending fungible-share DEX LP.

FluidSmartLendingSDK

FluidSmartLendingSDK(
    chain: str,
    resolver_address: str,
    rpc_url: str | None = None,
    gateway_client: GatewayClient | None = None,
)

Gateway-routed reads + tx builders for Fluid SmartLending LP.

get_smart_lending_data

get_smart_lending_data(wrapper: str) -> SmartLendingData

Read + SELF-VERIFY the resolver struct (VIB-5024 decode-fragility guard).

getSmartLendingEntireData is decoded by word position ([6]=totalSupply, [7]=reserve0, [8]=reserve1, [9]=token0, [10]=token1, [11]=dex, [14]=exchange_price). Because positional decoding of an undocumented resolver struct is the VIB-5024/5038 getSlot0 fragility class, every decoded address/total is cross-checked against the wrapper's OWN getters (TOKEN0/TOKEN1/DEX/totalSupply) before being trusted. Any mismatch fails closed.

position_token_amounts

position_token_amounts(
    wrapper: str, shares: int
) -> tuple[int, int]

Per-share proportional claim on the pool reserves (base units).

quote_deposit_shares

quote_deposit_shares(
    dex: str, token0_amt: int, token1_amt: int
) -> int

Estimate shares for a deposit via the DEX estimate revert-carrier.

DEX.deposit(t0, t1, 0, estimate=true) reverts with selector 0xe8d35d06 carrying the share amount in word 0 (verified on-chain; equals the wrapper mint when the exchange price is 1e18).

check_deposit_enabled

check_deposit_enabled(
    wrapper: str,
    token0_amt: int,
    token1_amt: int,
    wallet: str,
) -> None

Refuse a deposit-disabled pool at COMPILE (the 51013 pre-flight).

eth_call of the wrapper deposit with NO allowance: the UserSupplyInNotOn gate is checked BEFORE the token pull, so a disabled pool reverts 51013; an enabled pool reverts later on the token transferFrom (FluidSafeTransferError) — which we treat as ENABLED. No state overrides (gateway-safe, token-agnostic).

__getattr__

__getattr__(name: str) -> Any

PEP 562 lazy attribute access (no registration side effects here).

Implementation modules

The implementation lives in the fluid package (one codebase, three manifests):

almanak.connectors.fluid.smart_lending_sdk

Back-compat shim: fluid.smart_lending_sdk re-exports the shared implementation from almanak.connectors._fluid_core.smart_lending_sdk (single source of truth).

FluidDexLpError

Bases: FluidSDKError

SmartLending LP error.

FluidDexLpDepositDisabledError

Bases: FluidDexLpError

The target pool has deposits disabled (51013) — retryable later.

SmartLendingData dataclass

SmartLendingData(
    wrapper: str,
    dex: str,
    token0: str,
    token1: str,
    total_supply: int,
    reserve0: int,
    reserve1: int,
    exchange_price: int,
)

Decoded + self-verified SmartLending wrapper state.

FluidSmartLendingSDK

FluidSmartLendingSDK(
    chain: str,
    resolver_address: str,
    rpc_url: str | None = None,
    gateway_client: GatewayClient | None = None,
)

Gateway-routed reads + tx builders for Fluid SmartLending LP.

get_smart_lending_data

get_smart_lending_data(wrapper: str) -> SmartLendingData

Read + SELF-VERIFY the resolver struct (VIB-5024 decode-fragility guard).

getSmartLendingEntireData is decoded by word position ([6]=totalSupply, [7]=reserve0, [8]=reserve1, [9]=token0, [10]=token1, [11]=dex, [14]=exchange_price). Because positional decoding of an undocumented resolver struct is the VIB-5024/5038 getSlot0 fragility class, every decoded address/total is cross-checked against the wrapper's OWN getters (TOKEN0/TOKEN1/DEX/totalSupply) before being trusted. Any mismatch fails closed.

position_token_amounts

position_token_amounts(
    wrapper: str, shares: int
) -> tuple[int, int]

Per-share proportional claim on the pool reserves (base units).

quote_deposit_shares

quote_deposit_shares(
    dex: str, token0_amt: int, token1_amt: int
) -> int

Estimate shares for a deposit via the DEX estimate revert-carrier.

DEX.deposit(t0, t1, 0, estimate=true) reverts with selector 0xe8d35d06 carrying the share amount in word 0 (verified on-chain; equals the wrapper mint when the exchange price is 1e18).

check_deposit_enabled

check_deposit_enabled(
    wrapper: str,
    token0_amt: int,
    token1_amt: int,
    wallet: str,
) -> None

Refuse a deposit-disabled pool at COMPILE (the 51013 pre-flight).

eth_call of the wrapper deposit with NO allowance: the UserSupplyInNotOn gate is checked BEFORE the token pull, so a disabled pool reverts 51013; an enabled pool reverts later on the token transferFrom (FluidSafeTransferError) — which we treat as ENABLED. No state overrides (gateway-safe, token-agnostic).

__getattr__

__getattr__(name: str)

Re-export private / non-all names for back-compat (PEP 562).

almanak.connectors.fluid.dex_lp_compiler

Back-compat shim: fluid.dex_lp_compiler re-exports the shared implementation from almanak.connectors._fluid_core.dex_lp_compiler (single source of truth).

FluidDexLpCompiler

Bases: BaseProtocolCompiler[BaseCompilerContext]

Compiler for Fluid SmartLending fungible-share DEX LP.

__getattr__

__getattr__(name: str)

Re-export private / non-all names for back-compat (PEP 562).