//! Communication with a Solana node over RPC. //! //! Software that interacts with the Solana blockchain, whether querying its //! state or submitting transactions, communicates with a Solana node over //! [JSON-RPC], using the [`RpcClient`] type. //! //! [JSON-RPC]: https://www.jsonrpc.org/specification //! //! This is a blocking API. For a non-blocking API use the asynchronous client //! in [`crate::nonblocking::rpc_client`]. pub use crate::mock_sender::Mocks; #[allow(deprecated)] use solana_rpc_client_api::deprecated_config::{ RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig, }; use { crate::{ http_sender::HttpSender, mock_sender::MockSender, nonblocking::{self, rpc_client::get_rpc_request_str}, rpc_sender::*, }, serde::Serialize, serde_json::Value, solana_account_decoder::{ parse_token::{UiTokenAccount, UiTokenAmount}, UiAccount, UiAccountEncoding, }, solana_rpc_client_api::{ client_error::{Error as ClientError, ErrorKind, Result as ClientResult}, config::{RpcAccountInfoConfig, *}, request::{RpcRequest, TokenAccountsFilter}, response::*, }, solana_sdk::{ account::{Account, ReadableAccount}, clock::{Epoch, Slot, UnixTimestamp}, commitment_config::CommitmentConfig, epoch_info::EpochInfo, epoch_schedule::EpochSchedule, feature::Feature, fee_calculator::{FeeCalculator, FeeRateGovernor}, hash::Hash, message::{v0, Message as LegacyMessage}, pubkey::Pubkey, signature::Signature, transaction::{self, uses_durable_nonce, Transaction, VersionedTransaction}, }, solana_transaction_status::{ EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus, UiConfirmedBlock, UiTransactionEncoding, }, std::{net::SocketAddr, str::FromStr, sync::Arc, time::Duration}, }; #[derive(Default)] pub struct RpcClientConfig { pub commitment_config: CommitmentConfig, pub confirm_transaction_initial_timeout: Option, } impl RpcClientConfig { pub fn with_commitment(commitment_config: CommitmentConfig) -> Self { RpcClientConfig { commitment_config, ..Self::default() } } } /// Trait used to add support for versioned messages to RPC APIs while /// retaining backwards compatibility pub trait SerializableMessage: Serialize {} impl SerializableMessage for LegacyMessage {} impl SerializableMessage for v0::Message {} /// Trait used to add support for versioned transactions to RPC APIs while /// retaining backwards compatibility pub trait SerializableTransaction: Serialize { fn get_signature(&self) -> &Signature; fn get_recent_blockhash(&self) -> &Hash; fn uses_durable_nonce(&self) -> bool; } impl SerializableTransaction for Transaction { fn get_signature(&self) -> &Signature { &self.signatures[0] } fn get_recent_blockhash(&self) -> &Hash { &self.message.recent_blockhash } fn uses_durable_nonce(&self) -> bool { uses_durable_nonce(self).is_some() } } impl SerializableTransaction for VersionedTransaction { fn get_signature(&self) -> &Signature { &self.signatures[0] } fn get_recent_blockhash(&self) -> &Hash { self.message.recent_blockhash() } fn uses_durable_nonce(&self) -> bool { self.uses_durable_nonce() } } #[derive(Debug, Default)] pub struct GetConfirmedSignaturesForAddress2Config { pub before: Option, pub until: Option, pub limit: Option, pub commitment: Option, } /// A client of a remote Solana node. /// /// `RpcClient` communicates with a Solana node over [JSON-RPC], with the /// [Solana JSON-RPC protocol][jsonprot]. It is the primary Rust interface for /// querying and transacting with the network from external programs. /// /// This type builds on the underlying RPC protocol, adding extra features such /// as timeout handling, retries, and waiting on transaction [commitment levels][cl]. /// Some methods simply pass through to the underlying RPC protocol. Not all RPC /// methods are encapsulated by this type, but `RpcClient` does expose a generic /// [`send`](RpcClient::send) method for making any [`RpcRequest`]. /// /// The documentation for most `RpcClient` methods contains an "RPC Reference" /// section that links to the documentation for the underlying JSON-RPC method. /// The documentation for `RpcClient` does not reproduce the documentation for /// the underlying JSON-RPC methods. Thus reading both is necessary for complete /// understanding. /// /// `RpcClient`s generally communicate over HTTP on port 8899, a typical server /// URL being "http://localhost:8899". /// /// Methods that query information from recent [slots], including those that /// confirm transactions, decide the most recent slot to query based on a /// [commitment level][cl], which determines how committed or finalized a slot /// must be to be considered for the query. Unless specified otherwise, the /// commitment level is [`Finalized`], meaning the slot is definitely /// permanently committed. The default commitment level can be configured by /// creating `RpcClient` with an explicit [`CommitmentConfig`], and that default /// configured commitment level can be overridden by calling the various /// `_with_commitment` methods, like /// [`RpcClient::confirm_transaction_with_commitment`]. In some cases the /// configured commitment level is ignored and `Finalized` is used instead, as /// in [`RpcClient::get_blocks`], where it would be invalid to use the /// [`Processed`] commitment level. These exceptions are noted in the method /// documentation. /// /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// [`Processed`]: solana_sdk::commitment_config::CommitmentLevel::Processed /// [jsonprot]: https://solana.com/docs/rpc /// [JSON-RPC]: https://www.jsonrpc.org/specification /// [slots]: https://solana.com/docs/terminology#slot /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # Errors /// /// Methods on `RpcClient` return /// [`client_error::Result`][solana_rpc_client_api::client_error::Result], and many of them /// return the [`RpcResult`][solana_rpc_client_api::response::RpcResult] typedef, which /// contains [`Response`][solana_rpc_client_api::response::Response] on `Ok`. Both /// `client_error::Result` and [`RpcResult`] contain `ClientError` on error. In /// the case of `RpcResult`, the actual return value is in the /// [`value`][solana_rpc_client_api::response::Response::value] field, with RPC contextual /// information in the [`context`][solana_rpc_client_api::response::Response::context] /// field, so it is common for the value to be accessed with `?.value`, as in /// /// ``` /// # use solana_sdk::system_transaction; /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::signature::{Keypair, Signer}; /// # use solana_sdk::hash::Hash; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let key = Keypair::new(); /// # let to = solana_sdk::pubkey::new_rand(); /// # let lamports = 50; /// # let latest_blockhash = Hash::default(); /// # let tx = system_transaction::transfer(&key, &to, lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// let statuses = rpc_client.get_signature_statuses(&[signature])?.value; /// # Ok::<(), Error>(()) /// ``` /// /// Requests may timeout, in which case they return a [`ClientError`] where the /// [`ClientErrorKind`] is [`ClientErrorKind::Reqwest`], and where the interior /// [`reqwest::Error`](solana_rpc_client_api::client_error::reqwest::Error)s /// [`is_timeout`](solana_rpc_client_api::client_error::reqwest::Error::is_timeout) method /// returns `true`. The default timeout is 30 seconds, and may be changed by /// calling an appropriate constructor with a `timeout` parameter. /// /// [`ClientError`]: solana_rpc_client_api::client_error::Error /// [`ClientErrorKind`]: solana_rpc_client_api::client_error::ErrorKind /// [`ClientErrorKind::Reqwest`]: solana_rpc_client_api::client_error::ErrorKind::Reqwest pub struct RpcClient { rpc_client: Arc, runtime: Option, } impl Drop for RpcClient { fn drop(&mut self) { self.runtime.take().expect("runtime").shutdown_background(); } } impl RpcClient { /// Create an `RpcClient` from an [`RpcSender`] and an [`RpcClientConfig`]. /// /// This is the basic constructor, allowing construction with any type of /// `RpcSender`. Most applications should use one of the other constructors, /// such as [`RpcClient::new`], [`RpcClient::new_with_commitment`] or /// [`RpcClient::new_with_timeout`]. pub fn new_sender( sender: T, config: RpcClientConfig, ) -> Self { Self { rpc_client: Arc::new(nonblocking::rpc_client::RpcClient::new_sender( sender, config, )), runtime: Some( tokio::runtime::Builder::new_current_thread() .thread_name("solRpcClient") .enable_io() .enable_time() .build() .unwrap(), ), } } /// Create an HTTP `RpcClient`. /// /// The URL is an HTTP URL, usually for port 8899, as in /// "http://localhost:8899". /// /// The client has a default timeout of 30 seconds, and a default [commitment /// level][cl] of [`Finalized`]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// /// ``` /// # use solana_rpc_client::rpc_client::RpcClient; /// let url = "http://localhost:8899".to_string(); /// let client = RpcClient::new(url); /// ``` pub fn new(url: U) -> Self { Self::new_with_commitment(url, CommitmentConfig::default()) } /// Create an HTTP `RpcClient` with specified [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// The URL is an HTTP URL, usually for port 8899, as in /// "http://localhost:8899". /// /// The client has a default timeout of 30 seconds, and a user-specified /// [`CommitmentLevel`] via [`CommitmentConfig`]. /// /// [`CommitmentLevel`]: solana_sdk::commitment_config::CommitmentLevel /// /// # Examples /// /// ``` /// # use solana_sdk::commitment_config::CommitmentConfig; /// # use solana_rpc_client::rpc_client::RpcClient; /// let url = "http://localhost:8899".to_string(); /// let commitment_config = CommitmentConfig::processed(); /// let client = RpcClient::new_with_commitment(url, commitment_config); /// ``` pub fn new_with_commitment(url: U, commitment_config: CommitmentConfig) -> Self { Self::new_sender( HttpSender::new(url), RpcClientConfig::with_commitment(commitment_config), ) } /// Create an HTTP `RpcClient` with specified timeout. /// /// The URL is an HTTP URL, usually for port 8899, as in /// "http://localhost:8899". /// /// The client has and a default [commitment level][cl] of /// [`Finalized`]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// /// ``` /// # use std::time::Duration; /// # use solana_rpc_client::rpc_client::RpcClient; /// let url = "http://localhost::8899".to_string(); /// let timeout = Duration::from_secs(1); /// let client = RpcClient::new_with_timeout(url, timeout); /// ``` pub fn new_with_timeout(url: U, timeout: Duration) -> Self { Self::new_sender( HttpSender::new_with_timeout(url, timeout), RpcClientConfig::with_commitment(CommitmentConfig::default()), ) } /// Create an HTTP `RpcClient` with specified timeout and [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// The URL is an HTTP URL, usually for port 8899, as in /// "http://localhost:8899". /// /// # Examples /// /// ``` /// # use std::time::Duration; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// let url = "http://localhost::8899".to_string(); /// let timeout = Duration::from_secs(1); /// let commitment_config = CommitmentConfig::processed(); /// let client = RpcClient::new_with_timeout_and_commitment( /// url, /// timeout, /// commitment_config, /// ); /// ``` pub fn new_with_timeout_and_commitment( url: U, timeout: Duration, commitment_config: CommitmentConfig, ) -> Self { Self::new_sender( HttpSender::new_with_timeout(url, timeout), RpcClientConfig::with_commitment(commitment_config), ) } /// Create an HTTP `RpcClient` with specified timeout and [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// The URL is an HTTP URL, usually for port 8899, as in /// "http://localhost:8899". /// /// The `confirm_transaction_initial_timeout` argument specifies the amount of /// time to allow for the server to initially process a transaction, when /// confirming a transaction via one of the `_with_spinner` methods, like /// [`RpcClient::send_and_confirm_transaction_with_spinner`]. In /// other words, setting `confirm_transaction_initial_timeout` to > 0 allows /// `RpcClient` to wait for confirmation of a transaction that the server /// has not "seen" yet. /// /// # Examples /// /// ``` /// # use std::time::Duration; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// let url = "http://localhost::8899".to_string(); /// let timeout = Duration::from_secs(1); /// let commitment_config = CommitmentConfig::processed(); /// let confirm_transaction_initial_timeout = Duration::from_secs(10); /// let client = RpcClient::new_with_timeouts_and_commitment( /// url, /// timeout, /// commitment_config, /// confirm_transaction_initial_timeout, /// ); /// ``` pub fn new_with_timeouts_and_commitment( url: U, timeout: Duration, commitment_config: CommitmentConfig, confirm_transaction_initial_timeout: Duration, ) -> Self { Self::new_sender( HttpSender::new_with_timeout(url, timeout), RpcClientConfig { commitment_config, confirm_transaction_initial_timeout: Some(confirm_transaction_initial_timeout), }, ) } /// Create a mock `RpcClient`. /// /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does /// not use the network, and instead returns synthetic responses, for use in /// tests. /// /// It is primarily for internal use, with limited customizability, and /// behaviors determined by internal Solana test cases. New users should /// consider implementing `RpcSender` themselves and constructing /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior. /// /// Unless directed otherwise, a mock `RpcClient` will generally return a /// reasonable default response to any request, at least for [`RpcRequest`] /// values for which responses have been implemented. /// /// This mock can be customized by changing the `url` argument, which is not /// actually a URL, but a simple string directive that changes the mock /// behavior in specific scenarios: /// /// - It is customary to set the `url` to "succeeds" for mocks that should /// return successfully, though this value is not actually interpreted. /// /// - If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`. /// /// - Other possible values of `url` are specific to different `RpcRequest` /// values. Read the implementation of (non-public) `MockSender` for /// details. /// /// The [`RpcClient::new_mock_with_mocks`] function offers further /// customization options. /// /// # Examples /// /// ``` /// # use solana_rpc_client::rpc_client::RpcClient; /// // Create an `RpcClient` that always succeeds /// let url = "succeeds".to_string(); /// let successful_client = RpcClient::new_mock(url); /// ``` /// /// ``` /// # use solana_rpc_client::rpc_client::RpcClient; /// // Create an `RpcClient` that always fails /// let url = "fails".to_string(); /// let successful_client = RpcClient::new_mock(url); /// ``` pub fn new_mock(url: U) -> Self { Self::new_sender( MockSender::new(url), RpcClientConfig::with_commitment(CommitmentConfig::default()), ) } /// Create a mock `RpcClient`. /// /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does /// not use the network, and instead returns synthetic responses, for use in /// tests. /// /// It is primarily for internal use, with limited customizability, and /// behaviors determined by internal Solana test cases. New users should /// consider implementing `RpcSender` themselves and constructing /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior. /// /// Unless directed otherwise, a mock `RpcClient` will generally return a /// reasonable default response to any request, at least for [`RpcRequest`] /// values for which responses have been implemented. /// /// This mock can be customized in two ways: /// /// 1) By changing the `url` argument, which is not actually a URL, but a /// simple string directive that changes the mock behavior in specific /// scenarios. /// /// It is customary to set the `url` to "succeeds" for mocks that should /// return successfully, though this value is not actually interpreted. /// /// If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`. /// /// Other possible values of `url` are specific to different `RpcRequest` /// values. Read the implementation of `MockSender` (which is non-public) /// for details. /// /// 2) Custom responses can be configured by providing [`Mocks`]. This type /// is a [`HashMap`] from [`RpcRequest`] to a JSON [`Value`] response, /// Any entries in this map override the default behavior for the given /// request. /// /// The [`RpcClient::new_mock_with_mocks`] function offers further /// customization options. /// /// [`HashMap`]: std::collections::HashMap /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # request::RpcRequest, /// # response::{Response, RpcResponseContext}, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use std::collections::HashMap; /// # use serde_json::json; /// // Create a mock with a custom response to the `GetBalance` request /// let account_balance = 50; /// let account_balance_response = json!(Response { /// context: RpcResponseContext { slot: 1, api_version: None }, /// value: json!(account_balance), /// }); /// /// let mut mocks = HashMap::new(); /// mocks.insert(RpcRequest::GetBalance, account_balance_response); /// let url = "succeeds".to_string(); /// let client = RpcClient::new_mock_with_mocks(url, mocks); /// ``` pub fn new_mock_with_mocks(url: U, mocks: Mocks) -> Self { Self::new_sender( MockSender::new_with_mocks(url, mocks), RpcClientConfig::with_commitment(CommitmentConfig::default()), ) } /// Create an HTTP `RpcClient` from a [`SocketAddr`]. /// /// The client has a default timeout of 30 seconds, and a default [commitment /// level][cl] of [`Finalized`]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// /// ``` /// # use std::net::{Ipv4Addr, SocketAddr}; /// # use solana_rpc_client::rpc_client::RpcClient; /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 8899)); /// let client = RpcClient::new_socket(addr); /// ``` pub fn new_socket(addr: SocketAddr) -> Self { Self::new(get_rpc_request_str(addr, false)) } /// Create an HTTP `RpcClient` from a [`SocketAddr`] with specified [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// The client has a default timeout of 30 seconds, and a user-specified /// [`CommitmentLevel`] via [`CommitmentConfig`]. /// /// [`CommitmentLevel`]: solana_sdk::commitment_config::CommitmentLevel /// /// # Examples /// /// ``` /// # use std::net::{Ipv4Addr, SocketAddr}; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 8899)); /// let commitment_config = CommitmentConfig::processed(); /// let client = RpcClient::new_socket_with_commitment( /// addr, /// commitment_config /// ); /// ``` pub fn new_socket_with_commitment( addr: SocketAddr, commitment_config: CommitmentConfig, ) -> Self { Self::new_with_commitment(get_rpc_request_str(addr, false), commitment_config) } /// Create an HTTP `RpcClient` from a [`SocketAddr`] with specified timeout. /// /// The client has a default [commitment level][cl] of [`Finalized`]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// # Examples /// /// ``` /// # use std::net::{Ipv4Addr, SocketAddr}; /// # use std::time::Duration; /// # use solana_rpc_client::rpc_client::RpcClient; /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 8899)); /// let timeout = Duration::from_secs(1); /// let client = RpcClient::new_socket_with_timeout(addr, timeout); /// ``` pub fn new_socket_with_timeout(addr: SocketAddr, timeout: Duration) -> Self { let url = get_rpc_request_str(addr, false); Self::new_with_timeout(url, timeout) } /// Get the configured url of the client's sender pub fn url(&self) -> String { (self.rpc_client.as_ref()).url() } /// Get the configured default [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// The commitment config may be specified during construction, and /// determines how thoroughly committed a transaction must be when waiting /// for its confirmation or otherwise checking for confirmation. If not /// specified, the default commitment level is /// [`Finalized`]. /// /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// /// The default commitment level is overridden when calling methods that /// explicitly provide a [`CommitmentConfig`], like /// [`RpcClient::confirm_transaction_with_commitment`]. pub fn commitment(&self) -> CommitmentConfig { (self.rpc_client.as_ref()).commitment() } /// Submit a transaction and wait for confirmation. /// /// Once this function returns successfully, the given transaction is /// guaranteed to be processed with the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// After sending the transaction, this method polls in a loop for the /// status of the transaction until it has ben confirmed. /// /// # Errors /// /// If the transaction is not signed then an error with kind [`RpcError`] is /// returned, containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]. /// /// If the preflight transaction simulation fails then an error with kind /// [`RpcError`] is returned, containing an [`RpcResponseError`] with `code` /// set to [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]. /// /// If the receiving node is unhealthy, e.g. it is not fully synced to /// the cluster, then an error with kind [`RpcError`] is returned, /// containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. /// /// [`RpcError`]: solana_rpc_client_api::request::RpcError /// [`RpcResponseError`]: solana_rpc_client_api::request::RpcError::RpcResponseError /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY /// /// # RPC Reference /// /// This method is built on the [`sendTransaction`] RPC method, and the /// [`getLatestBlockhash`] RPC method. /// /// [`sendTransaction`]: https://solana.com/docs/rpc/http/sendtransaction /// [`getLatestBlockhash`]: https://solana.com/docs/rpc/http/getlatestblockhash /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_and_confirm_transaction(&tx)?; /// # Ok::<(), Error>(()) /// ``` pub fn send_and_confirm_transaction( &self, transaction: &impl SerializableTransaction, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).send_and_confirm_transaction(transaction)) } #[cfg(feature = "spinner")] pub fn send_and_confirm_transaction_with_spinner( &self, transaction: &impl SerializableTransaction, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()).send_and_confirm_transaction_with_spinner(transaction), ) } #[cfg(feature = "spinner")] pub fn send_and_confirm_transaction_with_spinner_and_commitment( &self, transaction: &impl SerializableTransaction, commitment: CommitmentConfig, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()) .send_and_confirm_transaction_with_spinner_and_commitment(transaction, commitment), ) } #[cfg(feature = "spinner")] pub fn send_and_confirm_transaction_with_spinner_and_config( &self, transaction: &impl SerializableTransaction, commitment: CommitmentConfig, config: RpcSendTransactionConfig, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()).send_and_confirm_transaction_with_spinner_and_config( transaction, commitment, config, ), ) } /// Submits a signed transaction to the network. /// /// Before a transaction is processed, the receiving node runs a "preflight /// check" which verifies signatures, checks that the node is healthy, /// and simulates the transaction. If the preflight check fails then an /// error is returned immediately. Preflight checks can be disabled by /// calling [`send_transaction_with_config`] and setting the /// [`skip_preflight`] field of [`RpcSendTransactionConfig`] to `true`. /// /// This method does not wait for the transaction to be processed or /// confirmed before returning successfully. To wait for the transaction to /// be processed or confirmed, use the [`send_and_confirm_transaction`] /// method. /// /// [`send_transaction_with_config`]: RpcClient::send_transaction_with_config /// [`skip_preflight`]: solana_rpc_client_api::config::RpcSendTransactionConfig::skip_preflight /// [`RpcSendTransactionConfig`]: solana_rpc_client_api::config::RpcSendTransactionConfig /// [`send_and_confirm_transaction`]: RpcClient::send_and_confirm_transaction /// /// # Errors /// /// If the transaction is not signed then an error with kind [`RpcError`] is /// returned, containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]. /// /// If the preflight transaction simulation fails then an error with kind /// [`RpcError`] is returned, containing an [`RpcResponseError`] with `code` /// set to [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]. /// /// If the receiving node is unhealthy, e.g. it is not fully synced to /// the cluster, then an error with kind [`RpcError`] is returned, /// containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. /// /// [`RpcError`]: solana_rpc_client_api::request::RpcError /// [`RpcResponseError`]: solana_rpc_client_api::request::RpcError::RpcResponseError /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY /// /// # RPC Reference /// /// This method is built on the [`sendTransaction`] RPC method. /// /// [`sendTransaction`]: https://solana.com/docs/rpc/http/sendtransaction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # hash::Hash, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Transfer lamports from Alice to Bob /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// # Ok::<(), Error>(()) /// ``` pub fn send_transaction( &self, transaction: &impl SerializableTransaction, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).send_transaction(transaction)) } /// Submits a signed transaction to the network. /// /// Before a transaction is processed, the receiving node runs a "preflight /// check" which verifies signatures, checks that the node is healthy, and /// simulates the transaction. If the preflight check fails then an error is /// returned immediately. Preflight checks can be disabled by setting the /// [`skip_preflight`] field of [`RpcSendTransactionConfig`] to `true`. /// /// This method does not wait for the transaction to be processed or /// confirmed before returning successfully. To wait for the transaction to /// be processed or confirmed, use the [`send_and_confirm_transaction`] /// method. /// /// [`send_transaction_with_config`]: RpcClient::send_transaction_with_config /// [`skip_preflight`]: solana_rpc_client_api::config::RpcSendTransactionConfig::skip_preflight /// [`RpcSendTransactionConfig`]: solana_rpc_client_api::config::RpcSendTransactionConfig /// [`send_and_confirm_transaction`]: RpcClient::send_and_confirm_transaction /// /// # Errors /// /// If preflight checks are enabled, if the transaction is not signed /// then an error with kind [`RpcError`] is returned, containing an /// [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]. /// /// If preflight checks are enabled, if the preflight transaction simulation /// fails then an error with kind [`RpcError`] is returned, containing an /// [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]. /// /// If the receiving node is unhealthy, e.g. it is not fully synced to /// the cluster, then an error with kind [`RpcError`] is returned, /// containing an [`RpcResponseError`] with `code` set to /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. /// /// [`RpcError`]: solana_rpc_client_api::request::RpcError /// [`RpcResponseError`]: solana_rpc_client_api::request::RpcError::RpcResponseError /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY /// /// # RPC Reference /// /// This method is built on the [`sendTransaction`] RPC method. /// /// [`sendTransaction`]: https://solana.com/docs/rpc/http/sendtransaction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::RpcSendTransactionConfig, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # hash::Hash, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Transfer lamports from Alice to Bob /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let config = RpcSendTransactionConfig { /// skip_preflight: true, /// .. RpcSendTransactionConfig::default() /// }; /// let signature = rpc_client.send_transaction_with_config( /// &tx, /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn send_transaction_with_config( &self, transaction: &impl SerializableTransaction, config: RpcSendTransactionConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).send_transaction_with_config(transaction, config)) } pub fn send(&self, request: RpcRequest, params: Value) -> ClientResult where T: serde::de::DeserializeOwned, { self.invoke((self.rpc_client.as_ref()).send(request, params)) } /// Check the confirmation status of a transaction. /// /// Returns `true` if the given transaction succeeded and has been committed /// with the configured [commitment level][cl], which can be retrieved with /// the [`commitment`](RpcClient::commitment) method. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// Note that this method does not wait for a transaction to be confirmed /// — it only checks whether a transaction has been confirmed. To /// submit a transaction and wait for it to confirm, use /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction]. /// /// _This method returns `false` if the transaction failed, even if it has /// been confirmed._ /// /// # RPC Reference /// /// This method is built on the [`getSignatureStatuses`] RPC method. /// /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Transfer lamports from Alice to Bob and wait for confirmation /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// /// loop { /// let confirmed = rpc_client.confirm_transaction(&signature)?; /// if confirmed { /// break; /// } /// } /// # Ok::<(), Error>(()) /// ``` pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult { self.invoke((self.rpc_client.as_ref()).confirm_transaction(signature)) } /// Check the confirmation status of a transaction. /// /// Returns an [`RpcResult`] with value `true` if the given transaction /// succeeded and has been committed with the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// Note that this method does not wait for a transaction to be confirmed /// — it only checks whether a transaction has been confirmed. To /// submit a transaction and wait for it to confirm, use /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction]. /// /// _This method returns an [`RpcResult`] with value `false` if the /// transaction failed, even if it has been confirmed._ /// /// # RPC Reference /// /// This method is built on the [`getSignatureStatuses`] RPC method. /// /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # commitment_config::CommitmentConfig, /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # system_transaction, /// # }; /// # use std::time::Duration; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Transfer lamports from Alice to Bob and wait for confirmation /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// /// loop { /// let commitment_config = CommitmentConfig::processed(); /// let confirmed = rpc_client.confirm_transaction_with_commitment(&signature, commitment_config)?; /// if confirmed.value { /// break; /// } /// } /// # Ok::<(), Error>(()) /// ``` pub fn confirm_transaction_with_commitment( &self, signature: &Signature, commitment_config: CommitmentConfig, ) -> RpcResult { self.invoke( (self.rpc_client.as_ref()) .confirm_transaction_with_commitment(signature, commitment_config), ) } #[cfg(feature = "spinner")] pub fn confirm_transaction_with_spinner( &self, signature: &Signature, recent_blockhash: &Hash, commitment_config: CommitmentConfig, ) -> ClientResult<()> { self.invoke((self.rpc_client.as_ref()).confirm_transaction_with_spinner( signature, recent_blockhash, commitment_config, )) } /// Simulates sending a transaction. /// /// If the transaction fails, then the [`err`] field of the returned /// [`RpcSimulateTransactionResult`] will be `Some`. Any logs emitted from /// the transaction are returned in the [`logs`] field. /// /// [`err`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::err /// [`logs`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::logs /// /// Simulating a transaction is similar to the ["preflight check"] that is /// run by default when sending a transaction. /// /// ["preflight check"]: https://solana.com/docs/rpc/http/sendtransaction /// /// By default, signatures are not verified during simulation. To verify /// signatures, call the [`simulate_transaction_with_config`] method, with /// the [`sig_verify`] field of [`RpcSimulateTransactionConfig`] set to /// `true`. /// /// [`simulate_transaction_with_config`]: RpcClient::simulate_transaction_with_config /// [`sig_verify`]: solana_rpc_client_api::config::RpcSimulateTransactionConfig::sig_verify /// /// # RPC Reference /// /// This method is built on the [`simulateTransaction`] RPC method. /// /// [`simulateTransaction`]: https://solana.com/docs/rpc/http/simulatetransaction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # response::RpcSimulateTransactionResult, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # hash::Hash, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Transfer lamports from Alice to Bob /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let result = rpc_client.simulate_transaction(&tx)?; /// assert!(result.value.err.is_none()); /// # Ok::<(), Error>(()) /// ``` pub fn simulate_transaction( &self, transaction: &impl SerializableTransaction, ) -> RpcResult { self.invoke((self.rpc_client.as_ref()).simulate_transaction(transaction)) } /// Simulates sending a transaction. /// /// If the transaction fails, then the [`err`] field of the returned /// [`RpcSimulateTransactionResult`] will be `Some`. Any logs emitted from /// the transaction are returned in the [`logs`] field. /// /// [`err`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::err /// [`logs`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::logs /// /// Simulating a transaction is similar to the ["preflight check"] that is /// run by default when sending a transaction. /// /// ["preflight check"]: https://solana.com/docs/rpc/http/sendtransaction /// /// By default, signatures are not verified during simulation. To verify /// signatures, call the [`simulate_transaction_with_config`] method, with /// the [`sig_verify`] field of [`RpcSimulateTransactionConfig`] set to /// `true`. /// /// [`simulate_transaction_with_config`]: RpcClient::simulate_transaction_with_config /// [`sig_verify`]: solana_rpc_client_api::config::RpcSimulateTransactionConfig::sig_verify /// /// This method can additionally query information about accounts by /// including them in the [`accounts`] field of the /// [`RpcSimulateTransactionConfig`] argument, in which case those results /// are reported in the [`accounts`][accounts2] field of the returned /// [`RpcSimulateTransactionResult`]. /// /// [`accounts`]: solana_rpc_client_api::config::RpcSimulateTransactionConfig::accounts /// [accounts2]: solana_rpc_client_api::response::RpcSimulateTransactionResult::accounts /// /// # RPC Reference /// /// This method is built on the [`simulateTransaction`] RPC method. /// /// [`simulateTransaction`]: https://solana.com/docs/rpc/http/simulatetransaction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::RpcSimulateTransactionConfig, /// # response::RpcSimulateTransactionResult, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # hash::Hash, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Transfer lamports from Alice to Bob /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let config = RpcSimulateTransactionConfig { /// sig_verify: true, /// .. RpcSimulateTransactionConfig::default() /// }; /// let result = rpc_client.simulate_transaction_with_config( /// &tx, /// config, /// )?; /// assert!(result.value.err.is_none()); /// # Ok::<(), Error>(()) /// ``` pub fn simulate_transaction_with_config( &self, transaction: &impl SerializableTransaction, config: RpcSimulateTransactionConfig, ) -> RpcResult { self.invoke( (self.rpc_client.as_ref()).simulate_transaction_with_config(transaction, config), ) } /// Returns the highest slot information that the node has snapshots for. /// /// This will find the highest full snapshot slot, and the highest incremental snapshot slot /// _based on_ the full snapshot slot, if there is one. /// /// # RPC Reference /// /// This method corresponds directly to the [`getHighestSnapshotSlot`] RPC method. /// /// [`getHighestSnapshotSlot`]: https://solana.com/docs/rpc/http/gethighestsnapshotslot /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let snapshot_slot_info = rpc_client.get_highest_snapshot_slot()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_highest_snapshot_slot(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_highest_snapshot_slot()) } #[deprecated( since = "1.8.0", note = "Please use RpcClient::get_highest_snapshot_slot() instead" )] #[allow(deprecated)] pub fn get_snapshot_slot(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_snapshot_slot()) } /// Check if a transaction has been processed with the default [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// If the transaction has been processed with the default commitment level, /// then this method returns `Ok` of `Some`. If the transaction has not yet /// been processed with the default commitment level, it returns `Ok` of /// `None`. /// /// If the transaction has been processed with the default commitment level, /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`. /// If the transaction has been processed with the default commitment level, /// and the transaction failed, this method returns `Ok(Some(Err(_)))`, /// where the interior error is type [`TransactionError`]. /// /// [`TransactionError`]: solana_sdk::transaction::TransactionError /// /// This function only searches a node's recent history, including all /// recent slots, plus up to /// [`MAX_RECENT_BLOCKHASHES`][solana_sdk::clock::MAX_RECENT_BLOCKHASHES] /// rooted slots. To search the full transaction history use the /// [`get_signature_status_with_commitment_and_history`][RpcClient::get_signature_status_with_commitment_and_history] /// method. /// /// # RPC Reference /// /// This method is built on the [`getSignatureStatuses`] RPC method. /// /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # hash::Hash, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// let status = rpc_client.get_signature_status(&signature)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_signature_status( &self, signature: &Signature, ) -> ClientResult>> { self.invoke((self.rpc_client.as_ref()).get_signature_status(signature)) } /// Gets the statuses of a list of transaction signatures. /// /// The returned vector of [`TransactionStatus`] has the same length as the /// input slice. /// /// For any transaction that has not been processed by the network, the /// value of the corresponding entry in the returned vector is `None`. As a /// result, a transaction that has recently been submitted will not have a /// status immediately. /// /// To submit a transaction and wait for it to confirm, use /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction]. /// /// This function ignores the configured confirmation level, and returns the /// transaction status whatever it is. It does not wait for transactions to /// be processed. /// /// This function only searches a node's recent history, including all /// recent slots, plus up to /// [`MAX_RECENT_BLOCKHASHES`][solana_sdk::clock::MAX_RECENT_BLOCKHASHES] /// rooted slots. To search the full transaction history use the /// [`get_signature_statuses_with_history`][RpcClient::get_signature_statuses_with_history] /// method. /// /// # Errors /// /// Any individual `TransactionStatus` may have triggered an error during /// processing, in which case its [`err`][`TransactionStatus::err`] field /// will be `Some`. /// /// # RPC Reference /// /// This method corresponds directly to the [`getSignatureStatuses`] RPC method. /// /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # hash::Hash, /// # system_transaction, /// # }; /// # use std::time::Duration; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// // Send lamports from Alice to Bob and wait for the transaction to be processed /// # let bob = Keypair::new(); /// # let lamports = 50; /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// /// let status = loop { /// let statuses = rpc_client.get_signature_statuses(&[signature])?.value; /// if let Some(status) = statuses[0].clone() { /// break status; /// } /// std::thread::sleep(Duration::from_millis(100)); /// }; /// /// assert!(status.err.is_none()); /// # Ok::<(), Error>(()) /// ``` pub fn get_signature_statuses( &self, signatures: &[Signature], ) -> RpcResult>> { self.invoke((self.rpc_client.as_ref()).get_signature_statuses(signatures)) } /// Gets the statuses of a list of transaction signatures. /// /// The returned vector of [`TransactionStatus`] has the same length as the /// input slice. /// /// For any transaction that has not been processed by the network, the /// value of the corresponding entry in the returned vector is `None`. As a /// result, a transaction that has recently been submitted will not have a /// status immediately. /// /// To submit a transaction and wait for it to confirm, use /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction]. /// /// This function ignores the configured confirmation level, and returns the /// transaction status whatever it is. It does not wait for transactions to /// be processed. /// /// This function searches a node's full ledger history and (if implemented) long-term storage. To search for /// transactions in recent slots only use the /// [`get_signature_statuses`][RpcClient::get_signature_statuses] method. /// /// # Errors /// /// Any individual `TransactionStatus` may have triggered an error during /// processing, in which case its [`err`][`TransactionStatus::err`] field /// will be `Some`. /// /// # RPC Reference /// /// This method corresponds directly to the [`getSignatureStatuses`] RPC /// method, with the `searchTransactionHistory` configuration option set to /// `true`. /// /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # hash::Hash, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # fn get_old_transaction_signature() -> Signature { Signature::default() } /// // Check if an old transaction exists /// let signature = get_old_transaction_signature(); /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let statuses = rpc_client.get_signature_statuses_with_history(&[signature])?.value; /// if statuses[0].is_none() { /// println!("old transaction does not exist"); /// } /// # Ok::<(), Error>(()) /// ``` pub fn get_signature_statuses_with_history( &self, signatures: &[Signature], ) -> RpcResult>> { self.invoke((self.rpc_client.as_ref()).get_signature_statuses_with_history(signatures)) } /// Check if a transaction has been processed with the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// If the transaction has been processed with the given commitment level, /// then this method returns `Ok` of `Some`. If the transaction has not yet /// been processed with the given commitment level, it returns `Ok` of /// `None`. /// /// If the transaction has been processed with the given commitment level, /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`. /// If the transaction has been processed with the given commitment level, /// and the transaction failed, this method returns `Ok(Some(Err(_)))`, /// where the interior error is type [`TransactionError`]. /// /// [`TransactionError`]: solana_sdk::transaction::TransactionError /// /// This function only searches a node's recent history, including all /// recent slots, plus up to /// [`MAX_RECENT_BLOCKHASHES`][solana_sdk::clock::MAX_RECENT_BLOCKHASHES] /// rooted slots. To search the full transaction history use the /// [`get_signature_status_with_commitment_and_history`][RpcClient::get_signature_status_with_commitment_and_history] /// method. /// /// # RPC Reference /// /// This method is built on the [`getSignatureStatuses`] RPC method. /// /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # commitment_config::CommitmentConfig, /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_and_confirm_transaction(&tx)?; /// let commitment_config = CommitmentConfig::processed(); /// let status = rpc_client.get_signature_status_with_commitment( /// &signature, /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_signature_status_with_commitment( &self, signature: &Signature, commitment_config: CommitmentConfig, ) -> ClientResult>> { self.invoke( (self.rpc_client.as_ref()) .get_signature_status_with_commitment(signature, commitment_config), ) } /// Check if a transaction has been processed with the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// If the transaction has been processed with the given commitment level, /// then this method returns `Ok` of `Some`. If the transaction has not yet /// been processed with the given commitment level, it returns `Ok` of /// `None`. /// /// If the transaction has been processed with the given commitment level, /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`. /// If the transaction has been processed with the given commitment level, /// and the transaction failed, this method returns `Ok(Some(Err(_)))`, /// where the interior error is type [`TransactionError`]. /// /// [`TransactionError`]: solana_sdk::transaction::TransactionError /// /// This method optionally searches a node's full ledger history and (if /// implemented) long-term storage. /// /// # RPC Reference /// /// This method is built on the [`getSignatureStatuses`] RPC method. /// /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # commitment_config::CommitmentConfig, /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// let commitment_config = CommitmentConfig::processed(); /// let search_transaction_history = true; /// let status = rpc_client.get_signature_status_with_commitment_and_history( /// &signature, /// commitment_config, /// search_transaction_history, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_signature_status_with_commitment_and_history( &self, signature: &Signature, commitment_config: CommitmentConfig, search_transaction_history: bool, ) -> ClientResult>> { self.invoke( (self.rpc_client.as_ref()).get_signature_status_with_commitment_and_history( signature, commitment_config, search_transaction_history, ), ) } /// Returns the slot that has reached the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getSlot`] RPC method. /// /// [`getSlot`]: https://solana.com/docs/rpc/http/getslot /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let slot = rpc_client.get_slot()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_slot(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_slot()) } /// Returns the slot that has reached the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getSlot`] RPC method. /// /// [`getSlot`]: https://solana.com/docs/rpc/http/getslot /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let commitment_config = CommitmentConfig::processed(); /// let slot = rpc_client.get_slot_with_commitment(commitment_config)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_slot_with_commitment( &self, commitment_config: CommitmentConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_slot_with_commitment(commitment_config)) } /// Returns the block height that has reached the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method is corresponds directly to the [`getBlockHeight`] RPC method. /// /// [`getBlockHeight`]: https://solana.com/docs/rpc/http/getblockheight /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let block_height = rpc_client.get_block_height()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block_height(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_block_height()) } /// Returns the block height that has reached the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method is corresponds directly to the [`getBlockHeight`] RPC method. /// /// [`getBlockHeight`]: https://solana.com/docs/rpc/http/getblockheight /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let commitment_config = CommitmentConfig::processed(); /// let block_height = rpc_client.get_block_height_with_commitment( /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block_height_with_commitment( &self, commitment_config: CommitmentConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_block_height_with_commitment(commitment_config)) } /// Returns the slot leaders for a given slot range. /// /// # RPC Reference /// /// This method corresponds directly to the [`getSlotLeaders`] RPC method. /// /// [`getSlotLeaders`]: https://solana.com/docs/rpc/http/getslotleaders /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::slot_history::Slot; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let start_slot = 1; /// let limit = 3; /// let leaders = rpc_client.get_slot_leaders(start_slot, limit)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_slot_leaders(&self, start_slot: Slot, limit: u64) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_slot_leaders(start_slot, limit)) } /// Get block production for the current epoch. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlockProduction`] RPC method. /// /// [`getBlockProduction`]: https://solana.com/docs/rpc/http/getblockproduction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let production = rpc_client.get_block_production()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block_production(&self) -> RpcResult { self.invoke((self.rpc_client.as_ref()).get_block_production()) } /// Get block production for the current or previous epoch. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlockProduction`] RPC method. /// /// [`getBlockProduction`]: https://solana.com/docs/rpc/http/getblockproduction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::{RpcBlockProductionConfig, RpcBlockProductionConfigRange}, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # commitment_config::CommitmentConfig, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let start_slot = 1; /// # let limit = 3; /// let leader = rpc_client.get_slot_leaders(start_slot, limit)?; /// let leader = leader[0]; /// let range = RpcBlockProductionConfigRange { /// first_slot: start_slot, /// last_slot: Some(start_slot + limit), /// }; /// let config = RpcBlockProductionConfig { /// identity: Some(leader.to_string()), /// range: Some(range), /// commitment: Some(CommitmentConfig::processed()), /// }; /// let production = rpc_client.get_block_production_with_config( /// config /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block_production_with_config( &self, config: RpcBlockProductionConfig, ) -> RpcResult { self.invoke((self.rpc_client.as_ref()).get_block_production_with_config(config)) } /// Returns epoch activation information for a stake account. /// /// This method uses the configured [commitment level]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getStakeActivation`] RPC method. /// /// [`getStakeActivation`]: https://solana.com/docs/rpc/http/getstakeactivation /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # response::StakeActivationState, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signer::keypair::Keypair, /// # signature::Signer, /// # pubkey::Pubkey, /// # stake, /// # stake::state::{Authorized, Lockup}, /// # transaction::Transaction /// # }; /// # use std::str::FromStr; /// # let alice = Keypair::new(); /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Find some vote account to delegate to /// let vote_accounts = rpc_client.get_vote_accounts()?; /// let vote_account = vote_accounts.current.get(0).unwrap_or_else(|| &vote_accounts.delinquent[0]); /// let vote_account_pubkey = &vote_account.vote_pubkey; /// let vote_account_pubkey = Pubkey::from_str(vote_account_pubkey).expect("pubkey"); /// /// // Create a stake account /// let stake_account = Keypair::new(); /// let stake_account_pubkey = stake_account.pubkey(); /// /// // Build the instructions to create new stake account, /// // funded by alice, and delegate to a validator's vote account. /// let instrs = stake::instruction::create_account_and_delegate_stake( /// &alice.pubkey(), /// &stake_account_pubkey, /// &vote_account_pubkey, /// &Authorized::auto(&stake_account_pubkey), /// &Lockup::default(), /// 1_000_000, /// ); /// /// let latest_blockhash = rpc_client.get_latest_blockhash()?; /// let tx = Transaction::new_signed_with_payer( /// &instrs, /// Some(&alice.pubkey()), /// &[&alice, &stake_account], /// latest_blockhash, /// ); /// /// rpc_client.send_and_confirm_transaction(&tx)?; /// /// let epoch_info = rpc_client.get_epoch_info()?; /// let activation = rpc_client.get_stake_activation( /// stake_account_pubkey, /// Some(epoch_info.epoch), /// )?; /// /// assert_eq!(activation.state, StakeActivationState::Activating); /// # Ok::<(), Error>(()) /// ``` pub fn get_stake_activation( &self, stake_account: Pubkey, epoch: Option, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_stake_activation(stake_account, epoch)) } /// Returns information about the current supply. /// /// This method uses the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getSupply`] RPC method. /// /// [`getSupply`]: https://solana.com/docs/rpc/http/getsupply /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let supply = rpc_client.supply()?; /// # Ok::<(), Error>(()) /// ``` pub fn supply(&self) -> RpcResult { self.invoke((self.rpc_client.as_ref()).supply()) } /// Returns information about the current supply. /// /// # RPC Reference /// /// This method corresponds directly to the [`getSupply`] RPC method. /// /// [`getSupply`]: https://solana.com/docs/rpc/http/getsupply /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let commitment_config = CommitmentConfig::processed(); /// let supply = rpc_client.supply_with_commitment( /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn supply_with_commitment( &self, commitment_config: CommitmentConfig, ) -> RpcResult { self.invoke((self.rpc_client.as_ref()).supply_with_commitment(commitment_config)) } /// Returns the 20 largest accounts, by lamport balance. /// /// # RPC Reference /// /// This method corresponds directly to the [`getLargestAccounts`] RPC /// method. /// /// [`getLargestAccounts`]: https://solana.com/docs/rpc/http/getlargestaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::{RpcLargestAccountsConfig, RpcLargestAccountsFilter}, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let commitment_config = CommitmentConfig::processed(); /// let config = RpcLargestAccountsConfig { /// commitment: Some(commitment_config), /// filter: Some(RpcLargestAccountsFilter::Circulating), /// }; /// let accounts = rpc_client.get_largest_accounts_with_config( /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_largest_accounts_with_config( &self, config: RpcLargestAccountsConfig, ) -> RpcResult> { self.invoke((self.rpc_client.as_ref()).get_largest_accounts_with_config(config)) } /// Returns the account info and associated stake for all the voting accounts /// that have reached the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getVoteAccounts`] /// RPC method. /// /// [`getVoteAccounts`]: https://solana.com/docs/rpc/http/getvoteaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let accounts = rpc_client.get_vote_accounts()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_vote_accounts(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_vote_accounts()) } /// Returns the account info and associated stake for all the voting accounts /// that have reached the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getVoteAccounts`] RPC method. /// /// [`getVoteAccounts`]: https://solana.com/docs/rpc/http/getvoteaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let commitment_config = CommitmentConfig::processed(); /// let accounts = rpc_client.get_vote_accounts_with_commitment( /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_vote_accounts_with_commitment( &self, commitment_config: CommitmentConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_vote_accounts_with_commitment(commitment_config)) } /// Returns the account info and associated stake for all the voting accounts /// that have reached the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getVoteAccounts`] RPC method. /// /// [`getVoteAccounts`]: https://solana.com/docs/rpc/http/getvoteaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::RpcGetVoteAccountsConfig, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signer::keypair::Keypair, /// # signature::Signer, /// # commitment_config::CommitmentConfig, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let vote_keypair = Keypair::new(); /// let vote_pubkey = vote_keypair.pubkey(); /// let commitment = CommitmentConfig::processed(); /// let config = RpcGetVoteAccountsConfig { /// vote_pubkey: Some(vote_pubkey.to_string()), /// commitment: Some(commitment), /// keep_unstaked_delinquents: Some(true), /// delinquent_slot_distance: Some(10), /// }; /// let accounts = rpc_client.get_vote_accounts_with_config( /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_vote_accounts_with_config( &self, config: RpcGetVoteAccountsConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_vote_accounts_with_config(config)) } pub fn wait_for_max_stake( &self, commitment: CommitmentConfig, max_stake_percent: f32, ) -> ClientResult<()> { self.invoke((self.rpc_client.as_ref()).wait_for_max_stake(commitment, max_stake_percent)) } /// Returns information about all the nodes participating in the cluster. /// /// # RPC Reference /// /// This method corresponds directly to the [`getClusterNodes`] /// RPC method. /// /// [`getClusterNodes`]: https://solana.com/docs/rpc/http/getclusternodes /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let cluster_nodes = rpc_client.get_cluster_nodes()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_cluster_nodes(&self) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_cluster_nodes()) } /// Returns identity and transaction information about a confirmed block in the ledger. /// /// The encodings are returned in [`UiTransactionEncoding::Json`][uite] /// format. To return transactions in other encodings, use /// [`get_block_with_encoding`]. /// /// [`get_block_with_encoding`]: RpcClient::get_block_with_encoding /// [uite]: UiTransactionEncoding::Json /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlock`] RPC /// method. /// /// [`getBlock`]: https://solana.com/docs/rpc/http/getblock /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let slot = rpc_client.get_slot()?; /// let block = rpc_client.get_block(slot)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block(&self, slot: Slot) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_block(slot)) } /// Returns identity and transaction information about a confirmed block in the ledger. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlock`] RPC method. /// /// [`getBlock`]: https://solana.com/docs/rpc/http/getblock /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_transaction_status::UiTransactionEncoding; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let slot = rpc_client.get_slot()?; /// let encoding = UiTransactionEncoding::Base58; /// let block = rpc_client.get_block_with_encoding( /// slot, /// encoding, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block_with_encoding( &self, slot: Slot, encoding: UiTransactionEncoding, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_block_with_encoding(slot, encoding)) } /// Returns identity and transaction information about a confirmed block in the ledger. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlock`] RPC method. /// /// [`getBlock`]: https://solana.com/docs/rpc/http/getblock /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # config::RpcBlockConfig, /// # client_error::Error, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_transaction_status::{ /// # TransactionDetails, /// # UiTransactionEncoding, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let slot = rpc_client.get_slot()?; /// let config = RpcBlockConfig { /// encoding: Some(UiTransactionEncoding::Base58), /// transaction_details: Some(TransactionDetails::None), /// rewards: Some(true), /// commitment: None, /// max_supported_transaction_version: Some(0), /// }; /// let block = rpc_client.get_block_with_config( /// slot, /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block_with_config( &self, slot: Slot, config: RpcBlockConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_block_with_config(slot, config)) } #[deprecated(since = "1.7.0", note = "Please use RpcClient::get_block() instead")] #[allow(deprecated)] pub fn get_confirmed_block(&self, slot: Slot) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_confirmed_block(slot)) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_block_with_encoding() instead" )] #[allow(deprecated)] pub fn get_confirmed_block_with_encoding( &self, slot: Slot, encoding: UiTransactionEncoding, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_confirmed_block_with_encoding(slot, encoding)) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_block_with_config() instead" )] #[allow(deprecated)] pub fn get_confirmed_block_with_config( &self, slot: Slot, config: RpcConfirmedBlockConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_confirmed_block_with_config(slot, config)) } /// Returns a list of finalized blocks between two slots. /// /// The range is inclusive, with results including the block for both /// `start_slot` and `end_slot`. /// /// If `end_slot` is not provided, then the end slot is for the latest /// finalized block. /// /// This method may not return blocks for the full range of slots if some /// slots do not have corresponding blocks. To simply get a specific number /// of sequential blocks, use the [`get_blocks_with_limit`] method. /// /// This method uses the [`Finalized`] [commitment level][cl]. /// /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// [`get_blocks_with_limit`]: RpcClient::get_blocks_with_limit. /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # Errors /// /// This method returns an error if the range is greater than 500,000 slots. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlocks`] RPC method, unless /// the remote node version is less than 1.7, in which case it maps to the /// [`getConfirmedBlocks`] RPC method. /// /// [`getBlocks`]: https://solana.com/docs/rpc/http/getblocks /// [`getConfirmedBlocks`]: https://solana.com/docs/rpc/deprecated/getconfirmedblocks /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Get up to the first 10 blocks /// let start_slot = 0; /// let end_slot = 9; /// let blocks = rpc_client.get_blocks(start_slot, Some(end_slot))?; /// # Ok::<(), Error>(()) /// ``` pub fn get_blocks(&self, start_slot: Slot, end_slot: Option) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_blocks(start_slot, end_slot)) } /// Returns a list of confirmed blocks between two slots. /// /// The range is inclusive, with results including the block for both /// `start_slot` and `end_slot`. /// /// If `end_slot` is not provided, then the end slot is for the latest /// block with the given [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// This method may not return blocks for the full range of slots if some /// slots do not have corresponding blocks. To simply get a specific number /// of sequential blocks, use the [`get_blocks_with_limit_and_commitment`] /// method. /// /// [`get_blocks_with_limit_and_commitment`]: RpcClient::get_blocks_with_limit_and_commitment. /// /// # Errors /// /// This method returns an error if the range is greater than 500,000 slots. /// /// This method returns an error if the given commitment level is below /// [`Confirmed`]. /// /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlocks`] RPC method, unless /// the remote node version is less than 1.7, in which case it maps to the /// [`getConfirmedBlocks`] RPC method. /// /// [`getBlocks`]: https://solana.com/docs/rpc/http/getblocks /// [`getConfirmedBlocks`]: https://solana.com/docs/rpc/deprecated/getconfirmedblocks /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Get up to the first 10 blocks /// let start_slot = 0; /// let end_slot = 9; /// // Method does not support commitment below `confirmed` /// let commitment_config = CommitmentConfig::confirmed(); /// let blocks = rpc_client.get_blocks_with_commitment( /// start_slot, /// Some(end_slot), /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_blocks_with_commitment( &self, start_slot: Slot, end_slot: Option, commitment_config: CommitmentConfig, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_blocks_with_commitment( start_slot, end_slot, commitment_config, )) } /// Returns a list of finalized blocks starting at the given slot. /// /// This method uses the [`Finalized`] [commitment level][cl]. /// /// [`Finalized`]: CommitmentLevel::Finalized. /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # Errors /// /// This method returns an error if the limit is greater than 500,000 slots. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlocksWithLimit`] RPC /// method, unless the remote node version is less than 1.7, in which case /// it maps to the [`getConfirmedBlocksWithLimit`] RPC method. /// /// [`getBlocksWithLimit`]: https://solana.com/docs/rpc/http/getblockswithlimit /// [`getConfirmedBlocksWithLimit`]: https://solana.com/docs/rpc/deprecated/getconfirmedblockswithlimit /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Get the first 10 blocks /// let start_slot = 0; /// let limit = 10; /// let blocks = rpc_client.get_blocks_with_limit(start_slot, limit)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_blocks_with_limit(&self, start_slot: Slot, limit: usize) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_blocks_with_limit(start_slot, limit)) } /// Returns a list of confirmed blocks starting at the given slot. /// /// # Errors /// /// This method returns an error if the limit is greater than 500,000 slots. /// /// This method returns an error if the given [commitment level][cl] is below /// [`Confirmed`]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlocksWithLimit`] RPC /// method, unless the remote node version is less than 1.7, in which case /// it maps to the `getConfirmedBlocksWithLimit` RPC method. /// /// [`getBlocksWithLimit`]: https://solana.com/docs/rpc/http/getblockswithlimit /// [`getConfirmedBlocksWithLimit`]: https://solana.com/docs/rpc/deprecated/getconfirmedblockswithlimit /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Get the first 10 blocks /// let start_slot = 0; /// let limit = 10; /// let commitment_config = CommitmentConfig::confirmed(); /// let blocks = rpc_client.get_blocks_with_limit_and_commitment( /// start_slot, /// limit, /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_blocks_with_limit_and_commitment( &self, start_slot: Slot, limit: usize, commitment_config: CommitmentConfig, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()).get_blocks_with_limit_and_commitment( start_slot, limit, commitment_config, ), ) } #[deprecated(since = "1.7.0", note = "Please use RpcClient::get_blocks() instead")] #[allow(deprecated)] pub fn get_confirmed_blocks( &self, start_slot: Slot, end_slot: Option, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_confirmed_blocks(start_slot, end_slot)) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_blocks_with_commitment() instead" )] #[allow(deprecated)] pub fn get_confirmed_blocks_with_commitment( &self, start_slot: Slot, end_slot: Option, commitment_config: CommitmentConfig, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()).get_confirmed_blocks_with_commitment( start_slot, end_slot, commitment_config, ), ) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_blocks_with_limit() instead" )] #[allow(deprecated)] pub fn get_confirmed_blocks_with_limit( &self, start_slot: Slot, limit: usize, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_confirmed_blocks_with_limit(start_slot, limit)) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_blocks_with_limit_and_commitment() instead" )] #[allow(deprecated)] pub fn get_confirmed_blocks_with_limit_and_commitment( &self, start_slot: Slot, limit: usize, commitment_config: CommitmentConfig, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()).get_confirmed_blocks_with_limit_and_commitment( start_slot, limit, commitment_config, ), ) } /// Get confirmed signatures for transactions involving an address. /// /// Returns up to 1000 signatures, ordered from newest to oldest. /// /// This method uses the [`Finalized`] [commitment level][cl]. /// /// [`Finalized`]: CommitmentLevel::Finalized. /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getSignaturesForAddress`] RPC /// method. /// /// [`getSignaturesForAddress`]: https://solana.com/docs/rpc/http/getsignaturesforaddress /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # system_transaction, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// let signatures = rpc_client.get_signatures_for_address( /// &alice.pubkey(), /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_signatures_for_address( &self, address: &Pubkey, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_signatures_for_address(address)) } /// Get confirmed signatures for transactions involving an address. /// /// # Errors /// /// This method returns an error if the given [commitment level][cl] is below /// [`Confirmed`]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// /// This method corresponds directly to the [`getSignaturesForAddress`] RPC /// method. /// /// [`getSignaturesForAddress`]: https://solana.com/docs/rpc/http/getsignaturesforaddress /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::{GetConfirmedSignaturesForAddress2Config, RpcClient}; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # system_transaction, /// # commitment_config::CommitmentConfig, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// # let signature = rpc_client.send_and_confirm_transaction(&tx)?; /// let config = GetConfirmedSignaturesForAddress2Config { /// before: None, /// until: None, /// limit: Some(3), /// commitment: Some(CommitmentConfig::confirmed()), /// }; /// let signatures = rpc_client.get_signatures_for_address_with_config( /// &alice.pubkey(), /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_signatures_for_address_with_config( &self, address: &Pubkey, config: GetConfirmedSignaturesForAddress2Config, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()).get_signatures_for_address_with_config(address, config), ) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_signatures_for_address() instead" )] #[allow(deprecated)] pub fn get_confirmed_signatures_for_address2( &self, address: &Pubkey, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_confirmed_signatures_for_address2(address)) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_signatures_for_address_with_config() instead" )] #[allow(deprecated)] pub fn get_confirmed_signatures_for_address2_with_config( &self, address: &Pubkey, config: GetConfirmedSignaturesForAddress2Config, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()) .get_confirmed_signatures_for_address2_with_config(address, config), ) } /// Returns transaction details for a confirmed transaction. /// /// This method uses the [`Finalized`] [commitment level][cl]. /// /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getTransaction`] RPC method, /// unless the remote node version is less than 1.7, in which case it maps /// to the [`getConfirmedTransaction`] RPC method. /// /// [`getTransaction`]: https://solana.com/docs/rpc/http/gettransaction /// [`getConfirmedTransaction`]: https://solana.com/docs/rpc/deprecated/getConfirmedTransaction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # system_transaction, /// # }; /// # use solana_transaction_status::UiTransactionEncoding; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_and_confirm_transaction(&tx)?; /// let transaction = rpc_client.get_transaction( /// &signature, /// UiTransactionEncoding::Json, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_transaction( &self, signature: &Signature, encoding: UiTransactionEncoding, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_transaction(signature, encoding)) } /// Returns transaction details for a confirmed transaction. /// /// # Errors /// /// This method returns an error if the given [commitment level][cl] is below /// [`Confirmed`]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed /// /// # RPC Reference /// /// This method corresponds directly to the [`getTransaction`] RPC method, /// unless the remote node version is less than 1.7, in which case it maps /// to the [`getConfirmedTransaction`] RPC method. /// /// [`getTransaction`]: https://solana.com/docs/rpc/http/gettransaction /// [`getConfirmedTransaction`]: https://solana.com/docs/rpc/deprecated/getConfirmedTransaction /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::RpcTransactionConfig, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, /// # system_transaction, /// # commitment_config::CommitmentConfig, /// # }; /// # use solana_transaction_status::UiTransactionEncoding; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// # let lamports = 50; /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_and_confirm_transaction(&tx)?; /// let config = RpcTransactionConfig { /// encoding: Some(UiTransactionEncoding::Json), /// commitment: Some(CommitmentConfig::confirmed()), /// max_supported_transaction_version: Some(0), /// }; /// let transaction = rpc_client.get_transaction_with_config( /// &signature, /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_transaction_with_config( &self, signature: &Signature, config: RpcTransactionConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_transaction_with_config(signature, config)) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_transaction() instead" )] #[allow(deprecated)] pub fn get_confirmed_transaction( &self, signature: &Signature, encoding: UiTransactionEncoding, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_confirmed_transaction(signature, encoding)) } #[deprecated( since = "1.7.0", note = "Please use RpcClient::get_transaction_with_config() instead" )] #[allow(deprecated)] pub fn get_confirmed_transaction_with_config( &self, signature: &Signature, config: RpcConfirmedTransactionConfig, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()).get_confirmed_transaction_with_config(signature, config), ) } /// Returns the estimated production time of a block. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBlockTime`] RPC method. /// /// [`getBlockTime`]: https://solana.com/docs/rpc/http/getblocktime /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// // Get the time of the most recent finalized block /// let slot = rpc_client.get_slot()?; /// let block_time = rpc_client.get_block_time(slot)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_block_time(&self, slot: Slot) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_block_time(slot)) } /// Returns information about the current epoch. /// /// This method uses the configured default [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getEpochInfo`] RPC method. /// /// [`getEpochInfo`]: https://solana.com/docs/rpc/http/getepochinfo /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let epoch_info = rpc_client.get_epoch_info()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_epoch_info(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_epoch_info()) } /// Returns information about the current epoch. /// /// # RPC Reference /// /// This method corresponds directly to the [`getEpochInfo`] RPC method. /// /// [`getEpochInfo`]: https://solana.com/docs/rpc/http/getepochinfo /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let commitment_config = CommitmentConfig::confirmed(); /// let epoch_info = rpc_client.get_epoch_info_with_commitment( /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_epoch_info_with_commitment( &self, commitment_config: CommitmentConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_epoch_info_with_commitment(commitment_config)) } /// Returns the leader schedule for an epoch. /// /// This method uses the configured default [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getLeaderSchedule`] RPC method. /// /// [`getLeaderSchedule`]: https://solana.com/docs/rpc/http/getleaderschedule /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let slot = rpc_client.get_slot()?; /// let leader_schedule = rpc_client.get_leader_schedule( /// Some(slot), /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_leader_schedule( &self, slot: Option, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_leader_schedule(slot)) } /// Returns the leader schedule for an epoch. /// /// # RPC Reference /// /// This method corresponds directly to the [`getLeaderSchedule`] RPC method. /// /// [`getLeaderSchedule`]: https://solana.com/docs/rpc/http/getleaderschedule /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let slot = rpc_client.get_slot()?; /// let commitment_config = CommitmentConfig::processed(); /// let leader_schedule = rpc_client.get_leader_schedule_with_commitment( /// Some(slot), /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_leader_schedule_with_commitment( &self, slot: Option, commitment_config: CommitmentConfig, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()).get_leader_schedule_with_commitment(slot, commitment_config), ) } /// Returns the leader schedule for an epoch. /// /// # RPC Reference /// /// This method corresponds directly to the [`getLeaderSchedule`] RPC method. /// /// [`getLeaderSchedule`]: https://solana.com/docs/rpc/http/getleaderschedule /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::RpcLeaderScheduleConfig, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let slot = rpc_client.get_slot()?; /// # let validator_pubkey_str = "7AYmEYBBetok8h5L3Eo3vi3bDWnjNnaFbSXfSNYV5ewB".to_string(); /// let config = RpcLeaderScheduleConfig { /// identity: Some(validator_pubkey_str), /// commitment: Some(CommitmentConfig::processed()), /// }; /// let leader_schedule = rpc_client.get_leader_schedule_with_config( /// Some(slot), /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_leader_schedule_with_config( &self, slot: Option, config: RpcLeaderScheduleConfig, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_leader_schedule_with_config(slot, config)) } /// Returns epoch schedule information from this cluster's genesis config. /// /// # RPC Reference /// /// This method corresponds directly to the [`getEpochSchedule`] RPC method. /// /// [`getEpochSchedule`]: https://solana.com/docs/rpc/http/getepochschedule /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let epoch_schedule = rpc_client.get_epoch_schedule()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_epoch_schedule(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_epoch_schedule()) } /// Returns a list of recent performance samples, in reverse slot order. /// /// Performance samples are taken every 60 seconds and include the number of /// transactions and slots that occur in a given time window. /// /// # RPC Reference /// /// This method corresponds directly to the [`getRecentPerformanceSamples`] RPC method. /// /// [`getRecentPerformanceSamples`]: https://solana.com/docs/rpc/http/getrecentperformancesamples /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let limit = 10; /// let performance_samples = rpc_client.get_recent_performance_samples( /// Some(limit), /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_recent_performance_samples( &self, limit: Option, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_recent_performance_samples(limit)) } /// Returns a list of minimum prioritization fees from recent blocks. /// Takes an optional vector of addresses; if any addresses are provided, the response will /// reflect the minimum prioritization fee to land a transaction locking all of the provided /// accounts as writable. /// /// Currently, a node's prioritization-fee cache stores data from up to 150 blocks. /// /// # RPC Reference /// /// This method corresponds directly to the [`getRecentPrioritizationFees`] RPC method. /// /// [`getRecentPrioritizationFees`]: https://solana.com/docs/rpc/http/getrecentprioritizationfees /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::signature::{Keypair, Signer}; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// let addresses = vec![alice.pubkey(), bob.pubkey()]; /// let prioritization_fees = rpc_client.get_recent_prioritization_fees( /// &addresses, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_recent_prioritization_fees( &self, addresses: &[Pubkey], ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_recent_prioritization_fees(addresses)) } /// Returns the identity pubkey for the current node. /// /// # RPC Reference /// /// This method corresponds directly to the [`getIdentity`] RPC method. /// /// [`getIdentity`]: https://solana.com/docs/rpc/http/getidentity /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let identity = rpc_client.get_identity()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_identity(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_identity()) } /// Returns the current inflation governor. /// /// This method uses the [`Finalized`] [commitment level][cl]. /// /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getInflationGovernor`] RPC /// method. /// /// [`getInflationGovernor`]: https://solana.com/docs/rpc/http/getinflationgovernor /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let inflation_governor = rpc_client.get_inflation_governor()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_inflation_governor(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_inflation_governor()) } /// Returns the specific inflation values for the current epoch. /// /// # RPC Reference /// /// This method corresponds directly to the [`getInflationRate`] RPC method. /// /// [`getInflationRate`]: https://solana.com/docs/rpc/http/getinflationrate /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let inflation_rate = rpc_client.get_inflation_rate()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_inflation_rate(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_inflation_rate()) } /// Returns the inflation reward for a list of addresses for an epoch. /// /// This method uses the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getInflationReward`] RPC method. /// /// [`getInflationReward`]: https://solana.com/docs/rpc/http/getinflationreward /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::signature::{Keypair, Signer}; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let epoch_info = rpc_client.get_epoch_info()?; /// # let epoch = epoch_info.epoch; /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// let addresses = vec![alice.pubkey(), bob.pubkey()]; /// let inflation_reward = rpc_client.get_inflation_reward( /// &addresses, /// Some(epoch), /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_inflation_reward( &self, addresses: &[Pubkey], epoch: Option, ) -> ClientResult>> { self.invoke((self.rpc_client.as_ref()).get_inflation_reward(addresses, epoch)) } /// Returns the current solana version running on the node. /// /// # RPC Reference /// /// This method corresponds directly to the [`getVersion`] RPC method. /// /// [`getVersion`]: https://solana.com/docs/rpc/http/getversion /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::signature::{Keypair, Signer}; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let expected_version = semver::Version::new(1, 7, 0); /// let version = rpc_client.get_version()?; /// let version = semver::Version::parse(&version.solana_core)?; /// assert!(version >= expected_version); /// # Ok::<(), Box>(()) /// ``` pub fn get_version(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_version()) } /// Returns the lowest slot that the node has information about in its ledger. /// /// This value may increase over time if the node is configured to purge /// older ledger data. /// /// # RPC Reference /// /// This method corresponds directly to the [`minimumLedgerSlot`] RPC /// method. /// /// [`minimumLedgerSlot`]: https://solana.com/docs/rpc/http/minimumledgerslot /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let slot = rpc_client.minimum_ledger_slot()?; /// # Ok::<(), Error>(()) /// ``` pub fn minimum_ledger_slot(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).minimum_ledger_slot()) } /// Returns all information associated with the account of the provided pubkey. /// /// This method uses the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// To get multiple accounts at once, use the [`get_multiple_accounts`] method. /// /// [`get_multiple_accounts`]: RpcClient::get_multiple_accounts /// /// # Errors /// /// If the account does not exist, this method returns /// [`RpcError::ForUser`]. This is unlike [`get_account_with_commitment`], /// which returns `Ok(None)` if the account does not exist. /// /// [`RpcError::ForUser`]: solana_rpc_client_api::request::RpcError::ForUser /// [`get_account_with_commitment`]: RpcClient::get_account_with_commitment /// /// # RPC Reference /// /// This method is built on the [`getAccountInfo`] RPC method. /// /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::{self, RpcClient}; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # pubkey::Pubkey, /// # }; /// # use std::str::FromStr; /// # let mocks = rpc_client::create_rpc_client_mocks(); /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks); /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap(); /// let account = rpc_client.get_account(&alice_pubkey)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_account(&self, pubkey: &Pubkey) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_account(pubkey)) } /// Returns all information associated with the account of the provided pubkey. /// /// If the account does not exist, this method returns `Ok(None)`. /// /// To get multiple accounts at once, use the [`get_multiple_accounts_with_commitment`] method. /// /// [`get_multiple_accounts_with_commitment`]: RpcClient::get_multiple_accounts_with_commitment /// /// # RPC Reference /// /// This method is built on the [`getAccountInfo`] RPC method. /// /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::{self, RpcClient}; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # pubkey::Pubkey, /// # commitment_config::CommitmentConfig, /// # }; /// # use std::str::FromStr; /// # let mocks = rpc_client::create_rpc_client_mocks(); /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks); /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap(); /// let commitment_config = CommitmentConfig::processed(); /// let account = rpc_client.get_account_with_commitment( /// &alice_pubkey, /// commitment_config, /// )?; /// assert!(account.value.is_some()); /// # Ok::<(), Error>(()) /// ``` pub fn get_account_with_commitment( &self, pubkey: &Pubkey, commitment_config: CommitmentConfig, ) -> RpcResult> { self.invoke( (self.rpc_client.as_ref()).get_account_with_commitment(pubkey, commitment_config), ) } /// Returns all information associated with the account of the provided pubkey. /// /// If the account does not exist, this method returns `Ok(None)`. /// /// To get multiple accounts at once, use the [`get_multiple_accounts_with_config`] method. /// /// [`get_multiple_accounts_with_config`]: RpcClient::get_multiple_accounts_with_config /// /// # RPC Reference /// /// This method is built on the [`getAccountInfo`] RPC method. /// /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # config::RpcAccountInfoConfig, /// # client_error::Error, /// # }; /// # use solana_rpc_client::rpc_client::{self, RpcClient}; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # pubkey::Pubkey, /// # commitment_config::CommitmentConfig, /// # }; /// # use solana_account_decoder::UiAccountEncoding; /// # use std::str::FromStr; /// # let mocks = rpc_client::create_rpc_client_mocks(); /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks); /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap(); /// let commitment_config = CommitmentConfig::processed(); /// let config = RpcAccountInfoConfig { /// encoding: Some(UiAccountEncoding::Base64), /// commitment: Some(commitment_config), /// .. RpcAccountInfoConfig::default() /// }; /// let account = rpc_client.get_account_with_config( /// &alice_pubkey, /// config, /// )?; /// assert!(account.value.is_some()); /// # Ok::<(), Error>(()) /// ``` pub fn get_account_with_config( &self, pubkey: &Pubkey, config: RpcAccountInfoConfig, ) -> RpcResult> { self.invoke((self.rpc_client.as_ref()).get_account_with_config(pubkey, config)) } /// Get the max slot seen from retransmit stage. /// /// # RPC Reference /// /// This method corresponds directly to the [`getMaxRetransmitSlot`] RPC /// method. /// /// [`getMaxRetransmitSlot`]: https://solana.com/docs/rpc/http/getmaxretransmitslot /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let slot = rpc_client.get_max_retransmit_slot()?; /// # Ok::<(), Error>(()) pub fn get_max_retransmit_slot(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_max_retransmit_slot()) } /// Get the max slot seen from after [shred](https://solana.com/docs/terminology#shred) insert. /// /// # RPC Reference /// /// This method corresponds directly to the /// [`getMaxShredInsertSlot`] RPC method. /// /// [`getMaxShredInsertSlot`]: https://solana.com/docs/rpc/http/getmaxshredinsertslot /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let slot = rpc_client.get_max_shred_insert_slot()?; /// # Ok::<(), Error>(()) pub fn get_max_shred_insert_slot(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_max_shred_insert_slot()) } /// Returns the account information for a list of pubkeys. /// /// This method uses the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method is built on the [`getMultipleAccounts`] RPC method. /// /// [`getMultipleAccounts`]: https://solana.com/docs/rpc/http/getmultipleaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// let pubkeys = vec![alice.pubkey(), bob.pubkey()]; /// let accounts = rpc_client.get_multiple_accounts(&pubkeys)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_multiple_accounts(&self, pubkeys: &[Pubkey]) -> ClientResult>> { self.invoke((self.rpc_client.as_ref()).get_multiple_accounts(pubkeys)) } /// Returns the account information for a list of pubkeys. /// /// # RPC Reference /// /// This method is built on the [`getMultipleAccounts`] RPC method. /// /// [`getMultipleAccounts`]: https://solana.com/docs/rpc/http/getmultipleaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # commitment_config::CommitmentConfig, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// let pubkeys = vec![alice.pubkey(), bob.pubkey()]; /// let commitment_config = CommitmentConfig::processed(); /// let accounts = rpc_client.get_multiple_accounts_with_commitment( /// &pubkeys, /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_multiple_accounts_with_commitment( &self, pubkeys: &[Pubkey], commitment_config: CommitmentConfig, ) -> RpcResult>> { self.invoke( (self.rpc_client.as_ref()) .get_multiple_accounts_with_commitment(pubkeys, commitment_config), ) } /// Returns the account information for a list of pubkeys. /// /// # RPC Reference /// /// This method is built on the [`getMultipleAccounts`] RPC method. /// /// [`getMultipleAccounts`]: https://solana.com/docs/rpc/http/getmultipleaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # config::RpcAccountInfoConfig, /// # client_error::Error, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # commitment_config::CommitmentConfig, /// # }; /// # use solana_account_decoder::UiAccountEncoding; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let bob = Keypair::new(); /// let pubkeys = vec![alice.pubkey(), bob.pubkey()]; /// let commitment_config = CommitmentConfig::processed(); /// let config = RpcAccountInfoConfig { /// encoding: Some(UiAccountEncoding::Base64), /// commitment: Some(commitment_config), /// .. RpcAccountInfoConfig::default() /// }; /// let accounts = rpc_client.get_multiple_accounts_with_config( /// &pubkeys, /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_multiple_accounts_with_config( &self, pubkeys: &[Pubkey], config: RpcAccountInfoConfig, ) -> RpcResult>> { self.invoke((self.rpc_client.as_ref()).get_multiple_accounts_with_config(pubkeys, config)) } /// Gets the raw data associated with an account. /// /// This is equivalent to calling [`get_account`] and then accessing the /// [`data`] field of the returned [`Account`]. /// /// [`get_account`]: RpcClient::get_account /// [`data`]: Account::data /// /// # RPC Reference /// /// This method is built on the [`getAccountInfo`] RPC method. /// /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::{self, RpcClient}; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # pubkey::Pubkey, /// # }; /// # use std::str::FromStr; /// # let mocks = rpc_client::create_rpc_client_mocks(); /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks); /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap(); /// let account_data = rpc_client.get_account_data(&alice_pubkey)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_account_data(&self, pubkey: &Pubkey) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_account_data(pubkey)) } /// Returns minimum balance required to make an account with specified data length rent exempt. /// /// # RPC Reference /// /// This method corresponds directly to the /// [`getMinimumBalanceForRentExemption`] RPC method. /// /// [`getMinimumBalanceForRentExemption`]: https://solana.com/docs/rpc/http/getminimumbalanceforrentexemption /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let data_len = 300; /// let balance = rpc_client.get_minimum_balance_for_rent_exemption(data_len)?; /// # Ok::<(), Error>(()) /// ``` pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_minimum_balance_for_rent_exemption(data_len)) } /// Request the balance of the provided account pubkey. /// /// This method uses the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getBalance`] RPC method. /// /// [`getBalance`]: https://solana.com/docs/rpc/http/getbalance /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// let balance = rpc_client.get_balance(&alice.pubkey())?; /// # Ok::<(), Error>(()) /// ``` pub fn get_balance(&self, pubkey: &Pubkey) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_balance(pubkey)) } /// Request the balance of the provided account pubkey. /// /// # RPC Reference /// /// This method corresponds directly to the [`getBalance`] RPC method. /// /// [`getBalance`]: https://solana.com/docs/rpc/http/getbalance /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # commitment_config::CommitmentConfig, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// let commitment_config = CommitmentConfig::processed(); /// let balance = rpc_client.get_balance_with_commitment( /// &alice.pubkey(), /// commitment_config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_balance_with_commitment( &self, pubkey: &Pubkey, commitment_config: CommitmentConfig, ) -> RpcResult { self.invoke( (self.rpc_client.as_ref()).get_balance_with_commitment(pubkey, commitment_config), ) } /// Returns all accounts owned by the provided program pubkey. /// /// This method uses the configured [commitment level][cl]. /// /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment /// /// # RPC Reference /// /// This method corresponds directly to the [`getProgramAccounts`] RPC /// method. /// /// [`getProgramAccounts`]: https://solana.com/docs/rpc/http/getprogramaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # }; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// let accounts = rpc_client.get_program_accounts(&alice.pubkey())?; /// # Ok::<(), Error>(()) /// ``` pub fn get_program_accounts(&self, pubkey: &Pubkey) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_program_accounts(pubkey)) } /// Returns all accounts owned by the provided program pubkey. /// /// # RPC Reference /// /// This method is built on the [`getProgramAccounts`] RPC method. /// /// [`getProgramAccounts`]: https://solana.com/docs/rpc/http/getprogramaccounts /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::{ /// # client_error::Error, /// # config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}, /// # filter::{MemcmpEncodedBytes, RpcFilterType, Memcmp}, /// # }; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::{ /// # signature::Signer, /// # signer::keypair::Keypair, /// # commitment_config::CommitmentConfig, /// # }; /// # use solana_account_decoder::{UiDataSliceConfig, UiAccountEncoding}; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// # let alice = Keypair::new(); /// # let base64_bytes = "\ /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\ /// # AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; /// let memcmp = RpcFilterType::Memcmp(Memcmp::new( /// 0, // offset /// MemcmpEncodedBytes::Base64(base64_bytes.to_string()), // encoded bytes /// )); /// let config = RpcProgramAccountsConfig { /// filters: Some(vec![ /// RpcFilterType::DataSize(128), /// memcmp, /// ]), /// account_config: RpcAccountInfoConfig { /// encoding: Some(UiAccountEncoding::Base64), /// data_slice: Some(UiDataSliceConfig { /// offset: 0, /// length: 5, /// }), /// commitment: Some(CommitmentConfig::processed()), /// min_context_slot: Some(1234), /// }, /// with_context: Some(false), /// }; /// let accounts = rpc_client.get_program_accounts_with_config( /// &alice.pubkey(), /// config, /// )?; /// # Ok::<(), Error>(()) /// ``` pub fn get_program_accounts_with_config( &self, pubkey: &Pubkey, config: RpcProgramAccountsConfig, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_program_accounts_with_config(pubkey, config)) } /// Returns the stake minimum delegation, in lamports. /// /// # RPC Reference /// /// This method corresponds directly to the [`getStakeMinimumDelegation`] RPC method. /// /// [`getStakeMinimumDelegation`]: https://solana.com/docs/rpc/http/getstakeminimumdelegation /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let stake_minimum_delegation = rpc_client.get_stake_minimum_delegation()?; /// # Ok::<(), Error>(()) /// ``` pub fn get_stake_minimum_delegation(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_stake_minimum_delegation()) } /// Returns the stake minimum delegation, in lamports, based on the commitment level. /// /// # RPC Reference /// /// This method corresponds directly to the [`getStakeMinimumDelegation`] RPC method. /// /// [`getStakeMinimumDelegation`]: https://solana.com/docs/rpc/http/getstakeminimumdelegation /// /// # Examples /// /// ``` /// # use solana_rpc_client_api::client_error::Error; /// # use solana_rpc_client::rpc_client::RpcClient; /// # use solana_sdk::commitment_config::CommitmentConfig; /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); /// let stake_minimum_delegation = /// rpc_client.get_stake_minimum_delegation_with_commitment(CommitmentConfig::confirmed())?; /// # Ok::<(), Error>(()) /// ``` pub fn get_stake_minimum_delegation_with_commitment( &self, commitment_config: CommitmentConfig, ) -> ClientResult { self.invoke( self.rpc_client .get_stake_minimum_delegation_with_commitment(commitment_config), ) } /// Request the transaction count. pub fn get_transaction_count(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_transaction_count()) } pub fn get_transaction_count_with_commitment( &self, commitment_config: CommitmentConfig, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()).get_transaction_count_with_commitment(commitment_config), ) } #[deprecated( since = "1.9.0", note = "Please use `get_latest_blockhash` and `get_fee_for_message` instead" )] #[allow(deprecated)] pub fn get_fees(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_fees()) } #[deprecated( since = "1.9.0", note = "Please use `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead" )] #[allow(deprecated)] pub fn get_fees_with_commitment(&self, commitment_config: CommitmentConfig) -> RpcResult { self.invoke((self.rpc_client.as_ref()).get_fees_with_commitment(commitment_config)) } #[deprecated(since = "1.9.0", note = "Please use `get_latest_blockhash` instead")] #[allow(deprecated)] pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> { self.invoke((self.rpc_client.as_ref()).get_recent_blockhash()) } #[deprecated( since = "1.9.0", note = "Please use `get_latest_blockhash_with_commitment` instead" )] #[allow(deprecated)] pub fn get_recent_blockhash_with_commitment( &self, commitment_config: CommitmentConfig, ) -> RpcResult<(Hash, FeeCalculator, Slot)> { self.invoke( (self.rpc_client.as_ref()).get_recent_blockhash_with_commitment(commitment_config), ) } #[deprecated(since = "1.9.0", note = "Please `get_fee_for_message` instead")] #[allow(deprecated)] pub fn get_fee_calculator_for_blockhash( &self, blockhash: &Hash, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_fee_calculator_for_blockhash(blockhash)) } #[deprecated( since = "1.9.0", note = "Please `get_latest_blockhash_with_commitment` and `get_fee_for_message` instead" )] #[allow(deprecated)] pub fn get_fee_calculator_for_blockhash_with_commitment( &self, blockhash: &Hash, commitment_config: CommitmentConfig, ) -> RpcResult> { self.invoke( (self.rpc_client.as_ref()) .get_fee_calculator_for_blockhash_with_commitment(blockhash, commitment_config), ) } #[deprecated( since = "1.9.0", note = "Please do not use, will no longer be available in the future" )] #[allow(deprecated)] pub fn get_fee_rate_governor(&self) -> RpcResult { self.invoke((self.rpc_client.as_ref()).get_fee_rate_governor()) } #[deprecated( since = "1.9.0", note = "Please do not use, will no longer be available in the future" )] #[allow(deprecated)] pub fn get_new_blockhash(&self, blockhash: &Hash) -> ClientResult<(Hash, FeeCalculator)> { self.invoke((self.rpc_client.as_ref()).get_new_blockhash(blockhash)) } pub fn get_first_available_block(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_first_available_block()) } pub fn get_genesis_hash(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_genesis_hash()) } pub fn get_health(&self) -> ClientResult<()> { self.invoke((self.rpc_client.as_ref()).get_health()) } pub fn get_token_account(&self, pubkey: &Pubkey) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_token_account(pubkey)) } pub fn get_token_account_with_commitment( &self, pubkey: &Pubkey, commitment_config: CommitmentConfig, ) -> RpcResult> { self.invoke( (self.rpc_client.as_ref()).get_token_account_with_commitment(pubkey, commitment_config), ) } pub fn get_token_account_balance(&self, pubkey: &Pubkey) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_token_account_balance(pubkey)) } pub fn get_token_account_balance_with_commitment( &self, pubkey: &Pubkey, commitment_config: CommitmentConfig, ) -> RpcResult { self.invoke( (self.rpc_client.as_ref()) .get_token_account_balance_with_commitment(pubkey, commitment_config), ) } pub fn get_token_accounts_by_delegate( &self, delegate: &Pubkey, token_account_filter: TokenAccountsFilter, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()) .get_token_accounts_by_delegate(delegate, token_account_filter), ) } pub fn get_token_accounts_by_delegate_with_commitment( &self, delegate: &Pubkey, token_account_filter: TokenAccountsFilter, commitment_config: CommitmentConfig, ) -> RpcResult> { self.invoke( (self.rpc_client.as_ref()).get_token_accounts_by_delegate_with_commitment( delegate, token_account_filter, commitment_config, ), ) } pub fn get_token_accounts_by_owner( &self, owner: &Pubkey, token_account_filter: TokenAccountsFilter, ) -> ClientResult> { self.invoke( (self.rpc_client.as_ref()).get_token_accounts_by_owner(owner, token_account_filter), ) } pub fn get_token_accounts_by_owner_with_commitment( &self, owner: &Pubkey, token_account_filter: TokenAccountsFilter, commitment_config: CommitmentConfig, ) -> RpcResult> { self.invoke( (self.rpc_client.as_ref()).get_token_accounts_by_owner_with_commitment( owner, token_account_filter, commitment_config, ), ) } pub fn get_token_largest_accounts( &self, mint: &Pubkey, ) -> ClientResult> { self.invoke((self.rpc_client.as_ref()).get_token_largest_accounts(mint)) } pub fn get_token_largest_accounts_with_commitment( &self, mint: &Pubkey, commitment_config: CommitmentConfig, ) -> RpcResult> { self.invoke( (self.rpc_client.as_ref()) .get_token_largest_accounts_with_commitment(mint, commitment_config), ) } pub fn get_token_supply(&self, mint: &Pubkey) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_token_supply(mint)) } pub fn get_token_supply_with_commitment( &self, mint: &Pubkey, commitment_config: CommitmentConfig, ) -> RpcResult { self.invoke( (self.rpc_client.as_ref()).get_token_supply_with_commitment(mint, commitment_config), ) } pub fn request_airdrop(&self, pubkey: &Pubkey, lamports: u64) -> ClientResult { self.invoke((self.rpc_client.as_ref()).request_airdrop(pubkey, lamports)) } pub fn request_airdrop_with_blockhash( &self, pubkey: &Pubkey, lamports: u64, recent_blockhash: &Hash, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).request_airdrop_with_blockhash( pubkey, lamports, recent_blockhash, )) } pub fn request_airdrop_with_config( &self, pubkey: &Pubkey, lamports: u64, config: RpcRequestAirdropConfig, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()).request_airdrop_with_config(pubkey, lamports, config), ) } pub fn poll_get_balance_with_commitment( &self, pubkey: &Pubkey, commitment_config: CommitmentConfig, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()).poll_get_balance_with_commitment(pubkey, commitment_config), ) } pub fn wait_for_balance_with_commitment( &self, pubkey: &Pubkey, expected_balance: Option, commitment_config: CommitmentConfig, ) -> Option { self.invoke((self.rpc_client.as_ref()).wait_for_balance_with_commitment( pubkey, expected_balance, commitment_config, )) .ok() } /// Poll the server to confirm a transaction. pub fn poll_for_signature(&self, signature: &Signature) -> ClientResult<()> { self.invoke((self.rpc_client.as_ref()).poll_for_signature(signature)) } /// Poll the server to confirm a transaction. pub fn poll_for_signature_with_commitment( &self, signature: &Signature, commitment_config: CommitmentConfig, ) -> ClientResult<()> { self.invoke( (self.rpc_client.as_ref()) .poll_for_signature_with_commitment(signature, commitment_config), ) } /// Poll the server to confirm a transaction. pub fn poll_for_signature_confirmation( &self, signature: &Signature, min_confirmed_blocks: usize, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()) .poll_for_signature_confirmation(signature, min_confirmed_blocks), ) } pub fn get_num_blocks_since_signature_confirmation( &self, signature: &Signature, ) -> ClientResult { self.invoke( (self.rpc_client.as_ref()).get_num_blocks_since_signature_confirmation(signature), ) } pub fn get_latest_blockhash(&self) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_latest_blockhash()) } #[allow(deprecated)] pub fn get_latest_blockhash_with_commitment( &self, commitment: CommitmentConfig, ) -> ClientResult<(Hash, u64)> { self.invoke((self.rpc_client.as_ref()).get_latest_blockhash_with_commitment(commitment)) } #[allow(deprecated)] pub fn is_blockhash_valid( &self, blockhash: &Hash, commitment: CommitmentConfig, ) -> ClientResult { self.invoke((self.rpc_client.as_ref()).is_blockhash_valid(blockhash, commitment)) } #[allow(deprecated)] pub fn get_fee_for_message(&self, message: &impl SerializableMessage) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_fee_for_message(message)) } pub fn get_new_latest_blockhash(&self, blockhash: &Hash) -> ClientResult { self.invoke((self.rpc_client.as_ref()).get_new_latest_blockhash(blockhash)) } pub fn get_transport_stats(&self) -> RpcTransportStats { (self.rpc_client.as_ref()).get_transport_stats() } pub fn get_feature_activation_slot(&self, feature_id: &Pubkey) -> ClientResult> { self.get_account_with_commitment(feature_id, self.commitment()) .and_then(|maybe_feature_account| { maybe_feature_account .value .map(|feature_account| { bincode::deserialize(feature_account.data()).map_err(|_| { ClientError::from(ErrorKind::Custom( "Failed to deserialize feature account".to_string(), )) }) }) .transpose() }) .map(|maybe_feature: Option| { maybe_feature.and_then(|feature| feature.activated_at) }) } fn invoke>>(&self, f: F) -> ClientResult { // `block_on()` panics if called within an asynchronous execution context. Whereas // `block_in_place()` only panics if called from a current_thread runtime, which is the // lesser evil. tokio::task::block_in_place(move || self.runtime.as_ref().expect("runtime").block_on(f)) } pub fn get_inner_client(&self) -> &Arc { &self.rpc_client } pub fn runtime(&self) -> &tokio::runtime::Runtime { self.runtime.as_ref().expect("runtime") } } /// Mocks for documentation examples #[doc(hidden)] pub fn create_rpc_client_mocks() -> crate::mock_sender::Mocks { let mut mocks = std::collections::HashMap::new(); let get_account_request = RpcRequest::GetAccountInfo; let get_account_response = serde_json::to_value(Response { context: RpcResponseContext { slot: 1, api_version: None, }, value: { let pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap(); let account = Account { lamports: 1_000_000, data: vec![], owner: pubkey, executable: false, rent_epoch: 0, }; UiAccount::encode(&pubkey, &account, UiAccountEncoding::Base64, None, None) }, }) .unwrap(); mocks.insert(get_account_request, get_account_response); mocks } #[cfg(test)] mod tests { use { super::*, crate::mock_sender::PUBKEY, assert_matches::assert_matches, crossbeam_channel::unbounded, jsonrpc_core::{futures::prelude::*, Error, IoHandler, Params}, jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder}, serde_json::{json, Number}, solana_rpc_client_api::client_error::ErrorKind, solana_sdk::{ instruction::InstructionError, signature::{Keypair, Signer}, system_transaction, transaction::TransactionError, }, std::{io, thread}, }; #[test] fn test_send() { _test_send(); } #[tokio::test(flavor = "current_thread")] #[should_panic(expected = "can call blocking only when running on the multi-threaded runtime")] async fn test_send_async_current_thread() { _test_send(); } #[tokio::test(flavor = "multi_thread")] async fn test_send_async_multi_thread() { _test_send(); } fn _test_send() { let (sender, receiver) = unbounded(); thread::spawn(move || { let rpc_addr = "0.0.0.0:0".parse().unwrap(); let mut io = IoHandler::default(); // Successful request io.add_method("getBalance", |_params: Params| { future::ok(Value::Number(Number::from(50))) }); // Failed request io.add_method("getRecentBlockhash", |params: Params| { if params != Params::None { future::err(Error::invalid_request()) } else { future::ok(Value::String( "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx".to_string(), )) } }); let server = ServerBuilder::new(io) .threads(1) .cors(DomainsValidation::AllowOnly(vec![ AccessControlAllowOrigin::Any, ])) .start_http(&rpc_addr) .expect("Unable to start RPC server"); sender.send(*server.address()).unwrap(); server.wait(); }); let rpc_addr = receiver.recv().unwrap(); let rpc_client = RpcClient::new_socket(rpc_addr); let balance: u64 = rpc_client .send( RpcRequest::GetBalance, json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"]), ) .unwrap(); assert_eq!(balance, 50); #[allow(deprecated)] let blockhash: String = rpc_client .send(RpcRequest::GetRecentBlockhash, Value::Null) .unwrap(); assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"); // Send erroneous parameter #[allow(deprecated)] let blockhash: ClientResult = rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"])); assert!(blockhash.is_err()); } #[test] fn test_send_transaction() { let rpc_client = RpcClient::new_mock("succeeds".to_string()); let key = Keypair::new(); let to = solana_sdk::pubkey::new_rand(); let blockhash = Hash::default(); let tx = system_transaction::transfer(&key, &to, 50, blockhash); let signature = rpc_client.send_transaction(&tx); assert_eq!(signature.unwrap(), tx.signatures[0]); let rpc_client = RpcClient::new_mock("fails".to_string()); let signature = rpc_client.send_transaction(&tx); assert!(signature.is_err()); // Test bad signature returned from rpc node let rpc_client = RpcClient::new_mock("malicious".to_string()); let signature = rpc_client.send_transaction(&tx); assert!(signature.is_err()); } #[test] fn test_get_recent_blockhash() { let rpc_client = RpcClient::new_mock("succeeds".to_string()); let expected_blockhash: Hash = PUBKEY.parse().unwrap(); let blockhash = rpc_client.get_latest_blockhash().expect("blockhash ok"); assert_eq!(blockhash, expected_blockhash); let rpc_client = RpcClient::new_mock("fails".to_string()); #[allow(deprecated)] let result = rpc_client.get_recent_blockhash(); assert!(result.is_err()); } #[test] fn test_custom_request() { let rpc_client = RpcClient::new_mock("succeeds".to_string()); let slot = rpc_client.get_slot().unwrap(); assert_eq!(slot, 0); let custom_slot = rpc_client .send::(RpcRequest::Custom { method: "getSlot" }, Value::Null) .unwrap(); assert_eq!(slot, custom_slot); } #[test] fn test_get_signature_status() { let signature = Signature::default(); let rpc_client = RpcClient::new_mock("succeeds".to_string()); let status = rpc_client.get_signature_status(&signature).unwrap(); assert_eq!(status, Some(Ok(()))); let rpc_client = RpcClient::new_mock("sig_not_found".to_string()); let status = rpc_client.get_signature_status(&signature).unwrap(); assert_eq!(status, None); let rpc_client = RpcClient::new_mock("account_in_use".to_string()); let status = rpc_client.get_signature_status(&signature).unwrap(); assert_eq!(status, Some(Err(TransactionError::AccountInUse))); } #[test] fn test_send_and_confirm_transaction() { let rpc_client = RpcClient::new_mock("succeeds".to_string()); let key = Keypair::new(); let to = solana_sdk::pubkey::new_rand(); let blockhash = Hash::default(); let tx = system_transaction::transfer(&key, &to, 50, blockhash); let result = rpc_client.send_and_confirm_transaction(&tx); result.unwrap(); let rpc_client = RpcClient::new_mock("account_in_use".to_string()); let result = rpc_client.send_and_confirm_transaction(&tx); assert!(result.is_err()); let rpc_client = RpcClient::new_mock("instruction_error".to_string()); let result = rpc_client.send_and_confirm_transaction(&tx); assert_matches!( result.unwrap_err().kind(), ErrorKind::TransactionError(TransactionError::InstructionError( 0, InstructionError::UninitializedAccount )) ); let rpc_client = RpcClient::new_mock("sig_not_found".to_string()); let result = rpc_client.send_and_confirm_transaction(&tx); if let ErrorKind::Io(err) = result.unwrap_err().kind() { assert_eq!(err.kind(), io::ErrorKind::Other); } } #[test] fn test_rpc_client_thread() { let rpc_client = RpcClient::new_mock("succeeds".to_string()); thread::spawn(move || rpc_client); } // Regression test that the get_block_production_with_config // method internally creates the json params array correctly. #[test] fn get_block_production_with_config_no_error() -> ClientResult<()> { let rpc_client = RpcClient::new_mock("succeeds".to_string()); let config = RpcBlockProductionConfig { identity: Some(Keypair::new().pubkey().to_string()), range: None, commitment: None, }; let prod = rpc_client.get_block_production_with_config(config)?.value; assert!(!prod.by_identity.is_empty()); Ok(()) } #[test] fn test_get_latest_blockhash() { let rpc_client = RpcClient::new_mock("succeeds".to_string()); let expected_blockhash: Hash = PUBKEY.parse().unwrap(); let blockhash = rpc_client.get_latest_blockhash().expect("blockhash ok"); assert_eq!(blockhash, expected_blockhash); let rpc_client = RpcClient::new_mock("fails".to_string()); #[allow(deprecated)] let is_err = rpc_client.get_latest_blockhash().is_err(); assert!(is_err); } #[test] fn test_get_stake_minimum_delegation() { let expected_minimum_delegation: u64 = 123_456_789; let rpc_client = RpcClient::new_mock("succeeds".to_string()); // Test: without commitment { let actual_minimum_delegation = rpc_client.get_stake_minimum_delegation().unwrap(); assert_eq!(expected_minimum_delegation, actual_minimum_delegation); } // Test: with commitment { let actual_minimum_delegation = rpc_client .get_stake_minimum_delegation_with_commitment(CommitmentConfig::confirmed()) .unwrap(); assert_eq!(expected_minimum_delegation, actual_minimum_delegation); } } #[test] fn test_get_program_accounts_with_config() { let program_id = Pubkey::new_unique(); let pubkey = Pubkey::new_unique(); let account = Account { lamports: 1_000_000, data: vec![], owner: program_id, executable: false, rent_epoch: 0, }; let keyed_account = RpcKeyedAccount { pubkey: pubkey.to_string(), account: UiAccount::encode(&pubkey, &account, UiAccountEncoding::Base64, None, None), }; let expected_result = vec![(pubkey, account)]; // Test: without context { let mocks: Mocks = [( RpcRequest::GetProgramAccounts, serde_json::to_value(OptionalContext::NoContext(vec![keyed_account.clone()])) .unwrap(), )] .into_iter() .collect(); let rpc_client = RpcClient::new_mock_with_mocks("mock_client".to_string(), mocks); let result = rpc_client .get_program_accounts_with_config( &program_id, RpcProgramAccountsConfig { filters: None, account_config: RpcAccountInfoConfig { encoding: Some(UiAccountEncoding::Base64), data_slice: None, commitment: None, min_context_slot: None, }, with_context: None, }, ) .unwrap(); assert_eq!(expected_result, result); } // Test: with context { let mocks: Mocks = [( RpcRequest::GetProgramAccounts, serde_json::to_value(OptionalContext::Context(Response { context: RpcResponseContext { slot: 1, api_version: None, }, value: vec![keyed_account], })) .unwrap(), )] .into_iter() .collect(); let rpc_client = RpcClient::new_mock_with_mocks("mock_client".to_string(), mocks); let result = rpc_client .get_program_accounts_with_config( &program_id, RpcProgramAccountsConfig { filters: None, account_config: RpcAccountInfoConfig { encoding: Some(UiAccountEncoding::Base64), data_slice: None, commitment: None, min_context_slot: None, }, with_context: Some(true), }, ) .unwrap(); assert_eq!(expected_result, result); } } }