Skip to content

Commit a15e721

Browse files
author
DogLooksGood
committed
Support multiple RPC urls for subscription
1 parent 6600ac0 commit a15e721

1 file changed

Lines changed: 23 additions & 8 deletions

File tree

transport/src/solana.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use async_stream::stream;
66
use constants::*;
77
use futures::{Stream, StreamExt};
88
use solana_transaction_status::UiTransactionEncoding;
9+
use tokio::sync::Mutex;
910
use std::time::Duration;
1011
use tracing::{error, info, warn};
1112
use types::*;
@@ -79,7 +80,8 @@ fn is_native_mint(mint_pubkey: &Pubkey) -> bool {
7980
}
8081

8182
pub 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

Comments
 (0)