@inflexion/sdk is the typed access layer over the live deployment. It is the only layer that holds a signer and the only one that can answer the load-bearing question — “what dollar premium will I be charged on this position if I sign in the next block?” — by combining a fresh on-chain FairValueOracle read with the position’s geometry.
One call wires everything: createInflexionSdk(config) builds one public (read) client plus one optional wallet (write) client, then injects them into all five stakeholder surfaces — lp, depositor, mm, data, and the read-only greeks/hedge.
No address is ever passed in. Every contract address loads from the on-chain address registry — a hard rule, not a convenience. See addresses & units and the deployments registry.
Install
The SDK is a workspace package in the Inflexion monorepo. It ships ESM withviem as the only hard runtime dependency on the read/write side; the EIP-712 quote helpers are re-exported from the engine.
Quote helpers are also exposed at a subpath. The EIP-712
SignedQuote helpers re-export from both @inflexion/sdk and @inflexion/sdk/quote. Import from the subpath when you only need signing/verification and want to keep your bundle tight.The one-call factory
Reads are graceful
Anything that needs a reverting oracle, an absent rich event, or an unreachable subgraph returns a typed degraded envelope (
{ available: false, reason } / { priceable: false, reason } / precision: 'coarse') — it never throws. See degradation.Writes degrade, never crash at construction
Construction never throws on a missing signer. With no
walletClient, LP/MM writes throw a clear error on call (the one place a missing signer is a hard error); DepositorClient instead returns WriteResult { status: 'deferred-no-wallet' } carrying the unsigned tx for an external signer.Every config field
InflexionSdkConfig. Every field is optional; precedence rules are in Resolution order.
string
Explicit RPC URL for the read client. Falls back to env, then to the chain’s default public RPC.
Transport
A custom viem
Transport (for example a test mock). Overrides rpcUrl.PublicClient
A pre-built viem read client. Overrides
rpcUrl and transport — this is the recommended browser path, since it reuses the client wagmi already holds and avoids a second RPC connection.WalletClient
A pre-built viem write client. Overrides
privateKey and account. This is how the browser injects the connected wallet.Hex
A raw signer key for writes (server/key-based mode). Falls back to env. Absent ⇒ writes are deferred, not crashed.
Account
A pre-built viem
Account for writes. Overrides privateKey.string
Base URL of the off-chain matching engine. Used for Path-B MM quotes and the
previewPremium latent-demand telemetry ping. Only the lp surface receives it.string
Base URL of the public REST API (the hosted backend). Passed to the
data surface so the history/aggregate methods (getNavHistory, getLoadSurfaceHistory, getQuoteCompetition, getDemandRequests, getNetGamma) fetch live from the subgraph; absent ⇒ those surfaces degrade to a typed ApiPending (the live RPC surfaces are unaffected). The app reads it from NEXT_PUBLIC_API_URL.string
Override for the telemetry endpoint. Defaults to
${engineBaseUrl}/telemetry/preview.typeof fetch
An injected
fetch implementation (tests / non-browser runtimes). Defaults to the global fetch when present.number
default:"421614"
The EIP-712 chain id used for quote signing. Defaults to the live chain,
421614. Only the mm surface receives it.Resolution order
This is the graceful-degradation contract. It is fully deterministic — higher-precedence fields win, and missing fields fall back to env, then to a safe default.Read client
publicClient, it is used verbatim. Otherwise the SDK builds one. The effective rpcUrl is resolved in this order:
1
config.rpcUrl
The explicit URL you passed.
2
process.env.ARBITRUM_SEPOLIA_RPC
The canonical env var for this network.
3
process.env.SEPOLIA_RPC
A secondary env fallback.
4
the chain's default public RPC
A safe last resort so reads always have a transport.
transport you pass overrides rpcUrl (it is injected directly into the viem client).
Write client
makeWalletClient returns undefined when no signer is available — no account, no privateKey arg, and no env key. When that happens the SDK degrades every write rather than crashing at construction. The signer key is resolved in this order:
1
config.account
A pre-built viem account wins outright.
2
config.privateKey
A raw key arg, from which an account is derived.
3
process.env.DEPLOYER_PRIVATE_KEY
The canonical deployer/server key.
4
process.env.PRIVATE_KEY
A secondary env fallback. If none of these is present, the write client is
undefined.Chain id
What the factory returns
InflexionSdk:
lp gets engineBaseUrl / telemetryUrl / fetchImpl; mm gets chainId; depositor / data / greeks / hedge get just the clients. The five surfaces are documented in the LP, depositor, MM, data, and greeks/hedge clients.
The two instantiation modes
- (a) Browser / wagmi — inject clients
- (b) Server / key-based — build from env or key
- (c) Read-only — no signer at all
The recommended path. Inject the pre-built viem clients wagmi already holds; passing
publicClient overrides rpcUrl/transport so you avoid opening a second RPC connection. The wallet client appears only once connected — omit it until then and writes throw a clear error on call.apps/web/lib/use-sdk.ts
Environment variables
The factory resolves these when the corresponding config field is absent. Set them in your shell,.env, or deployment platform — see env vars for the full app-side list.
In the browser, only
NEXT_PUBLIC_-prefixed env vars are visible. The app reads the engine URL from NEXT_PUBLIC_ENGINE_URL and passes it as engineBaseUrl (see mode (a)). The bare ARBITRUM_SEPOLIA_RPC / *_PRIVATE_KEY fallbacks are server-side conveniences — they never apply when you inject a publicClient/walletClient from wagmi.A first call — confirm it’s wired
A construction-only smoke test. Reads are graceful, so this never throws even if the oracle is degraded — it returns a typed envelope you can branch on.smoke-test.ts
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.
Where to go next
Addresses & units
The registry imports, dUSDC = 6-dec numéraire, WAD = 1e18, and the
sqrtPriceX96 conversions.LP client
previewPremium, buyProtection, settle — buying in-range IL protection (claim A).Depositor client
Deposit/withdraw the cvAMM tranches; every result carries the capital-not-guaranteed claim (claim B).
MM client
Per-market signed quotes, the pool-load-to-beat, and the I10 / below-pool guards.
Data client
The live load surface plus the typed-pending history surfaces of the data moat.
Degradation
The full
Degraded / Priceable / ApiPending envelope contract — why nothing throws.