1pub use solana_commitment_config::CommitmentConfig;
3pub use solana_commitment_config::CommitmentLevel;
4pub use solana_compute_budget_interface::ComputeBudgetInstruction;
5pub use solana_hash::Hash;
6pub use solana_instruction::Instruction;
7pub use solana_keypair::Signer;
8pub use solana_message::AddressLookupTableAccount;
9pub use solana_message::{v0::Message, Message as LegacyMessage, VersionedMessage};
10pub use solana_pubkey::Pubkey;
11pub use solana_signature::Signature;
12pub use solana_transaction::versioned::VersionedTransaction;
13pub use solana_transaction::Transaction;
14pub use solana_client::rpc_config::RpcSendTransactionConfig;
16pub use std::time::{Duration, Instant};
18pub use tokio::time::sleep;
19
20use solana_client::nonblocking::rpc_client::RpcClient;
21use std::sync::{Arc, OnceLock, RwLock};
22
23use crate::fee_config::{FeeConfig, JitoFeeStrategy, PriorityFeeStrategy};
24use crate::rpc_config::RpcConfig;
25
26static GLOBAL_CONFIG: OnceLock<RwLock<GlobalConfig>> = OnceLock::new();
32
33pub(crate) fn get_global_config() -> &'static RwLock<GlobalConfig> {
35 GLOBAL_CONFIG.get_or_init(|| {
36 RwLock::new(GlobalConfig {
37 rpc_config: None,
38 rpc_client: None,
39 fee_config: FeeConfig::default(),
40 })
41 })
42}
43
44#[derive(Clone)]
53pub struct GlobalConfig {
54 pub rpc_config: Option<RpcConfig>,
56 pub rpc_client: Option<Arc<RpcClient>>,
58 pub fee_config: FeeConfig,
59}
60
61pub async fn set_rpc(url: &str) -> Result<(), String> {
63 let rpc_config = RpcConfig::new(url).await?;
64 let rpc_client = Arc::new(rpc_config.client());
65
66 let mut config = get_global_config()
67 .write()
68 .map_err(|e| format!("Lock error: {}", e))?;
69 config.rpc_config = Some(rpc_config);
70 config.rpc_client = Some(rpc_client);
71 Ok(())
72}
73
74pub fn set_priority_fee_strategy(strategy: PriorityFeeStrategy) -> Result<(), String> {
76 let mut config = get_global_config()
77 .write()
78 .map_err(|e| format!("Lock error: {}", e))?;
79 config.fee_config.priority_fee = strategy;
80 Ok(())
81}
82
83pub fn set_jito_fee_strategy(strategy: JitoFeeStrategy) -> Result<(), String> {
85 let mut config = get_global_config()
86 .write()
87 .map_err(|e| format!("Lock error: {}", e))?;
88 config.fee_config.jito = strategy;
89 Ok(())
90}
91
92pub fn set_compute_unit_margin_multiplier(multiplier: f64) -> Result<(), String> {
94 let mut config = get_global_config()
95 .write()
96 .map_err(|e| format!("Lock error: {}", e))?;
97 config.fee_config.compute_unit_margin_multiplier = multiplier;
98 Ok(())
99}
100
101pub fn set_jito_block_engine_url(url: String) -> Result<(), String> {
103 let mut config = get_global_config()
104 .write()
105 .map_err(|e| format!("Lock error: {}", e))?;
106 config.fee_config.jito_block_engine_url = url;
107 Ok(())
108}
109
110pub fn get_rpc_client() -> Result<Arc<RpcClient>, String> {
112 let config = get_global_config()
113 .read()
114 .map_err(|e| format!("Lock error: {}", e))?;
115 config
117 .rpc_client
118 .clone()
119 .ok_or_else(|| "RPC not configured. Call set_rpc() first.".to_string())
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_global_config() {
128 set_compute_unit_margin_multiplier(1.2).unwrap();
130
131 let config = get_global_config().read().unwrap();
132 assert_eq!(config.fee_config.compute_unit_margin_multiplier, 1.2);
133
134 assert!(config.rpc_config.is_none());
136 assert!(config.rpc_client.is_none());
137 }
138}