Skip to main content
DataClient is the SDK surface over the data moat — the first public view into the microstructure of the DeFi LP volatility-risk premium. It carries no claim and holds no signer: every method is read-only and none of them ever mutate state. The surface splits cleanly into two classes, and the split is the whole design:

One LIVE method

getCurrentLoadSurface (+ the getSurfaceSigmaRef annotation) reads live RPC: the same multicall MM getMarketPricing does, fanned across a set of markets. The current “price-to-beat” snapshot, uncached.

Five history methods

getLoadSurfaceHistory, getQuoteCompetition, getDemandRequests, getNavHistory, getNetGamma — every history/aggregate surface. Each names its API route and is served live from the subgraph via the hosted API; if no source is configured it degrades to a typed ApiPending rather than throwing.
The SDK never fabricates history. The history/aggregate surfaces are served live from the deployed subgraph via the hosted API (REST at /, engine at /engine). If a backing source is not configured the method returns a typed degraded envelope ({ available:false, reason:'no-history-source', endpoint, query, detail }) — never a throw, never a guessed number. The on-chain moat events (SwapPriced, QuoteFilled) are LIVE since the 2026-06-05 redeploy and the subgraph has indexed them from block 274081134.

The method table

Construct it from the SDK factory (sdk.data) or directly via makeDataClient(publicClient). The constructor takes optional address overrides; by default it resolves InflexionCore, ConvexityVault, the Stylus FairValueOracle, and VolOracle from the deployment registry. Each history method maps 1:1 onto one of the five behavioral signals. The route strings are not free text — they are the SDK ↔ API contract, exported verbatim as DATA_API_ROUTES so the integration layer wires exactly the same paths the SDK already names.

The live half — getCurrentLoadSurface

This is the only DataClient method that hits live RPC directly instead of the hosted API. It is the live half of Signal 1 — the current clearing-load “price-to-beat” — while its historical evolution is getLoadSurfaceHistory.

Read set

Per call: one shared loadParams() + inventory(), then a per-market markets() multicall, then a per-market fairPremium() multicall — exactly the read set MM getMarketPricing does, fanned out:
The load stack is then finished client-side with the parity-locked CvammPricing TS port: load = loadComponents(σ_ref, util, conc, params) and poolPremium=min⁡ ⁣(⌈fairPremium⋅(1+totalLoad)⌉,  MaxIL)\text{poolPremium} = \min\!\Big(\big\lceil \text{fairPremium}\cdot(1+\text{totalLoad})\big\rceil,\; \text{MaxIL}\Big) The Φ-sum is read on-chain and never reimplemented; only the deterministic pure load stack is mirrored off-chain — the single permitted duplication, because the deployed CvammPricing library is delegatecall-only and reverts on a direct eth_call. See the cvAMM port.
Geometry is optional. If a market supplies none, a neutral reference geometry is used: a=0.81a=0.81, b=1.21b=1.21 (i.e. Pa/P0=0.9P_a/P_0=0.9, Pb/P0=1.1P_b/P_0=1.1), MaxIL = $1,000. The load percentage is geometry-independent — it is a function of (σref,util,conc)(\sigma_\text{ref}, \text{util}, \text{conc}) only — so only the absolute dollar fairPremium/poolPremium figures scale with aa/bb/MaxIL. Pass real per-market geometry when you need dollar-accurate premiums.

Return shape — LoadSurface

A live MarketPricing row carries the full price-to-beat decomposition:
Hex
bigint
FairPremium for the supplied geometry, USDC raw (6-dec) — from the Stylus FVO.
bigint
FairPremium / MaxIL as a WAD ratio (1e18-scaled).
bigint
The σ_ref (WAD) the fair value was computed against.
bigint
Path-A pool premium = ceil(FairPremium·(1+totalLoad)), capped at MaxIL, USDC raw.
bigint
MaxIL for the geometry, USDC raw — the cap poolPremium is clamped to.
LoadBreakdown
The pool load stack — the price-to-beat decomposition.
bigint
Pool utilization (locked / total), WAD.
bigint
Pool coverage concentration (HHI), WAD.
'calm' | 'normal' | 'stressed'
Vol regime from σ_ref vs the loadParams bands.

Per-market degradation

A single bad market never throws the whole surface — the degraded row is inlined so the caller sees exactly which markets have gaps:

Worked example

data-surface.ts
getSurfaceSigmaRef returns a Degraded<{ sigmaRefWad, regime }>: { available:false, reason } if the VolOracle is uninitialised for the token (poke it first), never a throw. See σ_ref and the load stack.

The degradation contract — the ApiPending envelope

The history/aggregate methods are served live from the subgraph via the hosted API. The full type is ApiBacked<T> = ({ available:true } & T) | ApiPending — the rich T from the API, else, if no backing source is configured, the same typed pending envelope:
This is the load-bearing design move: the envelope names the route and the exact query sent, so a UI can render “coming from <route>” regardless of backing state, and the degraded path is a typed body — not a throw — so graceful degradation is a design property: if a backing (subgraph URL / RPC / telemetry) is absent, the surface returns this pending body instead of erroring. When degraded, the detail string carries the disclaimer verbatim, with any method-specific prefix folded in front:

DATA_API_ROUTES — the route contract

The five routes are exported as a const so callers can read them and the hosted API serves the same strings:

The route + query, per method

Each method assembles its endpoint + query deterministically from its args (optional args are omitted from query when absent; bucketed methods default the bucket). Live, the API returns the rich body for that route; the snippets below show the typed degraded fallback the SDK returns when no source is configured, which is exact to source.
Args: { marketId: Hex; from?: number; to?: number; bucket?: '1h' | '1d' }
bucket defaults to '1d'; from/to are stringified when present, omitted when absent. Source for the historical evolution of getCurrentLoadSurface — the subgraph indexes MarketStateSnapshot and joins the now-live SwapPriced/QuoteFilled per-fill load events, served live via /data/load-surface. For the CURRENT surface, use getCurrentLoadSurface (live RPC). See Signal 1.
Args: { marketId?: Hex; from?: number; to?: number } (all optional)
Joins the now-live SwapPriced (mechanical pool baseline = the price-to-beat) with QuoteFilled.loadBps (the behavioral MM load) per swap from the subgraph, plus the off-chain engine COMPETITION_LOG telemetry for the dynamic half. The spread poolLoad − mmLoad is non-circular as a spread — the subtraction removes the circular component (see circular vs behavioral). Both halves are live: the dynamic half is captured in engine telemetry, the structural half is indexed by the subgraph.
Limit → Why → Mitigation. At one MM the spread conflates “MM expects vol to fall” with “MM has cheaper hedges” — two un-separable drivers (the limit). Why: a competitive distribution requires multiple independent load views, which only exist with multiple MMs. Mitigation: the spread is visible per fill from day one, and the off-chain COMPETITION_LOG captures every losing/withdrawn quote from the first interaction — so the forward-vol read sharpens with ≥3 competing MMs without losing the early data. See state and limits.
Args: { marketId?: Hex; from?: number; to?: number } (all optional)
Limit → Why → Mitigation. The latent half of this surface is off-chain by design and permanently — there is no live RPC fallback (the limit). Why: the latent half of demand (geometries an LP priced but did not buy) NEVER reaches the chain — invariant I7 guarantees an unchosen quote touches no nonce and no capacity, and putting unfilled interest on-chain would both cost gas and break I7. Mitigation: it is captured from the first interaction in the off-chain engine DEMAND_LOG (every GET /quote and every previewPremium ping), coarse-bucketed and PII-free, because it is unreconstructable retroactively — and it is served live via the hosted engine telemetry at /data/demand-requests. The realized half is on-chain (subgraph GeometryDemandBucket); the latent half is only ever telemetry. See telemetry.
Args: { from?: number; to?: number; bucket?: '1d' }
The subgraph computes PoolDaySnapshot from Deposited/Withdrawn/PremiumAccrued/SettlementReleased/JuniorLoss. The claim-B disclosure is folded into detail and never merged with claim A — NAV history is a depositor-risk surface, distinct from the LP no-bad-debt guarantee. See the tranches.
Depositor capital is NOT guaranteed: the junior tranche is first-loss; the senior tranche is structurally protected from underwriting loss only, not systemic tail.Underwriting capital — whether supplied to the pooled cvAMM vault (Path A) or posted directly by a market maker (Path B) — is at risk:
  • Junior tranche — first-loss. Junior depositors absorb underwriting losses first and buffer the senior tranche.
  • Senior tranche — protected from underwriting loss, exposed to the systemic tail. The senior tranche is structurally shielded from ordinary underwriting loss while junior capital buffers, but it still takes the systemic tail once the junior buffer is exhausted.
No-bad-debt is a guarantee to the LP being paid (see the FULL-mode payout clause), not a guarantee that depositor or MM capital is preserved.
Args: { marketId?: Hex } (optional; defaults to {})
Off-chain compute over the subgraph-tracked open swap set (SwapCreated opens, SwapSettled closes), summing per-swap Greeks finite-differenced from the deployed ILMath.computeIL / FairValueOracle.fairRate — no parallel pricing model. NOT a contract event; the live SDK has no aggregator because it needs the open set. This is the most launch-robust signal — a sum, not a distribution, so it is meaningful from a handful of swaps. See Signal 5 and the Greeks engine.

The five signals this surface maps to

Each DataClient method maps onto one behavioral signal. All five are non-circular — their informative degrees of freedom come from the MM’s loadBps or the LP’s geometry/duration choice, measured against the transparent mechanical baseline, never derived from it.
The “invert fairRate for an implied-vol surface” idea is deliberately DROPPED as circular — it is not a sixth signal. Because every premium is fairRate(σ_ref)·(1+load) by construction, inverting fairRate from the charged premium recovers nothing but the protocol’s own published σ_ref plus its own load stack — a tautology, not a market-implied vol. The full reasoning is on circular vs behavioral.
Exclude cap-bound fills from the load surfaces (Signals 1/2/3): when premium == MaxIL the load was truncated by the cap and the number carries zero load information. The on-chain SwapPriced.cappedAtMaxIL boolean makes this filter cheap and unambiguous. See the five signals.
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 pending state — never an error.

Live vs live — the one-glance summary

  • getCurrentLoadSurface — current pool load surface across markets (live RPC multicall).
  • getSurfaceSigmaRef — the σ_ref + regime a surface is priced against.
  • The on-chain moat events (SwapPriced, QuoteFilled) are emitting now (since 2026-06-05).
  • The off-chain telemetry sinks (DEMAND_LOG, COMPETITION_LOG) are capturing now — the dynamic/latent halves of Signals 2 & 4.

The data moat (concept)

The thesis, the five signals, and why the dataset cannot exist anywhere else.

Circular vs behavioral

Why inverting fairRate is circular, and what makes each signal legible.

DataClient (guide)

The narrative walkthrough of the load surface and the degradation contract.

MmClient reference

The same multicall read set, per-market, plus quote signing.