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}