solana_central/central_context/central_context.rs
1use crate::constants::PUMP_CONSTANTS;
2use crate::constants::RAYDIUM_CONSTANTS;
3use crate::types::meteora_vault::MeteoraVault;
4use crate::types::pf_bonding_curve::PfBondingCurve;
5use crate::types::pool::PoolTrait;
6use crate::types::raydium_launchpad::RaydiumLaunchpad;
7use solana_client;
8use solana_client::rpc_client::RpcClient;
9use solana_sdk::hash::Hash;
10use solana_sdk::pubkey::Pubkey;
11use std::collections::HashMap;
12use std::collections::HashSet;
13use std::env;
14use std::sync::{Arc, Mutex, RwLock};
15use std::time::Duration;
16
17/// Central context for managing DEX liquidity pools, markets, and RPC clients
18///
19/// This structure serves as the shared state across all pool operations, providing
20/// thread-safe access to:
21/// - Market graphs with bidirectional token pair mappings (markets["wsol"]["usdc"] will give you
22/// the same thread safe access as if you did markets["usdc"]["wsol"])
23/// - Protocol-specific pools and vaults
24/// - JSON RPC clients for on-chain data fetching
25/// - Token validation and legitimacy tracking
26/// - Current network state (slot, blockhash)
27pub struct CentralContext {
28 /// Bidirectional market graph: token A -> token B -> list of pools
29 ///
30 /// Markets are stored bidirectionally so pools can be looked up by either
31 /// token in the pair. Each pool is wrapped in Arc<RwLock<>> for shared
32 /// ownership and thread-safe access.
33 /// - RwLock on both layers of the hash map for mutability
34 /// - Arc on the vector for bidirectional reference
35 /// - RwLock on the vector for mutability and adding new markets in
36 /// - RwLock on the pool traits to modify the pools states
37 pub markets:
38 RwLock<HashMap<Pubkey, HashMap<Pubkey, Arc<RwLock<Vec<Arc<RwLock<dyn PoolTrait>>>>>>>>,
39 /// Synchronous JSON RPC client for Solana network requests
40 pub json_rpc_client: solana_client::rpc_client::RpcClient,
41 /// Asynchronous JSON RPC client for concurrent network requests
42 pub json_rpc_client_async: solana_client::nonblocking::rpc_client::RpcClient,
43 /// Fee rates for Raydium CPMM pools, keyed by config account address
44 ///
45 /// Stored in lamports (10^9 = 1 SOL) for high precision. Can be loaded during initialization via
46 /// the load_cpmm_pool_configs function and available throughout the process lifetime.
47 pub raydium_cpmm_fee_rates_lp: HashMap<Pubkey, u64>,
48 /// Cache of Meteora Ammv1 vaults keyed by token address
49 ///
50 /// Protected by Mutex to ensure only one vault instance exists per token, preventing race
51 /// conditions. Multiple pools should reference the same token vault as only one per token. Avoid
52 /// creating multiple vaults per token.
53 pub meteora_vault_cache: Mutex<HashMap<Pubkey, Arc<RwLock<MeteoraVault>>>>,
54 /// Cache of Pumpfun bonding curves keyed by bonding curve address
55 ///
56 /// Protected by Mutex for thread-safe read-check-write operations when
57 /// creating new bonding curve instances.
58 pub pf_bonding_curves: Mutex<HashMap<Pubkey, Arc<RwLock<PfBondingCurve>>>>,
59 /// Cache of Raydium launchpads keyed by launchpad/market address
60 ///
61 /// Protected by Mutex for thread-safe read-check-write operations when
62 /// creating new bonding curve instances.
63 pub raydium_launchpads: Mutex<HashMap<Pubkey, Arc<RwLock<RaydiumLaunchpad>>>>,
64 /// Cache of token legitimacy flags keyed by token address
65 ///
66 /// A token is considered legit if it has Metaplex metadata and the update authority
67 /// matches a reputable launchpad (Raydium Launchpad or Pumpfun Bonding Curve).
68 /// Mutex for lookup and then store if not in cache (write based on read)
69 pub legit_tokens: Mutex<HashMap<Pubkey, bool>>,
70 /// Set of legitimate update authorities used to validate tokens
71 ///
72 /// Contains update authorities from known reputable launchpads (Raydium Launchpad and Pumpfun
73 /// Bonding Curve only for now)
74 pub legit_update_authorities: HashSet<Pubkey>,
75 /// Map of account addresses to pools for efficient pool lookup
76 ///
77 /// A pool can be looked up by its pool address, token A vault address, or token B vault address.
78 /// Updated automatically when pools are inserted via `insert_pool`.
79 pub pools_map: RwLock<HashMap<Pubkey, Arc<RwLock<dyn PoolTrait>>>>,
80 /// Current slot being produced by the Solana network
81 pub current_slot: RwLock<u64>,
82 /// Most recent blockhash produced by the network
83 ///
84 /// Typically the blockhash of slot (current_slot - 1).
85 pub latest_blockhash: RwLock<Hash>,
86}
87
88impl CentralContext {
89 /// Create a new `CentralContext` instance
90 ///
91 /// Initializes RPC clients, empty caches, and sets up legitimate update authorities
92 /// from known reputable launchpads. Requires `RPC_NODE_URL` environment variable to be set.
93 pub fn new() -> Self {
94 let rpc_url = env::var("RPC_NODE_URL").expect("RPC_NODE_URL must be set");
95 let json_rpc_client = RpcClient::new_with_timeout(&rpc_url, Duration::from_secs(300));
96 let json_rpc_client_async = solana_client::nonblocking::rpc_client::RpcClient::new_with_timeout(
97 rpc_url,
98 Duration::from_secs(300),
99 );
100
101 let mut legit_update_authorities = HashSet::new();
102 // Raydium launchpad update authority
103 legit_update_authorities.insert(RAYDIUM_CONSTANTS.launchpad_authority);
104 // Pumpfun bonding curve update authority
105 legit_update_authorities.insert(PUMP_CONSTANTS.bonding_curve_update_authority);
106
107 Self {
108 markets: RwLock::new(HashMap::new()),
109 pf_bonding_curves: Mutex::new(HashMap::new()),
110 json_rpc_client,
111 json_rpc_client_async,
112 raydium_cpmm_fee_rates_lp: HashMap::new(),
113 raydium_launchpads: Mutex::new(HashMap::new()),
114 meteora_vault_cache: Mutex::new(HashMap::new()),
115 current_slot: RwLock::new(0),
116 pools_map: RwLock::new(HashMap::new()),
117 latest_blockhash: RwLock::new(Hash::default()),
118 legit_tokens: Mutex::new(HashMap::new()),
119 legit_update_authorities,
120 }
121 }
122}