Fluid DEX¶
Connector for the Fluid DEX (swap) and fToken (ERC-4626 lending) surfaces.
The vault borrow surface (NFT-CDP, protocol="fluid_vault") is documented
under Fluid Vault.
almanak.connectors.fluid
¶
Fluid DEX Connector — swap surface (Phase 1, VIB-5029).
Provides Fluid DEX exact-input swaps on arbitrum, base, ethereum, and polygon. Fluid is routerless: each pool is a per-pair contract; pool discovery and quoting go through the DexReservesResolver (quotes match on-chain execution to the wei — Phase-0 validation, VIB-5028).
Out of scope here (later phases): fToken lending SUPPLY/WITHDRAW (VIB-5030), vault BORROW/REPAY (VIB-5031), and LP via SmartLending / smart vaults (VIB-5032 — direct pool LP is whitelist-gated on-chain).
Key contracts (identical addresses on all supported chains): - DexFactory: 0x91716C4EDA1Fb55e84Bf8b4c7085f84285c19085 - DexReservesResolver: 0x05Bd8269A20C472b148246De20E6852091BF16Ff
Example
from almanak.connectors.fluid import FluidAdapter, FluidConfig
config = FluidConfig( chain="arbitrum", wallet_address="0x...", rpc_url="https://arb-mainnet.g.alchemy.com/v2/...", ) adapter = FluidAdapter(config)
FluidAdapter
¶
High-level adapter for Fluid DEX swap operations.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
config
|
FluidConfig
|
FluidConfig with chain, wallet, and transport settings |
必需 |
token_resolver
|
TokenResolver | None
|
Optional TokenResolver for symbol -> address resolution |
None
|
resolve_token_address
¶
Resolve a token symbol or address to checksummed address.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
token
|
str
|
Token symbol (e.g., "USDC") or address |
必需 |
返回:
| 类型 | 描述 |
|---|---|
str
|
Checksummed address |
get_token_decimals
¶
Get decimals for a token.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
token
|
str
|
Token symbol or address |
必需 |
返回:
| 类型 | 描述 |
|---|---|
int
|
Token decimals (never defaults to 18 — raises if unknown) |
find_pool
¶
Find a Fluid DEX pool for a token pair (order-insensitive).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
token0
|
str
|
First token symbol or address |
必需 |
token1
|
str
|
Second token symbol or address |
必需 |
返回:
| 类型 | 描述 |
|---|---|
str | None
|
Pool address if found, None otherwise |
find_pool_for_pair
¶
Find the pool and swap direction for an exact-input pair.
Returns (pool_address, swap0to1) or None.
get_pool_data
¶
Get full pool data (tokens + smart-collateral/debt flags).
get_swap_quote
¶
Quote an exact-input swap via the DexReservesResolver.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
token_in
|
str
|
Input token symbol or address |
必需 |
token_out
|
str
|
Output token symbol or address |
必需 |
amount_in
|
int
|
Input amount in the token's smallest unit |
必需 |
返回:
| 类型 | 描述 |
|---|---|
int
|
Expected output amount in the token's smallest unit |
引发:
| 类型 | 描述 |
|---|---|
FluidSDKError
|
If no pool exists or the quote fails |
FluidMinAmountError
|
If the size is limit-gated (retryable) |
build_swap_transaction
¶
build_swap_transaction(
token_in: str,
token_out: str,
amount_in: int,
amount_out_min: int,
value: int | None = None,
) -> TransactionData
Build a swapIn transaction for an exact-input swap.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
token_in
|
str
|
Input token symbol or address |
必需 |
token_out
|
str
|
Output token symbol or address |
必需 |
amount_in
|
int
|
Input amount in the token's smallest unit |
必需 |
amount_out_min
|
int
|
Minimum acceptable output (slippage protection) |
必需 |
value
|
int | None
|
Native value. Defaults to |
None
|
返回:
| 类型 | 描述 |
|---|---|
TransactionData
|
TransactionData targeting the per-pair pool contract |
build_approve_tx
¶
Build an ERC20 approval transaction.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
token_address
|
str
|
Token contract address |
必需 |
spender
|
str
|
Address to approve spending for |
必需 |
amount
|
int | None
|
Amount to approve (None = max uint256) |
None
|
返回:
| 类型 | 描述 |
|---|---|
TransactionData
|
TransactionData for the approval |
FluidConfig
dataclass
¶
FluidConfig(
chain: str,
wallet_address: str,
rpc_url: str | None = None,
default_slippage_bps: int = 50,
gateway_client: GatewayClient | None = None,
)
Configuration for Fluid DEX adapter.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
str
|
Chain name (any chain in |
必需 |
wallet_address
|
str
|
Address of the wallet executing transactions |
必需 |
rpc_url
|
str | None
|
DEPRECATED — direct RPC URL. Kept for ad-hoc script usage. Strategies running in isolated containers must use gateway_client. |
None
|
gateway_client
|
GatewayClient | None
|
Gateway client for routing eth_call through the gateway's RpcService. Preferred over rpc_url. |
None
|
default_slippage_bps
|
int
|
Default slippage tolerance in basis points (default: 50 = 0.5%) |
50
|
FluidCompiler
¶
Bases: BaseProtocolCompiler[SwapCompilerContext]
Fluid DEX swap compiler. SWAP-only, routerless (per-pool targets).
Subclasses BaseProtocolCompiler[SwapCompilerContext] because the
swap slippage / price-impact guard reads max_price_impact_pct and
using_placeholders — same shape as CamelotCompiler.
compile_swap
¶
Compile a Fluid DEX exact-input swap.
Pipeline: resolve tokens (native legs map to Fluid's 0xEeee…
sentinel — Fluid pools pair raw native, not WETH) → resolve the
per-pair pool + direction on-chain → quote via the reserves
resolver → price-impact guard → approve (ERC-20 input only) +
swapIn on the pool.
compile_supply
¶
Compile a Fluid fToken supply: approve + ERC-4626 deposit.
compile_withdraw
¶
Compile a Fluid fToken withdraw.
Exact amounts use ERC-4626 withdraw(assets, ...) behind a
maxWithdraw pre-flight; full exits (withdraw_all /
amount='all') use redeem(shares, ...) over the exact share
balance so rounding can never strand dust shares.
Fluid's withdrawal limits EXPAND OVER TIME: a request beyond the currently-withdrawable amount is a distinct, retryable failure — never a silent clamp, never a compiled-but-doomed transaction.
FluidReceiptParser
¶
Receipt parser for Fluid DEX transactions (swaps and LP operations).
Extracts NFT position IDs and token amounts from LogOperate events. Supports both LP_OPEN (new position) and LP_CLOSE (withdrawal) receipts.
SUPPORTED_EXTRACTIONS declares which ResultEnricher fields this parser supports.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
str
|
Chain name for token resolution (default: "arbitrum") |
'arbitrum'
|
parse_receipt
¶
Parse a Fluid DEX transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict with 'logs', 'transactionHash', etc. |
必需 |
返回:
| 类型 | 描述 |
|---|---|
FluidParseResult
|
FluidParseResult with extracted events and data |
extract_position_id
¶
Extract LP position NFT tokenId from receipt.
Called by ResultEnricher for LP_OPEN intents.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict |
必需 |
返回:
| 类型 | 描述 |
|---|---|
int | None
|
NFT position ID or None if not found |
extract_swap_amounts
¶
Extract swap amounts from receipt.
Called by ResultEnricher for SWAP intents. Resolves token decimals to produce human-readable decimal amounts (consistent with other parsers).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict |
必需 |
返回:
| 类型 | 描述 |
|---|---|
SwapAmounts | None
|
SwapAmounts with input/output amounts, or None |
extract_supply_amount
¶
Exact assets supplied, from the fToken's ERC-4626 Deposit event.
Called by ResultEnricher for SUPPLY intents (VIB-5030).
extract_withdraw_amount
¶
Exact assets withdrawn, from the fToken's ERC-4626 Withdraw event.
Both withdraw(assets, ...) and full-exit redeem(shares, ...)
emit the same event; assets is the underlying amount either way.
extract_lp_close_data
¶
Extract LP close data from receipt.
Called by ResultEnricher for LP_CLOSE intents. Returns amounts collected on withdrawal (negative amounts = withdrawn).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict |
必需 |
返回:
| 类型 | 描述 |
|---|---|
LPCloseData | None
|
LPCloseData with collected amounts, or None if not found |
extract_liquidity
¶
Extract liquidity amount from LP_OPEN receipt.
For Fluid DEX, liquidity is represented by the collateral shares (token0_amt + token1_amt deposited).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt dict |
必需 |
返回:
| 类型 | 描述 |
|---|---|
int | None
|
Combined deposit amount or None |
FluidSDK
¶
Low-level Fluid DEX protocol SDK.
Pool enumeration and swap quoting go through the DexReservesResolver
(single eth_call each); token-pair / smart-flag verification reads the
pool's constantsView() raw words.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
str
|
Chain name (one of |
必需 |
rpc_url
|
str | None
|
DEPRECATED — direct RPC URL. Bypasses the gateway and is only used for ad-hoc scripts. Prefer gateway_client for any code path that runs in a strategy container. |
None
|
gateway_client
|
GatewayClient | None
|
Gateway client used to route all eth_call traffic through the gateway's RpcService. Preferred over rpc_url for production code paths. |
None
|
get_all_dex_addresses
¶
Get all Fluid DEX pool addresses from the resolver.
get_all_pools
¶
Enumerate all pools with token pairs in a single eth_call.
Uses DexReservesResolver.getAllPools(). Smart-collateral/debt
flags are NOT populated here (use get_dex_data per pool when
needed); fee_raw is the resolver-reported raw fee value.
The result is cached for the lifetime of this SDK instance.
find_pool_for_pair
¶
Find the Fluid pool for a swap pair and the swap direction.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
token_in
|
str
|
Input token address ( |
必需 |
token_out
|
str
|
Output token address |
必需 |
返回:
| 类型 | 描述 |
|---|---|
tuple[str, bool] | None
|
|
tuple[str, bool] | None
|
|
find_dex_by_tokens
¶
Find a Fluid DEX pool for a token pair (order-insensitive).
get_dex_data
¶
Get pool data by calling constantsView() and readFromStorage().
Uses raw eth_call to avoid ABI decoding issues with the complex DexEntireData struct. constantsView() returns 18 words: - word[9]: token0 address - word[10]: token1 address
readFromStorage(bytes32(0)) returns dexVariables: - bit 1: isSmartCollateralEnabled - bit 2: isSmartDebtEnabled
get_swap_quote
¶
Quote an exact-input swap via DexReservesResolver.estimateSwapIn.
This is Fluid's official quote path; Phase-0 validation showed the
quote matches real swapIn output to the wei.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
dex_address
|
str
|
Pool contract address |
必需 |
swap0to1
|
bool
|
True to swap token0->token1, False for token1->token0 |
必需 |
amount_in
|
int
|
Input amount in the token's smallest unit |
必需 |
返回:
| 类型 | 描述 |
|---|---|
int
|
Expected output amount in the token's smallest unit |
引发:
| 类型 | 描述 |
|---|---|
FluidMinAmountError
|
The size is rejected by the pool's time-expanding limits (retryable later / at smaller size). |
FluidSDKError
|
Any other quote failure. |
encode_swap_in_calldata
¶
ABI-encode swapIn calldata (offline — no RPC interaction).
build_swap_tx
¶
build_swap_tx(
dex_address: str,
swap0to1: bool,
amount_in: int,
amount_out_min: int,
to: str,
value: int = 0,
) -> dict[str, Any]
Build a swapIn transaction for a Fluid DEX pool.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
dex_address
|
str
|
Pool contract address |
必需 |
swap0to1
|
bool
|
True to swap token0->token1, False for token1->token0 |
必需 |
amount_in
|
int
|
Input amount in token's smallest unit |
必需 |
amount_out_min
|
int
|
Minimum acceptable output (slippage protection) |
必需 |
to
|
str
|
Recipient address |
必需 |
value
|
int
|
Native token value (must equal amount_in for native-input swaps; 0 for ERC-20 inputs) |
0
|
返回:
| 类型 | 描述 |
|---|---|
dict[str, Any]
|
Transaction dict with 'to', 'data', 'value', 'gas' |
get_all_ftokens
¶
Enumerate the chain's Fluid fTokens via the LendingResolver.
The result is cached for the lifetime of this SDK instance (fToken listings change rarely; SDK instances are per-compile).
find_ftoken_for_underlying
¶
Resolve the fToken whose ERC-4626 asset() is underlying.
Fluid lists exactly one fToken per underlying per chain, so the first match is THE market. Returns None when Fluid has no market for the asset on this chain.
get_max_withdraw
¶
ERC-4626 maxWithdraw(owner) — reflects Fluid's time-expanding
withdrawal limits, NOT just the owner's balance. The compile-time
pre-flight reads this to distinguish "limit-gated, retry later" from
a hard failure.
get_max_redeem
¶
ERC-4626 maxRedeem(owner) in shares (limit-aware).
get_ftoken_share_balance
¶
fToken share balance of owner (ERC-20 balanceOf on the vault).
convert_to_assets
¶
ERC-4626 convertToAssets(shares) — underlying value of shares.
build_deposit_tx
¶
Build an ERC-4626 deposit(assets, receiver) transaction.
build_withdraw_tx
¶
Build an ERC-4626 withdraw(assets, receiver, owner) transaction.
build_redeem_tx
¶
Build an ERC-4626 redeem(shares, receiver, owner) transaction.
Full exits go through redeem-by-shares (never withdraw-by-assets): burning the exact share balance cannot strand rounding dust.