Skip to main content

Documentation Index

Fetch the complete documentation index at: https://continuum-ec12e897.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

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.
Devnet ID: 5vxiCrDpFnQ2W5QtgZBC66K2XTC19bjVBjinGYYBsadC

Accounts

OracleConfig PDA

seeds = [b"oracle_config", market_id]
One per market.
FieldTypePurpose
market_idPubkeyBound market PDA
admin_authorityPubkeyAdmin signer (configure, force, pause)
keeper_authorityPubkeyKeeper signer (push observations)
pyth_oraclePubkeyDefault Pyth feed pubkey
switchboard_oraclePubkeyOptional Switchboard feed
max_confidence_intervalu64Reject observations with confidence above this
max_stalenessi64Seconds before health degrades
is_pausedboolEmergency stop
last_priceu64Most recent observation (6 decimals)
last_confidenceu64Most recent confidence (6 decimals)
last_update_timei64Last observation unix-ts
user_twapTwapStateUser-facing TWAP (longer window)
keeper_twapTwapStateKeeper-facing TWAP (shorter window)
market_stateenumActive / Paused
recent_volatility_bpsu32Rolling realized vol
recent_move_countu32Counter for volatility window
observationsring bufferRecent PriceObservation entries
TwapState fields: last_twap, cumulative_price, cumulative_time, last_update, window_seconds. PriceObservation fields: price, confidence, timestamp.

OracleFeed PDA

seeds = [b"oracle_feed", oracle_config, pyth_oracle]
Per-feed registration. A market can have multiple feeds for different trading sessions.
FieldTypePurpose
oracle_configPubkeyBound oracle config
pyth_oraclePubkeyPyth feed account
priorityu8Lower = higher priority
kindenumPrimary / PreMarket / PostMarket / Overnight / Fallback / Custom
is_activeboolIf false, ignored in feed selection
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

CodeNameCause
6000OraclePausedis_paused = true
6001InvalidPythAccountWrong Pyth account passed
6002PriceUnavailableNo fresh observation
6003ConfidenceTooHighConfidence > max_confidence_interval
6004PriceStaleLast update older than max_staleness
6005PriceMovementTooLargeNew observation > 20% from prior
6006TwapNotReadyTWAP buffer not yet populated
6007InvalidTwapWindowTWAP window < 1s or > 24h
6008MarketStateRestrictionOperation not allowed in current state
6009UnauthorizedKeeperSigner ≠ keeper_authority
6010UnauthorizedAdminSigner ≠ admin_authority
6011InvalidRegisteredFeedFeed not in OracleFeed registry
6012InactiveOracleFeedFeed exists but is_active = false
6013MathOverflowShould be unreachable
Full error catalog

TypeScript

import { Program, BN } from "@coral-xyz/anchor";
import { PublicKey } from "@solana/web3.js";
import idl from "./oracle.json";

const oracle = new Program(idl, provider);

const oracleConfig = await oracle.account.oracleConfig.fetch(market.oracleAddress);

console.log("Last price:", oracleConfig.lastPrice.toString(), "(6 decimals)");
console.log("Confidence:", oracleConfig.lastConfidence.toString());
console.log("Stale (s):", Date.now() / 1000 - oracleConfig.lastUpdateTime.toNumber());
console.log("Volatility (bps):", oracleConfig.recentVolatilityBps);
console.log("State:", Object.keys(oracleConfig.marketState)[0]);
console.log("User TWAP:", oracleConfig.userTwap.lastTwap.toString());

See also

Oracle concept

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

Risk states

Downstream effects of oracle state on user operations.