@@ -111,7 +111,7 @@ pub struct NetworkState {
111111/// fetching the blockhash and slot number.
112112struct NetworkStateQuerier {
113113 /// The RPC client
114- rpc_client : RpcClient ,
114+ rpc_clients : Vec < RpcClient > ,
115115
116116 /// The interval with which to query the network state
117117 query_interval : Interval ,
@@ -122,20 +122,24 @@ struct NetworkStateQuerier {
122122
123123impl NetworkStateQuerier {
124124 #[ instrument(
125- skip( rpc_endpoint , rpc_timeout, query_interval) ,
125+ skip( rpc_urls , rpc_timeout, query_interval) ,
126126 fields(
127127 rpc_timeout = rpc_timeout. as_millis( ) ,
128128 query_interval = query_interval. period( ) . as_millis( ) ,
129129 )
130130 ) ]
131131 pub fn new (
132- rpc_endpoint : & str ,
132+ rpc_urls : & Vec < String > ,
133133 rpc_timeout : Duration ,
134134 query_interval : Interval ,
135135 network_state_tx : watch:: Sender < NetworkState > ,
136136 ) -> Self {
137+ let rpc_clients = rpc_urls
138+ . iter ( )
139+ . map ( |rpc_url| RpcClient :: new_with_timeout ( rpc_url. clone ( ) , rpc_timeout) )
140+ . collect ( ) ;
137141 NetworkStateQuerier {
138- rpc_client : RpcClient :: new_with_timeout ( rpc_endpoint . to_string ( ) , rpc_timeout ) ,
142+ rpc_clients ,
139143 query_interval,
140144 network_state_tx,
141145 }
@@ -152,11 +156,12 @@ impl NetworkStateQuerier {
152156
153157 #[ instrument( skip( self ) ) ]
154158 async fn query_network_state ( & mut self ) -> Result < ( ) > {
159+ // TODO: These are polled every 200ms and errors are simply logged.
160+ // TODO: Should we retry/fallback on failure?
155161 // Fetch the blockhash and current slot in parallel
156- let current_slot_future = self
157- . rpc_client
158- . get_slot_with_commitment ( CommitmentConfig :: confirmed ( ) ) ;
159- let latest_blockhash_future = self . rpc_client . get_latest_blockhash ( ) ;
162+ let current_slot_future =
163+ self . rpc_clients [ 0 ] . get_slot_with_commitment ( CommitmentConfig :: confirmed ( ) ) ;
164+ let latest_blockhash_future = self . rpc_clients [ 0 ] . get_latest_blockhash ( ) ;
160165
161166 let ( current_slot_result, latest_blockhash_result) =
162167 future:: join ( current_slot_future, latest_blockhash_future) . await ;
@@ -183,7 +188,7 @@ where
183188 // Create and spawn the network state querier
184189 let ( network_state_tx, network_state_rx) = watch:: channel ( Default :: default ( ) ) ;
185190 let mut network_state_querier = NetworkStateQuerier :: new (
186- & config. rpc_url ,
191+ & config. rpc_urls ,
187192 config. rpc_timeout ,
188193 tokio:: time:: interval ( config. exporter . refresh_network_state_interval_duration ) ,
189194 network_state_tx,
@@ -226,6 +231,7 @@ mod exporter {
226231 } ,
227232 } ,
228233 solana_client:: nonblocking:: rpc_client:: RpcClient ,
234+ solana_sdk:: commitment_config:: CommitmentConfig ,
229235 std:: sync:: Arc ,
230236 tokio:: sync:: watch,
231237 } ;
@@ -243,10 +249,21 @@ mod exporter {
243249 let mut dynamic_compute_unit_price_update_interval =
244250 tokio:: time:: interval ( config. exporter . publish_interval_duration ) ;
245251
246- let client = Arc :: new ( RpcClient :: new_with_timeout (
247- config. rpc_url . to_string ( ) ,
248- config. rpc_timeout ,
249- ) ) ;
252+ let clients: Arc < Vec < RpcClient > > = Arc :: new (
253+ config
254+ . rpc_urls
255+ . iter ( )
256+ . map ( |rpc_url| {
257+ RpcClient :: new_with_timeout_and_commitment (
258+ rpc_url. clone ( ) ,
259+ config. rpc_timeout ,
260+ CommitmentConfig {
261+ commitment : config. oracle . commitment ,
262+ } ,
263+ )
264+ } )
265+ . collect ( ) ,
266+ ) ;
250267 let Ok ( key_store) = KeyStore :: new ( config. key_store . clone ( ) ) else {
251268 tracing:: warn!( "Key store not available, Exporter won't start." ) ;
252269 return ;
@@ -265,7 +282,7 @@ mod exporter {
265282 let publisher_buffer_key = Exporter :: get_publisher_buffer_key( & * state) . await ;
266283 if let Err ( err) = publish_batches(
267284 state. clone( ) ,
268- client . clone( ) ,
285+ clients . clone( ) ,
269286 network,
270287 & network_state_rx,
271288 key_store. accumulator_key,
@@ -293,7 +310,7 @@ mod exporter {
293310 if let Err ( err) = Exporter :: update_recent_compute_unit_price(
294311 & * state,
295312 & publish_keypair,
296- & client ,
313+ & clients ,
297314 config. exporter. staleness_threshold,
298315 config. exporter. unchanged_publish_threshold,
299316 ) . await {
@@ -352,13 +369,17 @@ mod transaction_monitor {
352369 where
353370 S : Transactions ,
354371 {
355- let client = RpcClient :: new_with_timeout ( config. rpc_url . to_string ( ) , config. rpc_timeout ) ;
372+ let rpc_clients = config
373+ . rpc_urls
374+ . iter ( )
375+ . map ( |rpc_url| RpcClient :: new_with_timeout ( rpc_url. clone ( ) , config. rpc_timeout ) )
376+ . collect ( ) ;
356377 let mut poll_interval =
357378 tokio:: time:: interval ( config. exporter . transaction_monitor . poll_interval_duration ) ;
358379
359380 loop {
360381 poll_interval. tick ( ) . await ;
361- if let Err ( err) = Transactions :: poll_transactions_status ( & * state, & client ) . await {
382+ if let Err ( err) = Transactions :: poll_transactions_status ( & * state, & rpc_clients ) . await {
362383 tracing:: error!( err = ?err, "Transaction monitor failed." ) ;
363384 }
364385 }
0 commit comments