Skip to main content
Mint, redeem and committed orders all price from the market’s Market account in the mint-redeem program. Read that account; you don’t need an off-chain feed. Despite its name, user_twap_price is a spot price, not a time-weighted average. The keeper writes it with mint-redeem’s update_risk_state_v2, already adjusted for corporate actions, and the same call stamps twap_updated_at. On devnet the keeper prices markets from a free public quote source, because Pyth’s public Hermes endpoint now needs an API key. A GJR-GARCH volatility model sets the confidence band. The keeper checks every print against Hyperliquid and skips the push when the two disagree, so Hyperliquid can veto a price but never sets one. Mainnet will use Pyth (Pyth Pro). See Oracle.
Mint and redeem don’t trade at NAV. They quote each leg against the user, with c = oracle_confidence × the confidence multiplier for the current risk state: The multipliers live in worst_case_config: 1× in Normal, 1.5× in ProxyMode and 3× in Stress. In Recovery the multiplier falls from 3× to 1× over one hour. Every devnet market runs in ProxyMode. When worst_case_config.enabled is false, c is 0 and both legs trade at NAV; as of 10 Oct 2026 that is true for QQQ only. Fees are separate and use risk_fee_config (see Mint and redeem example).

Sample

Output on Saturday 10 Oct 2026 at 19:32 UTC. The underlying markets were closed, so every price was stale:
QQQ’s c is 0 because its worst-case quoting is off. SPY’s c is its confidence of 0.123159 times 1.5. EUR’s s_gamma_index was still 0 (never written), so γ read as 1.0. Its first write, on 11 Oct 2026, set it to 0.99954.

Freshness

Mint and redeem revert with TwapNotAvailable when P is 0 or twap_updated_at is more than 300 s old. There is no fallback price. The keeper withholds a push whenever its source price is stale. That happens every time the underlying market closes, so outside trading hours mint and redeem stop working 300 s after the last push. Committed orders (enabled on every live market since 11 Oct 2026) settle only at a push newer than the commit, and expire 180 s after it. The bin books are the reverse: they trade only once the price is more than 300 s old outside Normal, against a demand-sized free-float book that the keeper posts. Apply the same rule in your UI: mark prices older than 300 s as stale and disable mint and redeem.

OracleConfig is not the live price

The oracle program’s OracleConfig accounts are not updated on devnet; the keeper writes prices only to Market. As of 10 Oct 2026, QQQ’s OracleConfig still holds a last_price of 562330000000, written on 4 Apr 2026. OracleConfig prices are scaled to 1e9, not 1e6, so that is $562.33. Don’t read OracleConfig for live prices.

Book centre (Pool account)

Each side of a market has a bin book: a Pool account in the CLP program at [b"pool", market, [side]]. Its base_price_1e6 is the centre the keeper last posted. The keeper shifts that centre for the protocol’s inventory, so it can sit away from NAV. With a CLP client loaded from clp.json the same way:
On 10 Oct 2026 QQQ’s long book was centred at 751.27 and its short book at 304.599737, the same as the NAVs above.

Subscribe or poll

  • Subscribe with connection.onAccountChange(marketPda, ...) to see each push as it lands.
  • Poll every 15 to 30 s for dashboards, and batch markets into one fetchMultiple call.
The Continuum app reads all market accounts in one batched call every 30 s.

Decimals

Token amounts and Market prices use 6 decimals. γ and OracleConfig prices use 9. Keep raw values in BN or bigint math and convert once, for display:
BN has arbitrary precision, so prefer it over toNumber() for anything you multiply.

See also

Reading state

Full state-fetch patterns (markets, vaults, positions).

Risk states

What Stress, ProxyMode and Recovery mean and how to surface them.