Fluid Vault (NFT-CDP)¶
Connector for Fluid's vault borrow surface (protocol="fluid_vault"):
NFT-CDP lending positions driven by a single signed-delta operate()
entrypoint per type-1 vault on Arbitrum and Base. market_id is the vault
address and is required on every intent; the fToken lending surface
(protocol="fluid") is documented under Fluid.
almanak.connectors.fluid_vault
¶
Fluid vault (NFT-CDP) connector — thin second manifest over the fluid package.
Phase 3 (VIB-5031, ADR r2 Q0): Fluid vault borrow positions are NFT-CDPs
driven by a single signed-delta operate() entrypoint per vault, with
market_id (the vault address) REQUIRED — while the shipped Phase-2
fToken surface (protocol="fluid" / "fluid_lending") REJECTS any
market_id. One protocol key cannot demand and forbid market_id
simultaneously, so vault lending is its own connector registration:
protocol="fluid_vault", one codebase (all implementation modules live
in almanak.connectors.fluid), two manifests.
Scope (Checkpoint-1): arbitrum + base, type-1 vaults only. Position keys:
lending:{chain}:fluid_vault:{wallet}:{vault}:{asset} (vault lowercased;
the nftId is metadata in extracted_data_json, never a key segment).
Example
from decimal import Decimal
from almanak.framework.intents import BorrowIntent
intent = BorrowIntent( protocol="fluid_vault", market_id="0xeAbBfca72F8a8bf14C4ac59e69ECB2eB69F0811C", # arbitrum vault id 1 collateral_token="ETH", collateral_amount=Decimal("1"), borrow_token="USDC", borrow_amount=Decimal("500"), chain="arbitrum", )
FluidVaultCompiler
¶
Bases: BaseLendingCompiler
Compile fluid_vault SUPPLY / BORROW / REPAY / WITHDRAW / DELEVERAGE.
DELEVERAGE routes to :meth:compile_repay via the
:class:BaseLendingCompiler dispatch (framework convention: a
deleverage is a repay with risk context).
FluidVaultSDK
¶
FluidVaultSDK(
chain: str,
rpc_url: str | None = None,
gateway_client: GatewayClient | None = None,
)
Low-level Fluid vault (NFT-CDP) protocol SDK.
All reads go through the VaultResolver with typed-ABI decoding; writes
are offline calldata builders for the vault's operate() entrypoint.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
str
|
Chain name (one of |
必需 |
rpc_url
|
str | None
|
DEPRECATED — direct RPC URL for ad-hoc scripts/tests only. |
None
|
gateway_client
|
GatewayClient | None
|
Gateway client routing all eth_call traffic through the gateway's RpcService. Preferred for production code paths. |
None
|
get_vault_entire_data
¶
VaultResolver.getVaultEntireData(vault) — 97-word typed decode.
position_by_nft_id
¶
VaultResolver.positionByNftId(nftId) — (12 + 97)-word typed decode.
positions_by_user
¶
VaultResolver.positionsByUser(wallet) — every position with its vault.
The two returned arrays are index-aligned (position i ↔ its vault's data at i — verification report D1), so each position carries its lowercased vault address. No pagination exists; cost is bounded by the one-NFT-per-(wallet,vault) invariant.
resolve_user_nft_for_vault
¶
Resolve the wallet's nftId on vault fresh from chain state.
The VIB-5010 answer: chain is the source of truth — persisted nftIds
are never load-bearing. Returns None when the wallet holds no
position NFT on the vault (the measured "no position" answer —
distinct from a read failure, which RAISES FluidSDKError so the
compiler fails closed instead of minting a duplicate position).
If the wallet somehow holds MULTIPLE NFTs on one vault (user acted outside the SDK), selection is deterministic: lowest nftId wins, with a warning — the others stay invisible by design (ADR §1.1).
encode_operate_calldata
¶
ABI-encode operate(nftId, newCol, newDebt, to) calldata.
Signed deltas: positive = deposit/borrow, negative = withdraw/repay,
INT256_MIN = the protocol max sentinel (full withdraw/repay).
build_operate_tx
¶
build_operate_tx(
vault: str,
nft_id: int,
col_delta: int,
debt_delta: int,
to: str,
value: int = 0,
) -> dict[str, Any]
Build an operate() transaction for a Fluid type-1 vault.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
vault
|
str
|
Vault contract address (the per-market operate target). |
必需 |
nft_id
|
int
|
Position NFT id (0 mints a new position). |
必需 |
col_delta
|
int
|
Signed collateral delta (raw units; INT256_MIN = all). |
必需 |
debt_delta
|
int
|
Signed debt delta (raw units; INT256_MIN = full repay). |
必需 |
to
|
str
|
Recipient of withdrawn collateral / borrowed debt. |
必需 |
value
|
int
|
msg.value — MUST equal |
0
|
__getattr__
¶
PEP 562 lazy attribute access (no registration side effects here).
Implementation modules¶
The implementation lives in the fluid package (one codebase, two
manifests):
almanak.connectors.fluid.vault_sdk
¶
Back-compat shim: fluid.vault_sdk re-exports the shared implementation from
almanak.connectors._fluid_core.vault_sdk (single source of truth).
FluidVaultPosition
dataclass
¶
FluidVaultPosition(
nft_id: int,
owner: str,
is_liquidated: bool,
is_supply_position: bool,
tick: int,
tick_id: int,
supply: int,
borrow: int,
dust_borrow: int,
vault: str = "",
)
One decoded UserPosition (+ the vault it belongs to, when paired).
supply / borrow are exchange-price-scaled TOKEN amounts in the
vault pair's native base units (verification report note 4); borrow
already has dust_borrow netted out.
FluidVaultData
dataclass
¶
FluidVaultData(
vault: str,
is_smart_col: bool,
is_smart_debt: bool,
supply_token: str,
borrow_token: str,
vault_id: int,
vault_type: int,
collateral_factor: int,
liquidation_threshold: int,
liquidation_max_limit: int,
liquidation_penalty: int,
oracle: str,
oracle_price_operate: int,
oracle_price_liquidate: int,
withdrawable: int,
borrowable: int,
total_supply_vault: int,
total_borrow_vault: int,
)
The VaultEntireData fields the compiler / lending read consume.
FluidVaultSDK
¶
FluidVaultSDK(
chain: str,
rpc_url: str | None = None,
gateway_client: GatewayClient | None = None,
)
Low-level Fluid vault (NFT-CDP) protocol SDK.
All reads go through the VaultResolver with typed-ABI decoding; writes
are offline calldata builders for the vault's operate() entrypoint.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
chain
|
str
|
Chain name (one of |
必需 |
rpc_url
|
str | None
|
DEPRECATED — direct RPC URL for ad-hoc scripts/tests only. |
None
|
gateway_client
|
GatewayClient | None
|
Gateway client routing all eth_call traffic through the gateway's RpcService. Preferred for production code paths. |
None
|
get_vault_entire_data
¶
VaultResolver.getVaultEntireData(vault) — 97-word typed decode.
position_by_nft_id
¶
VaultResolver.positionByNftId(nftId) — (12 + 97)-word typed decode.
positions_by_user
¶
VaultResolver.positionsByUser(wallet) — every position with its vault.
The two returned arrays are index-aligned (position i ↔ its vault's data at i — verification report D1), so each position carries its lowercased vault address. No pagination exists; cost is bounded by the one-NFT-per-(wallet,vault) invariant.
resolve_user_nft_for_vault
¶
Resolve the wallet's nftId on vault fresh from chain state.
The VIB-5010 answer: chain is the source of truth — persisted nftIds
are never load-bearing. Returns None when the wallet holds no
position NFT on the vault (the measured "no position" answer —
distinct from a read failure, which RAISES FluidSDKError so the
compiler fails closed instead of minting a duplicate position).
If the wallet somehow holds MULTIPLE NFTs on one vault (user acted outside the SDK), selection is deterministic: lowest nftId wins, with a warning — the others stay invisible by design (ADR §1.1).
encode_operate_calldata
¶
ABI-encode operate(nftId, newCol, newDebt, to) calldata.
Signed deltas: positive = deposit/borrow, negative = withdraw/repay,
INT256_MIN = the protocol max sentinel (full withdraw/repay).
build_operate_tx
¶
build_operate_tx(
vault: str,
nft_id: int,
col_delta: int,
debt_delta: int,
to: str,
value: int = 0,
) -> dict[str, Any]
Build an operate() transaction for a Fluid type-1 vault.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
vault
|
str
|
Vault contract address (the per-market operate target). |
必需 |
nft_id
|
int
|
Position NFT id (0 mints a new position). |
必需 |
col_delta
|
int
|
Signed collateral delta (raw units; INT256_MIN = all). |
必需 |
debt_delta
|
int
|
Signed debt delta (raw units; INT256_MIN = full repay). |
必需 |
to
|
str
|
Recipient of withdrawn collateral / borrowed debt. |
必需 |
value
|
int
|
msg.value — MUST equal |
0
|
position_from_tuple
¶
Map a decoded 12-field UserPosition tuple onto the dataclass.
vault_data_from_tuple
¶
Map a decoded 97-word VaultEntireData tuple onto the dataclass.
almanak.connectors.fluid.vault_compiler
¶
Back-compat shim: fluid.vault_compiler re-exports the shared implementation from
almanak.connectors._fluid_core.vault_compiler (single source of truth).
FluidVaultCompiler
¶
Bases: BaseLendingCompiler
Compile fluid_vault SUPPLY / BORROW / REPAY / WITHDRAW / DELEVERAGE.
DELEVERAGE routes to :meth:compile_repay via the
:class:BaseLendingCompiler dispatch (framework convention: a
deleverage is a repay with risk context).