@@ -6,6 +6,7 @@ use async_stream::stream;
66use constants:: * ;
77use futures:: { Stream , StreamExt } ;
88use solana_transaction_status:: UiTransactionEncoding ;
9+ use tokio:: sync:: Mutex ;
910use std:: time:: Duration ;
1011use tracing:: { error, info, warn} ;
1112use types:: * ;
@@ -79,7 +80,8 @@ fn is_native_mint(mint_pubkey: &Pubkey) -> bool {
7980}
8081
8182pub struct SolanaTransport {
82- rpc : String ,
83+ rpcs : Vec < String > ,
84+ rpc_index : Mutex < usize > ,
8385 program_id : Pubkey ,
8486 client : RpcClient ,
8587 keypair : Option < Keypair > ,
@@ -1276,8 +1278,9 @@ impl TransportT for SolanaTransport {
12761278 & ' a self ,
12771279 addr : & ' a str ,
12781280 ) -> Result < Pin < Box < dyn Stream < Item = Result < GameAccount > > + Send + ' a > > > {
1281+
12791282 let ws_rpc = self
1280- . rpc
1283+ . next_rpc_url ( ) . await
12811284 . replace ( "https://" , "wss://" )
12821285 . replace ( "http://" , "ws://" ) ;
12831286 let game_account_pubkey = Self :: parse_pubkey ( addr) ?;
@@ -1565,9 +1568,10 @@ impl SolanaTransport {
15651568 keyfile : Option < PathBuf > ,
15661569 skip_preflight : bool ,
15671570 ) -> TransportResult < Self > {
1571+ let rpcs: Vec < String > = rpc. split ( ',' ) . map ( |s| s. trim ( ) . to_owned ( ) ) . collect ( ) ;
15681572 let keypair = keyfile. map ( read_keypair) . transpose ( ) ?;
15691573 let program_id = Pubkey :: from_str ( PROGRAM_ID ) ?;
1570- SolanaTransport :: try_new_with_program_id ( rpc , keypair, program_id, skip_preflight)
1574+ SolanaTransport :: try_new_with_program_id ( rpcs , keypair, program_id, skip_preflight)
15711575 }
15721576
15731577 pub ( crate ) fn payer ( & self ) -> TransportResult < ( & Keypair , Pubkey ) > {
@@ -1579,14 +1583,17 @@ impl SolanaTransport {
15791583 }
15801584
15811585 pub ( crate ) fn try_new_with_program_id (
1582- rpc : String ,
1586+ rpcs : Vec < String > ,
15831587 keypair : Option < Keypair > ,
15841588 program_id : Pubkey ,
15851589 skip_preflight : bool ,
15861590 ) -> TransportResult < Self > {
1591+ let Some ( first_rpc) = rpcs. first ( ) else {
1592+ panic ! ( "No RPC is specified for Solana transport" ) ;
1593+ } ;
15871594 println ! (
1588- "Create Solana transport: RPC : {}, program_id: {:?}" ,
1589- rpc , program_id
1595+ "Create Solana transport: RPCs : {:? }, program_id: {:?}" ,
1596+ rpcs , program_id
15901597 ) ;
15911598 let commitment = if cfg ! ( test) {
15921599 CommitmentConfig :: confirmed ( )
@@ -1595,19 +1602,27 @@ impl SolanaTransport {
15951602 } ;
15961603 let debug = skip_preflight;
15971604 let client = RpcClient :: new_with_timeout_and_commitment (
1598- rpc . clone ( ) ,
1605+ first_rpc . clone ( ) ,
15991606 Duration :: from_secs ( 60 ) ,
16001607 commitment,
16011608 ) ;
16021609 Ok ( Self {
1603- rpc,
1610+ rpcs,
1611+ rpc_index : Mutex :: new ( 0 ) ,
16041612 client,
16051613 keypair,
16061614 program_id,
16071615 debug,
16081616 } )
16091617 }
16101618
1619+ async fn next_rpc_url ( & self ) -> & str {
1620+ let mut rpc_index = self . rpc_index . lock ( ) . await ;
1621+ let current_index = * rpc_index;
1622+ * rpc_index = ( * rpc_index + 1 ) % self . rpcs . len ( ) ;
1623+ & self . rpcs [ current_index]
1624+ }
1625+
16111626 fn parse_pubkey ( addr : & str ) -> TransportResult < Pubkey > {
16121627 Pubkey :: from_str ( addr)
16131628 . map_err ( |_| TransportError :: InvalidConfig ( format ! ( "Can't parse public key: {}" , addr) ) )
0 commit comments