Two contracts run through the whole SDK. A read never throws — it returns a typed degraded envelope you must narrow before you can touch the data. A write never crashes at construction — without a signer it either throws a clear error on call or returns a deferred result carrying the unsigned tx. This page is the complete catalogue of those envelopes, the live-today vs degradation cheat-sheet, and the approvals/spenders table — the three things a UI engineer needs to render Inflexion safely, including when a backing (subgraph URL / RPC / telemetry) is absent.
<route>” state instead of wrapping every call in a try/catch. The type system enforces it: every fallible read returns a discriminated union, and the compiler will not let you read the payload until you check the discriminant.
The five envelopes
There are exactly five degradation shapes in the SDK. Three are read envelopes (Degraded<T>, Priceable<T>, ApiPending), one is a read precision flag (NonceStatus), and one is the write-result union (WriteResult). Everything fallible the SDK returns is one of these.
Degraded<T>
Generic read envelope: success or a
{ available: false, reason }. Vault state, position, regime, surface σ_ref.Priceable<T>
Anything that needs the live price . Success or
NotPriceable { priceable: false, reason, detail? }.ApiPending
History/aggregate surfaces when no backing is configured. Names the route + the exact query. Served live today via the hosted API.
NonceStatus
Not pass/fail — a precision flag:
'coarse' | 'precise'. MM fill attribution is coarse on-chain.WriteResult
The DepositorClient write union:
{ tx, txHash?, status: 'sent' | 'deferred-no-wallet' | 'error', detail? }. LP/MM writes throw a clear error instead of deferring.Quick reference
Degraded<T> — generic read degradation
DepositorClient.getVaultState, getPosition, getRegime, and DataClient.getSurfaceSigmaRef all return Degraded<T>.
On
Degraded<VaultState>, the success branch carries capitalNotGuaranteed: true — the SDK attaches Claim B to every depositor state read. Render the tranche risk disclosure wherever you surface vault state.Priceable<T> — anything that needs the live price
Degraded<T> because the dominant failure is the live price being unavailable. Every read that derives catches an OracleManager.getPrice revert (stale feed, sequencer down) and returns NotPriceable { reason: 'oracle-degraded' } rather than throwing. This covers lp.resolveGeometry, previewPremium, getPayoffCurve, and the nested ilToDate inside getProtectionStatus.
DegradeReason — the closed union
Every reason on a Priceable/Degraded/ApiPending failure is drawn from one closed union, so the UI can exhaustively switch on it:
ApiPending — the SDK that never fabricates history
/), backed by the deployed subgraph (slug inflexion-arb-sepolia) which has indexed on-chain history since the redeploy block. ApiPending is the graceful-degradation fallback: if no backing is configured (e.g. SUBGRAPH_URL is unset), each DataClient history method returns this typed envelope rather than inventing a number — it names the route and the exact query that would be sent, so the UI can render “served from <route>” with zero re-derivation when a backing is present. The SDK never fabricates history.
History/aggregate surfaces are live today — served from the subgraph via the hosted API.The deployed subgraph (slug
inflexion-arb-sepolia) has indexed on-chain history since the redeploy block, so all five data-moat history signals resolve to real data through the API. getCurrentLoadSurface and getSurfaceSigmaRef hit live RPC directly. getDemandRequests is the one inherently off-chain signal: it is served from engine telemetry, not the chain, because latent demand never touches the chain by invariant I7. If no backing is configured (e.g. SUBGRAPH_URL is unset), the history methods degrade to a typed ApiPending envelope naming their route — they never throw.NonceStatus — coarse vs precise fill attribution
WriteResult — writes fail clearly, never silently
makeWalletClient returns undefined rather than crashing. What happens when you then call a write is deliberately different per surface, because the right failure mode differs by intent.
- DepositorClient — deferred result
- LpClient / MmClient — throw on call
deposit, requestWithdrawal, and withdraw return a WriteResult. Without a signer the status is 'deferred-no-wallet' and tx carries the unsigned calldata for an external signer — the right shape for server-side and custody flows where the SDK builds calldata that something else signs. An on-chain revert (e.g. the JuniorBelowLocked gate on withdraw) surfaces as status: 'error', never a thrown exception.Live-RPC vs subgraph-backed — the cheat-sheet
The SDK is fully usable against the live deployment, and the subgraph is deployed and indexing too. The line is between live-RPC surfaces (data straight from the chain) and history/aggregate surfaces served from the subgraph via the hosted API — which degrade to a typed pending state only if no backing is configured.- Live-RPC (direct, no subgraph needed)
- Subgraph-backed (live via API)
The subgraph is deployed and indexing — history, NAV, precise fill attribution, and full fee accounting are live, served via the hosted API.The subgraph (slug
inflexion-arb-sepolia) has indexed on-chain history since the redeploy block, so these surfaces resolve to real data with no consumer-side changes. Graceful degradation remains a design property: if a backing is absent (e.g. SUBGRAPH_URL is unset), each affected surface degrades to a typed envelope — ApiPending (history), NonceStatus { precision: 'coarse' } (fills), or an under-stating-but-honest read (getClaimableFees) — and the UI renders the pending state; nothing throws.Structures ship from day one; the full DYNAMICS (pool-vs-MM spread as a forward-vol signal) mature with multiple competing MMs and volume. The dataset begins at the single redeploy; the off-chain telemetry halves begin at the first interaction logged.What Inflexion offers today is the architecture and the first public view into the microstructure of the DeFi LP volatility-risk premium — not yet a mature dataset:
- Structures are present day-one. All five non-circular behavioral signals are defined and queryable from launch.
- Dynamics mature with volume. The richer signal — the pool-vs-MM spread read as a forward-vol indicator — only sharpens once multiple market makers compete and real flow accumulates.
- The dataset begins at the single redeploy, and the off-chain telemetry halves begin at the first interaction logged. History is served live from the subgraph via the API; if a backing (subgraph URL / RPC / telemetry) is absent, surfaces degrade to a typed
pendingstate — never an error.
Approvals & spenders — the one-glance table
Reads need no approvals. For writes, the spender differs per surface — and getting it right is the difference between a successful tx and a wasted approval to the wrong contract.All collateral and premium flows are denominated in dUSDC, 6 decimals (the numéraire —
1 dUSDC = 1_000_000n). maxPremium, amount, V0, maxIL, and every collateral figure are 6-dec raw bigints. See decimals & units and addresses & units.The depositor claim, stated correctly
Because the live load surface, NAV history, and vault-state reads on this page all touch depositor capital, the SDK attaches Claim B to every depositor read. It is never merged with Claim A (LP no-bad-debt).Where to go next
Guardrails
The write-safety model in full —
build* calldata, deferred results, and the never-merge claim discipline.Data client
The live-RPC surface and the five behavioral signals of the data moat, served via the API.
Getting started
Construction, the full config table, and the RPC/key resolution order that drives
no-rpc.Subgraph
What the live subgraph indexes, and which envelopes resolve from coarse/pending to precise.
Invariants
I7 (capacity authority) and the settlement-liveness fork behind
oracle-degraded.Deployments
Live Arbitrum Sepolia addresses — never hardcode; import from the SDK.