All articles
solanaswitchboardoraclevrf

Switchboard: the customisable oracle, queues, jobs, and aggregators

Switchboard is Solana's customisable oracle network. Queues, oracles, jobs, aggregators, randomness — here's the on-chain shape and how to wire each up.

Share
devrels.xyz/a/79short link

Switchboard is Solana's other major oracle. Pyth handles a curated list of canonical asset prices; Switchboard lets you publish a feed of anything by writing a job definition. Sports scores, custom CEX prices, weather data, election results, on-chain randomness — same primitive across all of them.

The four account types

text
Queue          → the oracle network that processes update requests
Oracle         → a participant in a queue, runs the off-chain worker
Aggregator     → the on-chain feed account holding the latest aggregated value
Job            → a definition of how to fetch + transform raw data
                 (referenced by Aggregators; each Aggregator can have N Jobs)
Crank          → a permissionless turn-the-handle account that triggers
                 due updates

Switchboard's permissionless design: anyone can create an Aggregator with their own Jobs, pay into a queue, and start receiving updates from the queue's oracles. The on-chain program enforces validation; the off-chain oracles compete to publish.

What a Job looks like

Jobs are serialized protobuf describing a pipeline of tasks: HTTP fetch → JSON path extract → math transform. Each oracle in the queue runs the same job, posts its result, and the aggregator takes the median (with outlier rejection).

json
{
  "tasks": [
    {
      "httpTask": {
        "url": "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=solana"
      }
    },
    {
      "jsonParseTask": {
        "path": "$[0].current_price"
      }
    }
  ]
}

That's the entire definition for a SOL/USD feed. Switch solana to bitcoin and you have BTC/USD. Replace the URL with a sports API and JSON path with a score field, and you have a live game score feed.

The Aggregator account

rust
pub struct AggregatorAccountData {
    pub name:                 [u8; 32],
    pub metadata:             [u8; 128],
    pub author_wallet:        Pubkey,
    pub queue_pubkey:         Pubkey,                  // which queue this feed lives in
    pub oracle_request_batch_size: u32,                // how many oracles must respond
    pub min_oracle_results:   u32,                     // minimum valid responses for an update
    pub min_job_results:      u32,
    pub min_update_delay_seconds: u32,                 // throttle — minimum seconds between updates
    pub start_after:          i64,
    pub variance_threshold:   SwitchboardDecimal,      // % change required to trigger an update
    pub force_report_period:  i64,
    pub expiration:           i64,
    pub consecutive_failure_count: u64,
    pub next_allowed_update_time: i64,
    pub is_locked:            bool,
    pub crank_pubkey:         Pubkey,
    pub latest_confirmed_round: AggregatorRound {
        num_success:         u32,
        num_error:           u32,
        is_closed:           bool,
        round_open_slot:     u64,
        round_open_timestamp: i64,
        result:              SwitchboardDecimal,      // the actual aggregated value
        std_deviation:       SwitchboardDecimal,
        min_response:        SwitchboardDecimal,
        max_response:        SwitchboardDecimal,
        oracle_pubkeys_data: [Pubkey; 16],
        medians_data:        [SwitchboardDecimal; 16],
        current_payout:      [i64; 16],
        errors_fulfilled:    [bool; 16],
        medians_fulfilled:   [bool; 16],
    },
    pub current_round:        AggregatorRound,
    pub job_pubkeys_data:     [Pubkey; 16],
    pub job_hashes:           [Hash; 16],
    pub job_pubkeys_size:     u32,
    pub jobs_checksum:        [u8; 32],
    pub authority:            Pubkey,
    pub history_buffer:       Pubkey,                  // optional ring-buffer of past results
    pub previous_confirmed_round_result: SwitchboardDecimal,
    pub previous_confirmed_round_slot: u64,
    pub disable_crank:        bool,
    pub job_weights:          [u8; 16],
    pub creation_timestamp:   i64,
    pub _ebuf:                [u8; 130],
}

Reading a Switchboard feed

rust
use anchor_lang::prelude::*;
use switchboard_solana::AggregatorAccountData;

#[derive(Accounts)]
pub struct UseSwitchboard<'info> {
    /// CHECK: validated by Switchboard
    pub aggregator: AccountLoader<'info, AggregatorAccountData>,
}

pub fn read_price(ctx: Context<UseSwitchboard>) -> Result<()> {
    let agg = ctx.accounts.aggregator.load()?;

    // Returns SwitchboardDecimal { mantissa: i128, scale: u32 }
    let result = agg.get_result()?;
    let price_f64: f64 = result.try_into()?;

    // Reject if stale (>5 minutes old)
    agg.check_staleness(Clock::get()?.unix_timestamp, 300)?;

    // Reject if confidence too wide (variance > 1%)
    agg.check_confidence_interval(SwitchboardDecimal::from_f64(0.01))?;

    msg!("price: {}", price_f64);
    Ok(())
}

Switchboard randomness (VRF)

Beyond price feeds, Switchboard publishes a verifiable random function — on-chain randomness backed by an oracle's cryptographic proof. Useful for games, fair draws, mint ordering.

rust
use switchboard_solana::VrfAccountData;

pub fn use_random(ctx: Context<UseVrf>) -> Result<()> {
    let vrf = ctx.accounts.vrf_account.load()?;
    let randomness = vrf.get_result()?;        // [u8; 32]

    // Use first 8 bytes as u64
    let n = u64::from_le_bytes(randomness[..8].try_into().unwrap());
    let dice = (n % 6) + 1;

    msg!("rolled: {}", dice);
    Ok(())
}

Switchboard vs Pyth

text
                  Pyth                       Switchboard
─────────────────────────────────────────────────────────────────
Model             Push (account)             Push (account)
Custom feeds      No — curated symbols       Yes — any job definition
Setup cost        Free (read the account)    Pay queue lease + per-update
Update cadence    Every slot                 Configurable (variance + delay)
Confidence        First-class (1-sigma)      Variance + std deviation
Randomness        No                         Yes (VRF)
Best for          Canonical asset prices     Custom data, long-tail symbols

References

Pyth for canonical asset prices, Switchboard for everything else. Both run in production on every major Solana DeFi protocol's read path.

Keep reading

Get new articles in your inbox

Technical deep-dives on Solana tooling, infrastructure, and ecosystem. No noise.

Switchboard: the customisable oracle, queues, jobs, and aggregators | devrels.xyz