//! Example to utilize the `reconnecting rpc client` in subxt //! which hidden behind behind `--feature reconnecting-rpc-client` //! //! To utilize full logs from the RPC client use: //! `RUST_LOG="jsonrpsee=trace,subxt-reconnecting-rpc-client=trace"` #![allow(missing_docs)] use std::time::Duration; use futures::StreamExt; use subxt::backend::rpc::reconnecting_rpc_client::{ExponentialBackoff, RpcClient}; use subxt::{OnlineClient, PolkadotConfig}; // Generate an interface that we can use from the node's metadata. #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")] pub mod polkadot {} #[tokio::main] async fn main() -> Result<(), Box> { tracing_subscriber::fmt::init(); // Create a new client with with a reconnecting RPC client. let rpc = RpcClient::builder() // Reconnect with exponential backoff // // This API is "iterator-like" and we use `take` to limit the number of retries. .retry_policy( ExponentialBackoff::from_millis(100) .max_delay(Duration::from_secs(10)) .take(3), ) // There are other configurations as well that can be found at [`reconnecting_rpc_client::ClientBuilder`]. .build("ws://localhost:9944".to_string()) .await?; // If you want to use the chainhead backend with the reconnecting RPC client, you can do so like this: // // ``` // use subxt::backend::chain_head:ChainHeadBackend; // use subxt::OnlineClient; // // let backend = ChainHeadBackend::builder().build_with_background_task(RpcClient::new(rpc.clone())); // let api: OnlineClient = OnlineClient::from_backend(Arc::new(backend)).await?; // ``` let api: OnlineClient = OnlineClient::from_rpc_client(rpc.clone()).await?; // Run for at most 100 blocks and print a bunch of information about it. // // The subscription is automatically re-started when the RPC client has reconnected. // You can test that by stopping the polkadot node and restarting it. let mut blocks_sub = api.blocks().subscribe_finalized().await?.take(100); while let Some(block) = blocks_sub.next().await { let block = match block { Ok(b) => b, Err(e) => { // This can only happen on the legacy backend and the unstable backend // will handle this internally. if e.is_disconnected_will_reconnect() { println!("The RPC connection was lost and we may have missed a few blocks"); continue; } return Err(e.into()); } }; let block_number = block.number(); let block_hash = block.hash(); println!("Block #{block_number} ({block_hash})"); } Ok(()) }