switchboard_on_demand/
lib.rs

1#![allow(clippy::crate_in_macro_def)]
2#![allow(clippy::repr_packed_without_abi)]
3#![allow(clippy::manual_is_multiple_of)]
4#![doc(html_logo_url = "https://i.imgur.com/2cZloJp.png")]
5#![allow(unexpected_cfgs)]
6#![allow(unused_attributes)]
7#![allow(clippy::result_large_err)]
8//! # Switchboard On-Demand Oracle SDK
9//!
10//! Official Rust SDK for Switchboard On-Demand Oracles on Solana.
11//!
12//! This SDK provides secure, efficient access to real-time oracle data with
13//! comprehensive validation and zero-copy performance optimizations.
14//!
15//! ## Quick Start
16//!
17//! ```rust,no_run
18//! use switchboard_on_demand::prelude::*;
19//! # use solana_program::account_info::AccountInfo;
20//! # let queue_account: AccountInfo = todo!();
21//! # let slothash_sysvar: AccountInfo = todo!();
22//! # let instructions_sysvar: AccountInfo = todo!();
23//! # let clock_slot: u64 = 0;
24//!
25//! // Configure the verifier with required accounts
26//! let quote = QuoteVerifier::new()
27//!     .queue(&queue_account)
28//!     .slothash_sysvar(&slothash_sysvar)
29//!     .ix_sysvar(&instructions_sysvar)
30//!     .clock_slot(clock_slot)
31//!     .max_age(150)
32//!     .verify_instruction_at(0)?;
33//!
34//! // Access feed data
35//! for feed in quote.feeds() {
36//!     println!("Feed {}: {}", feed.hex_id(), feed.value());
37//! }
38//! # Ok::<(), Box<dyn std::error::Error>>(())
39//! ```
40//!
41//! ## Security Considerations
42//!
43//! - Always validate oracle data freshness with appropriate `max_age` values
44//! - Use minimum sample counts for critical operations
45//! - Verify feed signatures in production environments
46//! - Monitor for stale data and implement appropriate fallback mechanisms
47//!
48//! ## Feature Flags
49//!
50//! - `client` - Enable RPC client functionality
51//! - `anchor` - Enable Anchor framework integration
52
53// ===== Feature compatibility checks =====
54// These compile errors catch mutually exclusive features at build time
55
56#[cfg(all(feature = "solana-v2", feature = "solana-v3"))]
57compile_error!("Cannot enable both 'solana-v2' and 'solana-v3' features. Choose one: use 'solana-v2' for production or 'solana-v3' for experimental builds.");
58
59#[cfg(all(feature = "client", feature = "client-v3"))]
60compile_error!("Cannot enable both 'client' (v2) and 'client-v3' features. Use 'client' for Solana v2 or 'client-v3' for Solana v3.");
61
62#[cfg(all(feature = "client-v2", feature = "client-v3"))]
63compile_error!("Cannot enable both 'client-v2' and 'client-v3' features. Choose one client version.");
64
65// When both solana-v2 and client features are enabled, provide type compatibility layers
66#[cfg(all(feature = "solana-v2", feature = "client"))]
67pub mod v2_client_compat;
68
69#[cfg(all(feature = "solana-v2", feature = "client"))]
70pub mod instruction_compat;
71
72#[cfg(all(feature = "solana-v2", feature = "client"))]
73pub use instruction_compat::CompatInstruction;
74#[cfg(all(feature = "solana-v2", feature = "client"))]
75pub use v2_client_compat::IntoV2Instruction;
76
77// Implement the conversion trait at crate root so it's always available
78#[cfg(all(feature = "solana-v2", feature = "client"))]
79impl instruction_compat::mixed_version::IntoInstructionBytes
80    for anchor_lang::solana_program::instruction::Instruction
81{
82    fn into_bytes(self) -> ([u8; 32], Vec<([u8; 32], bool, bool)>, Vec<u8>) {
83        let program_id_bytes = self.program_id.to_bytes();
84        let accounts_data: Vec<([u8; 32], bool, bool)> = self
85            .accounts
86            .into_iter()
87            .map(|meta| (meta.pubkey.to_bytes(), meta.is_signer, meta.is_writable))
88            .collect();
89        (program_id_bytes, accounts_data, self.data)
90    }
91}
92
93mod macros;
94#[allow(unused_imports)]
95use std::sync::Arc;
96
97/// Current SDK version
98pub const VERSION: &str = env!("CARGO_PKG_VERSION");
99
100/// SDK name for identification
101pub const SDK_NAME: &str = "switchboard-on-demand";
102
103/// Supported Switchboard On-Demand program versions on Solana
104pub const SUPPORTED_PROGRAM_VERSIONS: &[&str] = &["0.7.0"];
105
106/// Minimum supported Solana version for compatibility
107pub const MIN_SOLANA_VERSION: &str = "1.18.0";
108
109/// Decimal number utilities for handling Switchboard oracle data
110pub mod decimal;
111pub use decimal::*;
112
113/// Small vector types with compact length prefixes for Borsh serialization
114pub mod smallvec;
115
116/// Core oracle functionality for on-demand data feeds
117pub mod on_demand;
118pub use on_demand::*;
119
120/// Utility functions and helpers
121pub mod utils;
122pub use utils::*;
123
124/// Associated token account utilities and constants
125pub mod associated_token_account;
126pub use associated_token_account::*;
127
128/// Traits extracted from anchor-lang to avoid dependency conflicts
129pub mod anchor_traits;
130pub use anchor_traits::*;
131
132/// Solana program ID constants
133pub mod program_id;
134pub use program_id::*;
135
136/// Solana account definitions and parsers
137pub mod accounts;
138/// Solana instruction builders and processors
139pub mod instructions;
140/// Common type definitions
141pub mod types;
142
143/// Re-exports of commonly used types and traits for convenience
144pub mod prelude;
145
146/// Solana version compatibility layer
147pub mod solana_compat;
148
149// Re-export everything from solana_compat for internal use
150pub use solana_compat::{solana_program, AccountMeta, Instruction, Pubkey};
151pub use SYSTEM_PROGRAM_ID;
152
153// Re-export solana_sdk for client code (when client or client-v3 feature is enabled)
154#[cfg(any(feature = "client", feature = "client-v3"))]
155pub use solana_compat::solana_sdk;
156
157/// Solana sysvar utilities
158pub mod sysvar;
159pub use sysvar::*;
160
161/// AccountInfo compatibility layer
162mod account_info_compat;
163pub use account_info_compat::{AccountInfo, AsAccountInfo};
164
165cfg_client! {
166    pub type RpcClient = crate::solana_compat::solana_client::nonblocking::rpc_client::RpcClient;
167
168    /// Client functionality for off-chain interactions with Switchboard On-Demand
169    ///
170    /// This module provides comprehensive tools for interacting with the Switchboard
171    /// Oracle Network and Crossbar API, including:
172    /// - Gateway and Crossbar API clients
173    /// - Pull feed management
174    /// - Oracle job definitions
175    /// - Transaction builders
176    /// - Cryptographic utilities
177    ///
178    /// Enable this module with the `client` feature flag.
179    ///
180    /// Access client functionality via the `client` module to avoid naming conflicts.
181    /// For example: `use switchboard_on_demand::client::{Gateway, PullFeed};`
182    pub mod client;
183
184    /// Returns the appropriate Switchboard On-Demand program ID for the current network.
185    ///
186    /// This client-compatible version returns Pubkey type.
187    pub fn get_switchboard_on_demand_program_id() -> crate::solana_compat::Pubkey {
188        use crate::solana_compat::Pubkey;
189        if is_devnet() {
190            Pubkey::from(crate::ON_DEMAND_DEVNET_PID.to_bytes())
191        } else {
192            Pubkey::from(crate::ON_DEMAND_MAINNET_PID.to_bytes())
193        }
194    }
195
196    /// Determines if the devnet environment is enabled for client usage.
197    pub fn is_devnet() -> bool {
198        cfg!(feature = "devnet") || std::env::var("SB_ENV").unwrap_or_default() == "devnet"
199    }
200
201    /// Seed bytes for deriving the Switchboard state account PDA.
202    pub const STATE_SEED: &[u8] = b"STATE";
203
204    /// Seed bytes for deriving oracle feed statistics account PDAs.
205    pub const ORACLE_FEED_STATS_SEED: &[u8] = b"OracleFeedStats";
206
207    /// Seed bytes for deriving oracle randomness statistics account PDAs.
208    pub const ORACLE_RANDOMNESS_STATS_SEED: &[u8] = b"OracleRandomnessStats";
209
210    /// Seed bytes for deriving oracle statistics account PDAs.
211    pub const ORACLE_STATS_SEED: &[u8] = b"OracleStats";
212
213    /// Seed bytes for deriving lookup table signer account PDAs.
214    pub const LUT_SIGNER_SEED: &[u8] = b"LutSigner";
215
216    /// Seed bytes for deriving delegation account PDAs.
217    pub const DELEGATION_SEED: &[u8] = b"Delegation";
218
219    /// Seed bytes for deriving delegation group account PDAs.
220    pub const DELEGATION_GROUP_SEED: &[u8] = b"Group";
221
222    /// Seed bytes for deriving reward pool vault account PDAs.
223    pub const REWARD_POOL_VAULT_SEED: &[u8] = b"RewardPool";
224}