From 293b4af34e0cd4072f9bc2fbd9b8cbf300629f04 Mon Sep 17 00:00:00 2001 From: Sergey Timoshin Date: Sun, 15 Jun 2025 22:22:40 +0100 Subject: [PATCH 1/3] refactor: replace `with_indexer` with `photon_url` in `LightClientConfig` and adjust related tests and RPC calls --- forester-utils/src/rpc_pool.rs | 2 +- forester/src/epoch_manager.rs | 8 +++----- forester/src/forester_status.rs | 2 +- forester/src/lib.rs | 3 +-- forester/tests/address_v2_test.rs | 13 +++---------- forester/tests/batched_address_test.rs | 2 +- .../tests/batched_state_async_indexer_test.rs | 12 ++---------- forester/tests/batched_state_indexer_test.rs | 12 ++---------- forester/tests/batched_state_test.rs | 2 +- forester/tests/e2e_test.rs | 13 ++++--------- forester/tests/priority_fee_test.rs | 12 ++---------- program-tests/utils/src/setup_accounts.rs | 2 +- sdk-libs/client/src/rpc/client.rs | 17 ++--------------- sdk-libs/client/src/rpc/rpc_trait.rs | 14 +++++++------- xtask/src/create_batch_address_tree.rs | 2 +- xtask/src/create_batch_state_tree.rs | 2 +- xtask/src/create_state_tree.rs | 2 +- xtask/src/create_update_protocol_config_ix.rs | 2 +- xtask/src/new_deployment.rs | 2 +- 19 files changed, 36 insertions(+), 88 deletions(-) diff --git a/forester-utils/src/rpc_pool.rs b/forester-utils/src/rpc_pool.rs index 0fae7f764f..bcb5cece5b 100644 --- a/forester-utils/src/rpc_pool.rs +++ b/forester-utils/src/rpc_pool.rs @@ -58,8 +58,8 @@ impl bb8::ManageConnection for SolanaConnectionManager { async fn connect(&self) -> Result { let config = LightClientConfig { url: self.url.to_string(), + photon_url: None, commitment_config: Some(self.commitment), - with_indexer: false, fetch_active_tree: false, }; diff --git a/forester/src/epoch_manager.rs b/forester/src/epoch_manager.rs index 6e9f13b8a6..17c12b60f3 100644 --- a/forester/src/epoch_manager.rs +++ b/forester/src/epoch_manager.rs @@ -475,10 +475,9 @@ impl + 'static> EpochManager { ) -> Result { let rpc = LightClient::new(LightClientConfig { url: self.config.external_services.rpc_url.to_string(), + photon_url: None, commitment_config: None, fetch_active_tree: false, - - with_indexer: false, }) .await .unwrap(); @@ -545,10 +544,9 @@ impl + 'static> EpochManager { info!("Registering for epoch: {}", epoch); let mut rpc = LightClient::new(LightClientConfig { url: self.config.external_services.rpc_url.to_string(), + photon_url: None, commitment_config: None, fetch_active_tree: false, - - with_indexer: false, }) .await .unwrap(); @@ -1198,9 +1196,9 @@ impl + 'static> EpochManager { info!("Reporting work"); let mut rpc = LightClient::new(LightClientConfig { url: self.config.external_services.rpc_url.to_string(), + photon_url: None, commitment_config: None, fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/forester/src/forester_status.rs b/forester/src/forester_status.rs index e889313c7a..45b03aba7e 100644 --- a/forester/src/forester_status.rs +++ b/forester/src/forester_status.rs @@ -175,9 +175,9 @@ pub async fn fetch_forester_status(args: &StatusArgs) { debug!("RPC URL: {}", config.external_services.rpc_url); let mut rpc = LightClient::new(LightClientConfig { url: config.external_services.rpc_url.to_string(), + photon_url: None, commitment_config: None, fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/forester/src/lib.rs b/forester/src/lib.rs index de80c83679..4920e74990 100644 --- a/forester/src/lib.rs +++ b/forester/src/lib.rs @@ -53,10 +53,9 @@ pub async fn run_queue_info( ) { let mut rpc = LightClient::new(LightClientConfig { url: config.external_services.rpc_url.to_string(), + photon_url: None, commitment_config: None, fetch_active_tree: false, - - with_indexer: false, }) .await .unwrap(); diff --git a/forester/tests/address_v2_test.rs b/forester/tests/address_v2_test.rs index 4ecf541066..d1a4671436 100644 --- a/forester/tests/address_v2_test.rs +++ b/forester/tests/address_v2_test.rs @@ -11,7 +11,7 @@ use light_batched_merkle_tree::{ use light_client::{ indexer::{photon_indexer::PhotonIndexer, AddressWithTree}, local_test_validator::{LightValidatorConfig, ProverConfig}, - rpc::{client::RpcUrl, merkle_tree::MerkleTreeExt, LightClient, LightClientConfig, Rpc}, + rpc::{merkle_tree::MerkleTreeExt, LightClient, LightClientConfig, Rpc}, }; use light_compressed_account::{ address::derive_address, @@ -32,7 +32,7 @@ use light_test_utils::{ use rand::{prelude::StdRng, Rng, SeedableRng}; use serial_test::serial; use solana_program::{native_token::LAMPORTS_PER_SOL, pubkey::Pubkey}; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Keypair, signer::Signer}; +use solana_sdk::{signature::Keypair, signer::Signer}; use tokio::sync::{mpsc, oneshot, Mutex}; use crate::test_utils::{forester_config, init}; @@ -71,14 +71,7 @@ async fn test_create_v2_address() { config.derivation_pubkey = env.protocol.forester.pubkey(); config.general_config = GeneralConfig::test_address_v2(); - let mut rpc = LightClient::new(LightClientConfig { - url: RpcUrl::Localnet.to_string(), - commitment_config: Some(CommitmentConfig::processed()), - fetch_active_tree: false, - with_indexer: true, - }) - .await - .unwrap(); + let mut rpc = LightClient::new(LightClientConfig::local()).await.unwrap(); rpc.payer = env.protocol.forester.insecure_clone(); ensure_sufficient_balance( diff --git a/forester/tests/batched_address_test.rs b/forester/tests/batched_address_test.rs index 84a27c1eac..3f239f1d7e 100644 --- a/forester/tests/batched_address_test.rs +++ b/forester/tests/batched_address_test.rs @@ -65,9 +65,9 @@ async fn test_address_batched() { let commitment_config = CommitmentConfig::confirmed(); let mut rpc = LightClient::new(LightClientConfig { url: RpcUrl::Localnet.to_string(), + photon_url: None, commitment_config: Some(commitment_config), fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/forester/tests/batched_state_async_indexer_test.rs b/forester/tests/batched_state_async_indexer_test.rs index c7759223a6..a661af39c1 100644 --- a/forester/tests/batched_state_async_indexer_test.rs +++ b/forester/tests/batched_state_async_indexer_test.rs @@ -12,7 +12,7 @@ use light_client::{ GetCompressedTokenAccountsByOwnerOrDelegateOptions, Indexer, }, local_test_validator::{LightValidatorConfig, ProverConfig}, - rpc::{client::RpcUrl, LightClient, LightClientConfig, Rpc}, + rpc::{LightClient, LightClientConfig, Rpc}, }; use light_compressed_account::{ address::derive_address_legacy, @@ -38,7 +38,6 @@ use rand::{prelude::SliceRandom, rngs::StdRng, Rng, SeedableRng}; use serial_test::serial; use solana_program::{native_token::LAMPORTS_PER_SOL, pubkey::Pubkey}; use solana_sdk::{ - commitment_config::CommitmentConfig, signature::{Keypair, Signature}, signer::Signer, }; @@ -222,14 +221,7 @@ async fn test_state_indexer_async_batched() { // ───────────────────────────────────────────────────────────────────────────── async fn setup_rpc_connection(forester: &Keypair) -> LightClient { - let mut rpc = LightClient::new(LightClientConfig { - url: RpcUrl::Localnet.to_string(), - commitment_config: Some(CommitmentConfig::processed()), - fetch_active_tree: false, - with_indexer: true, - }) - .await - .unwrap(); + let mut rpc = LightClient::new(LightClientConfig::local()).await.unwrap(); rpc.payer = forester.insecure_clone(); rpc } diff --git a/forester/tests/batched_state_indexer_test.rs b/forester/tests/batched_state_indexer_test.rs index 7657722e06..81ee4a4c1f 100644 --- a/forester/tests/batched_state_indexer_test.rs +++ b/forester/tests/batched_state_indexer_test.rs @@ -12,7 +12,7 @@ use light_batched_merkle_tree::{ use light_client::{ indexer::{photon_indexer::PhotonIndexer, Indexer, IndexerRpcConfig, RetryConfig}, local_test_validator::{LightValidatorConfig, ProverConfig}, - rpc::{client::RpcUrl, LightClient, LightClientConfig, Rpc}, + rpc::{LightClient, LightClientConfig, Rpc}, }; use light_compressed_account::TreeType; use light_program_test::{accounts::test_accounts::TestAccounts, indexer::TestIndexer}; @@ -61,15 +61,7 @@ async fn test_state_indexer_batched() { .await .unwrap(); - let commitment_config = CommitmentConfig::confirmed(); - let mut rpc = LightClient::new(LightClientConfig { - url: RpcUrl::Localnet.to_string(), - fetch_active_tree: false, - commitment_config: Some(commitment_config), - with_indexer: true, - }) - .await - .unwrap(); + let mut rpc = LightClient::new(LightClientConfig::local()).await.unwrap(); rpc.payer = forester_keypair.insecure_clone(); rpc.airdrop_lamports(&forester_keypair.pubkey(), LAMPORTS_PER_SOL * 100_000) diff --git a/forester/tests/batched_state_test.rs b/forester/tests/batched_state_test.rs index 8af791edd1..c88fdf4a0d 100644 --- a/forester/tests/batched_state_test.rs +++ b/forester/tests/batched_state_test.rs @@ -69,9 +69,9 @@ async fn test_state_batched() { let commitment_config = CommitmentConfig::confirmed(); let mut rpc = LightClient::new(LightClientConfig { url: RpcUrl::Localnet.to_string(), + photon_url: None, commitment_config: Some(commitment_config), fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/forester/tests/e2e_test.rs b/forester/tests/e2e_test.rs index 267b182332..386e31cb8f 100644 --- a/forester/tests/e2e_test.rs +++ b/forester/tests/e2e_test.rs @@ -60,14 +60,9 @@ async fn test_epoch_monitor_with_2_foresters() { .await .unwrap(); - let mut rpc = LightClient::new(LightClientConfig { - url: RpcUrl::Localnet.to_string(), - commitment_config: Some(CommitmentConfig::confirmed()), - fetch_active_tree: false, - with_indexer: false, - }) - .await - .unwrap(); + let mut rpc = LightClient::new(LightClientConfig::local_no_indexer()) + .await + .unwrap(); rpc.payer = forester_keypair1.insecure_clone(); // Airdrop to both foresters and governance authority @@ -410,9 +405,9 @@ async fn test_epoch_double_registration() { let mut rpc = LightClient::new(LightClientConfig { url: RpcUrl::Localnet.to_string(), + photon_url: None, commitment_config: Some(CommitmentConfig::confirmed()), fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/forester/tests/priority_fee_test.rs b/forester/tests/priority_fee_test.rs index c418775d9b..ba0af91efd 100644 --- a/forester/tests/priority_fee_test.rs +++ b/forester/tests/priority_fee_test.rs @@ -7,9 +7,8 @@ use forester::{ ForesterConfig, }; use light_client::rpc::{LightClient, LightClientConfig, Rpc}; -use light_test_utils::RpcUrl; use reqwest::Url; -use solana_sdk::{commitment_config::CommitmentConfig, signature::Signer}; +use solana_sdk::signature::Signer; use crate::test_utils::init; mod test_utils; @@ -79,14 +78,7 @@ async fn test_priority_fee_request() { let config = ForesterConfig::new_for_start(&args).expect("Failed to create config"); // Setup RPC connection using config - let mut rpc = LightClient::new(LightClientConfig { - url: RpcUrl::Localnet.to_string(), - commitment_config: Some(CommitmentConfig::confirmed()), - fetch_active_tree: false, - with_indexer: false, - }) - .await - .unwrap(); + let mut rpc = LightClient::new(LightClientConfig::local()).await.unwrap(); rpc.payer = config.payer_keypair.insecure_clone(); let account_keys = vec![config.payer_keypair.pubkey()]; diff --git a/program-tests/utils/src/setup_accounts.rs b/program-tests/utils/src/setup_accounts.rs index 05561466bb..c52fd86002 100644 --- a/program-tests/utils/src/setup_accounts.rs +++ b/program-tests/utils/src/setup_accounts.rs @@ -13,7 +13,7 @@ pub async fn setup_accounts(keypairs: TestKeypairs, url: RpcUrl) -> Result, - pub with_indexer: bool, + pub photon_url: Option, pub fetch_active_tree: bool, } impl LightClientConfig { - pub fn new(url: String) -> Self { + pub fn new(url: String, photon_url: Option) -> Self { Self { url, + photon_url, commitment_config: Some(CommitmentConfig::confirmed()), - with_indexer: true, fetch_active_tree: true, } } @@ -44,7 +44,7 @@ impl LightClientConfig { Self { url: RpcUrl::Localnet.to_string(), commitment_config: Some(CommitmentConfig::confirmed()), - with_indexer: false, + photon_url: None, fetch_active_tree: false, } } @@ -53,16 +53,16 @@ impl LightClientConfig { Self { url: RpcUrl::Localnet.to_string(), commitment_config: Some(CommitmentConfig::confirmed()), - with_indexer: true, + photon_url: Some("http://127.0.0.1:8784".to_string()), fetch_active_tree: false, } } - pub fn devnet() -> Self { + pub fn devnet(photon_url: Option) -> Self { Self { url: RpcUrl::Devnet.to_string(), + photon_url, commitment_config: Some(CommitmentConfig::confirmed()), - with_indexer: true, fetch_active_tree: true, } } diff --git a/xtask/src/create_batch_address_tree.rs b/xtask/src/create_batch_address_tree.rs index 3b7f18c1d8..ffb39ef368 100644 --- a/xtask/src/create_batch_address_tree.rs +++ b/xtask/src/create_batch_address_tree.rs @@ -41,9 +41,9 @@ pub async fn create_batch_address_tree(options: Options) -> anyhow::Result<()> { }; let mut rpc = LightClient::new(LightClientConfig { url: rpc_url, + photon_url: None, commitment_config: None, fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/xtask/src/create_batch_state_tree.rs b/xtask/src/create_batch_state_tree.rs index 961892dd8f..0cf7810b71 100644 --- a/xtask/src/create_batch_state_tree.rs +++ b/xtask/src/create_batch_state_tree.rs @@ -46,9 +46,9 @@ pub async fn create_batch_state_tree(options: Options) -> anyhow::Result<()> { }; let mut rpc = LightClient::new(LightClientConfig { url: rpc_url, + photon_url: None, commitment_config: None, fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/xtask/src/create_state_tree.rs b/xtask/src/create_state_tree.rs index acae6ec14c..e1b8a7b733 100644 --- a/xtask/src/create_state_tree.rs +++ b/xtask/src/create_state_tree.rs @@ -46,9 +46,9 @@ pub async fn create_state_tree(options: Options) -> anyhow::Result<()> { }; let mut rpc = LightClient::new(LightClientConfig { url: rpc_url, + photon_url: None, commitment_config: None, fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/xtask/src/create_update_protocol_config_ix.rs b/xtask/src/create_update_protocol_config_ix.rs index 7c3ba921c0..a2a136d541 100644 --- a/xtask/src/create_update_protocol_config_ix.rs +++ b/xtask/src/create_update_protocol_config_ix.rs @@ -34,9 +34,9 @@ pub async fn create_update_protocol_config_ix(options: Options) -> anyhow::Resul let rpc_url = String::from("https://api.mainnet-beta.solana.com"); let rpc = LightClient::new(LightClientConfig { url: rpc_url, + photon_url: None, commitment_config: None, fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); diff --git a/xtask/src/new_deployment.rs b/xtask/src/new_deployment.rs index 689f3ad3b4..4cb7f6f5ff 100644 --- a/xtask/src/new_deployment.rs +++ b/xtask/src/new_deployment.rs @@ -55,9 +55,9 @@ pub async fn init_new_deployment(options: Options) -> anyhow::Result<()> { }; let mut rpc = LightClient::new(LightClientConfig { url: rpc_url, + photon_url: None, commitment_config: None, fetch_active_tree: false, - with_indexer: false, }) .await .unwrap(); From 69c1204ff0f6f91ef72c6b1c2f9802d1ca8922e7 Mon Sep 17 00:00:00 2001 From: Sergey Timoshin Date: Sun, 15 Jun 2025 22:48:43 +0100 Subject: [PATCH 2/3] use `indexer_url` from config as photon_url in register_for_epoch_with_retry --- forester/src/epoch_manager.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forester/src/epoch_manager.rs b/forester/src/epoch_manager.rs index 17c12b60f3..4402a74794 100644 --- a/forester/src/epoch_manager.rs +++ b/forester/src/epoch_manager.rs @@ -475,7 +475,7 @@ impl + 'static> EpochManager { ) -> Result { let rpc = LightClient::new(LightClientConfig { url: self.config.external_services.rpc_url.to_string(), - photon_url: None, + photon_url: self.config.external_services.indexer_url.clone(), commitment_config: None, fetch_active_tree: false, }) From 34b60b39b43abbc045509ba569ef56a1a7bfbcc7 Mon Sep 17 00:00:00 2001 From: Sergey Timoshin Date: Sun, 15 Jun 2025 22:59:24 +0100 Subject: [PATCH 3/3] forester: use `indexer_url` from config as photon_url in `SolanaRpcPoolBuilder` --- forester-utils/src/rpc_pool.rs | 14 +++++++++++++- forester/src/lib.rs | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/forester-utils/src/rpc_pool.rs b/forester-utils/src/rpc_pool.rs index bcb5cece5b..cc9037ff30 100644 --- a/forester-utils/src/rpc_pool.rs +++ b/forester-utils/src/rpc_pool.rs @@ -26,6 +26,7 @@ pub enum PoolError { pub struct SolanaConnectionManager { url: String, + photon_url: Option, commitment: CommitmentConfig, // TODO: implement Rpc for SolanaConnectionManager and rate limit requests. _rpc_rate_limiter: Option, @@ -36,12 +37,14 @@ pub struct SolanaConnectionManager { impl SolanaConnectionManager { pub fn new( url: String, + photon_url: Option, commitment: CommitmentConfig, rpc_rate_limiter: Option, send_tx_rate_limiter: Option, ) -> Self { Self { url, + photon_url, commitment, _rpc_rate_limiter: rpc_rate_limiter, _send_tx_rate_limiter: send_tx_rate_limiter, @@ -58,7 +61,7 @@ impl bb8::ManageConnection for SolanaConnectionManager { async fn connect(&self) -> Result { let config = LightClientConfig { url: self.url.to_string(), - photon_url: None, + photon_url: self.photon_url.clone(), commitment_config: Some(self.commitment), fetch_active_tree: false, }; @@ -86,6 +89,8 @@ pub struct SolanaRpcPool { #[derive(Debug)] pub struct SolanaRpcPoolBuilder { url: Option, + photon_url: Option, + commitment: Option, max_size: u32, @@ -110,6 +115,7 @@ impl SolanaRpcPoolBuilder { pub fn new() -> Self { Self { url: None, + photon_url: None, commitment: None, max_size: 50, connection_timeout_secs: 15, @@ -128,6 +134,11 @@ impl SolanaRpcPoolBuilder { self } + pub fn photon_url(mut self, url: Option) -> Self { + self.photon_url = url; + self + } + pub fn commitment(mut self, commitment: CommitmentConfig) -> Self { self.commitment = Some(commitment); self @@ -183,6 +194,7 @@ impl SolanaRpcPoolBuilder { let manager = SolanaConnectionManager::new( url, + self.photon_url, commitment, self.rpc_rate_limiter, self.send_tx_rate_limiter, diff --git a/forester/src/lib.rs b/forester/src/lib.rs index 4920e74990..3fdc4f8ceb 100644 --- a/forester/src/lib.rs +++ b/forester/src/lib.rs @@ -100,6 +100,7 @@ pub async fn run_pipeline + 'static>( ) -> Result<()> { let mut builder = SolanaRpcPoolBuilder::::default() .url(config.external_services.rpc_url.to_string()) + .photon_url(config.external_services.indexer_url.clone()) .commitment(CommitmentConfig::confirmed()) .max_size(config.rpc_pool_config.max_size) .connection_timeout_secs(config.rpc_pool_config.connection_timeout_secs)