Skip to main content
Source of NAV, gate of operations. The oracle program holds per-market price observations (Pyth on-chain or Hermes-pushed by the keeper), maintains keeper- and user-facing TWAPs, and exposes a state machine that downstream programs read.

Accounts

OracleConfig PDA

One per market. TwapState fields: last_twap, cumulative_price, cumulative_time, last_update, window_seconds. PriceObservation fields: price, confidence, timestamp.

OracleFeed PDA

Per-feed registration. A market can have multiple feeds for different trading sessions. The keeper picks the feed whose kind matches the current US trading session.

Instructions

Initialization (admin)

initialize_oracle_config(max_confidence_interval, max_staleness)

Create the OracleConfig for a new market. Sets initial admin, keeper, and primary Pyth pubkey.

upsert_oracle_feed(...)

Register or update an additional feed (e.g., a pre-market feed kind). Used to extend a market’s session coverage.

Updates

update_price_observation (keeper-signer)

The hot path. Keeper calls every ~15s with the latest Pyth/Hermes price + confidence. The instruction:
  1. Validates signer == oracle_config.keeper_authority.
  2. Rejects if price moves > 20% in one update (PriceMovementTooLarge).
  3. Rejects if confidence > max_confidence_interval (ConfidenceTooHigh).
  4. Pushes observation into the ring buffer.
  5. Updates last_price, last_confidence, last_update_time.
  6. Recomputes user_twap, keeper_twap.
  7. Updates recent_volatility_bps.
  8. Writes user_twap.last_twap to the bound Market.user_twap_price (CPI).

Configuration (admin)

configure_twap_windows(keeper_window_seconds, user_window_seconds)

Defaults are 60s and 300s respectively. Adjust per market based on volatility.

configure_health_thresholds

Per-market override of the staleness / confidence thresholds that drive MarketState transitions.

update_oracle_config

Update admin/keeper authorities, Pyth pubkey, etc.

reset_volatility_counters

Clear recent_volatility_bps (used after large legitimate move that should not bias future regime classification).

Read-only helpers

These instructions don’t write - they’re convenient CPI-callable helpers if your own program needs to query oracle state without account-fetching.
  • get_keeper_twap - returns the keeper-window TWAP.
  • get_user_twap - returns the user-window TWAP.
  • get_market_state - returns MarketState enum.
  • get_oracle_health - returns a struct combining staleness, confidence, state.
  • get_price - returns most-recent observation.
  • get_user_price / get_keeper_price - TWAP-based price for the right window.
In practice you can also just account.fetch(oracleConfig) and read fields directly. The CPI helpers exist for programs that want to enforce on-chain price consistency.

Operator emergency

force_price(price, confidence) (admin, devnet)

Manually set a price. Used to set up tests or force-recover a market with corrupted feed data. Should never be used on mainnet outside extreme emergencies.

emergency_pause (admin)

Set is_paused = true. All reads return OraclePaused. Mint-redeem treats this as OraclePriceUnavailable and rejects mints.

Errors

Full error catalog

TypeScript

See also

Oracle concept

How prices flow, why dual TWAPs, session-aware feeds.

Risk states

Downstream effects of oracle state on user operations.