#solana #switchboard #oracle

switchboard-solana

A Rust library to interact with Switchboard accounts

182 releases (11 breaking)

0.29.102 Feb 29, 2024
0.29.92 Jan 30, 2024
0.29.79 Dec 19, 2023
0.29.71 Nov 28, 2023
0.27.0 Jul 10, 2023

#1277 in Magic Beans

Download history 15/week @ 2023-12-22 47/week @ 2023-12-29 174/week @ 2024-01-05 225/week @ 2024-01-12 85/week @ 2024-01-19 62/week @ 2024-01-26 61/week @ 2024-02-02 148/week @ 2024-02-09 381/week @ 2024-02-16 427/week @ 2024-02-23 334/week @ 2024-03-01 131/week @ 2024-03-08 114/week @ 2024-03-15 15/week @ 2024-03-22 795/week @ 2024-03-29 1743/week @ 2024-04-05

2,689 downloads per month
Used in 2 crates

MIT license

1MB
16K SLoC

Switchboard Logo

switchboard-solana

A Rust library to interact with Switchboard accounts on Solana.

Crates.io Badge

Discord Badge

Twitter Badge

Typedocs: docs.rs/switchboard-solana

Solana SDK: github.com/switchboard-xyz/solana-sdk

Switchboard Documentation: docs.switchboard.xyz

Install

Run the following Cargo command in your project directory:

cargo add switchboard-solana

Or add the following line to your Cargo.toml:

[dependencies]
switchboard-solana = "0.29"

NOTE: The minor version corresponds to the anchor-lang dependency. Version 0.29.* of this crate uses anchor-lang 0.29.0 while version 0.27.* of this crate uses anchor-lang 0.27.0. We currently support Anchor 29, 28, and 27.

Accounts

This SDK provides the following account definitions for the Oracle Program:

This SDK provides the following account definitions for the Attestation Program:

Usage

Functions

You will need to validate your function's enclave_signer before allowing your program to modify its state.

use switchboard_solana::FunctionAccountData;

#[derive(Accounts)]
pub struct SaveDataInstruction<'info> {
    // ... your required accounts to modify your program's state

    // We use this to derive and verify the functions enclave state
    #[account(
        constraint =
            function.load()?.validate(
              &enclave_signer.to_account_info()
            )?
    )]
    pub function: AccountLoader<'info, FunctionAccountData>,
    pub enclave_signer: Signer<'info>,
}

Aggregator

Read Latest Result

use anchor_lang::solana_program::clock;
use std::convert::TryInto;
use switchboard_solana::{AggregatorAccountData, SwitchboardDecimal, SWITCHBOARD_PROGRAM_ID};

// check feed owner
let owner = *aggregator.owner;
if owner != SWITCHBOARD_PROGRAM_ID {
    return Err(error!(ErrorCode::InvalidSwitchboardAccount));
}

// deserialize account info
let feed = ctx.accounts.aggregator.load()?;
// OR
let feed = AggregatorAccountData::new(feed_account_info)?;

// get result
let decimal: f64 = feed.get_result()?.try_into()?;

// check if feed has been updated in the last 5 minutes
feed.check_staleness(clock::Clock::get().unwrap().unix_timestamp, 300)?;

// check if feed exceeds a confidence interval of +/i $0.80
feed.check_confidence_interval(SwitchboardDecimal::from_f64(0.80))?;

Read Aggregator History

Note: The Aggregator must have a history buffer initialized before using

use switchboard_solana::AggregatorHistoryBuffer;
use std::convert::TryInto;

let history_buffer = AggregatorHistoryBuffer::new(history_account_info)?;
let current_timestamp = Clock::get()?.unix_timestamp;
let one_hour_ago: f64 = history_buffer.lower_bound(current_timestamp - 3600).unwrap().try_into()?;

VRF Account

Read VRF Result

use switchboard_solana::VrfAccountData;

// deserialize the account info
let vrf = ctx.accounts.vrf.load()?;
// OR
let vrf = VrfAccountData::new(vrf_account_info)?;

// read the result
let result_buffer = vrf.get_result()?;
let value: &[u128] = bytemuck::cast_slice(&result_buffer[..]);
let result = value[0] % 256000 as u128;

RequestRandomness CPI

pub use switchboard_solana::{VrfAccountData, VrfRequestRandomness};

let switchboard_program = ctx.accounts.switchboard_program.to_account_info();

let vrf_request_randomness = VrfRequestRandomness {
    authority: ctx.accounts.state.to_account_info(),
    vrf: ctx.accounts.vrf.to_account_info(),
    oracle_queue: ctx.accounts.oracle_queue.to_account_info(),
    queue_authority: ctx.accounts.queue_authority.to_account_info(),
    data_buffer: ctx.accounts.data_buffer.to_account_info(),
    permission: ctx.accounts.permission.to_account_info(),
    escrow: ctx.accounts.escrow.clone(),
    payer_wallet: ctx.accounts.payer_wallet.clone(),
    payer_authority: ctx.accounts.payer_authority.to_account_info(),
    recent_blockhashes: ctx.accounts.recent_blockhashes.to_account_info(),
    program_state: ctx.accounts.program_state.to_account_info(),
    token_program: ctx.accounts.token_program.to_account_info(),
};

let vrf_key = ctx.accounts.vrf.key.clone();
let authority_key = ctx.accounts.authority.key.clone();

let state_seeds: &[&[&[u8]]] = &[&[
    &STATE_SEED,
    vrf_key.as_ref(),
    authority_key.as_ref(),
    &[bump],
]];
msg!("requesting randomness");
vrf_request_randomness.invoke_signed(
    switchboard_program,
    params.switchboard_state_bump,
    params.permission_bump,
    state_seeds,
)?;

Dependencies

~58–78MB
~1.5M SLoC