solana_rpc_client/
rpc_client.rs

1//! Communication with a Solana node over RPC.
2//!
3//! Software that interacts with the Solana blockchain, whether querying its
4//! state or submitting transactions, communicates with a Solana node over
5//! [JSON-RPC], using the [`RpcClient`] type.
6//!
7//! [JSON-RPC]: https://www.jsonrpc.org/specification
8//!
9//! This is a blocking API. For a non-blocking API use the asynchronous client
10//! in [`crate::nonblocking::rpc_client`].
11
12pub use crate::mock_sender::Mocks;
13use {
14    crate::{
15        http_sender::HttpSender,
16        mock_sender::{mock_encoded_account, MockSender},
17        nonblocking::{self, rpc_client::get_rpc_request_str},
18        rpc_sender::*,
19    },
20    serde::Serialize,
21    serde_json::Value,
22    solana_account_decoder_client_types::token::{UiTokenAccount, UiTokenAmount},
23    solana_rpc_client_api::{
24        client_error::{Error as ClientError, ErrorKind, Result as ClientResult},
25        config::{RpcAccountInfoConfig, *},
26        request::{RpcRequest, TokenAccountsFilter},
27        response::*,
28    },
29    solana_sdk::{
30        account::{Account, ReadableAccount},
31        clock::{Epoch, Slot, UnixTimestamp},
32        commitment_config::CommitmentConfig,
33        epoch_info::EpochInfo,
34        epoch_schedule::EpochSchedule,
35        feature::Feature,
36        hash::Hash,
37        message::{v0, Message as LegacyMessage},
38        pubkey::Pubkey,
39        signature::Signature,
40        transaction::{self, uses_durable_nonce, Transaction, VersionedTransaction},
41    },
42    solana_transaction_status_client_types::{
43        EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus,
44        UiConfirmedBlock, UiTransactionEncoding,
45    },
46    std::{net::SocketAddr, str::FromStr, sync::Arc, time::Duration},
47};
48
49#[derive(Default)]
50pub struct RpcClientConfig {
51    pub commitment_config: CommitmentConfig,
52    pub confirm_transaction_initial_timeout: Option<Duration>,
53}
54
55impl RpcClientConfig {
56    pub fn with_commitment(commitment_config: CommitmentConfig) -> Self {
57        RpcClientConfig {
58            commitment_config,
59            ..Self::default()
60        }
61    }
62}
63
64/// Trait used to add support for versioned messages to RPC APIs while
65/// retaining backwards compatibility
66pub trait SerializableMessage: Serialize {}
67impl SerializableMessage for LegacyMessage {}
68impl SerializableMessage for v0::Message {}
69
70/// Trait used to add support for versioned transactions to RPC APIs while
71/// retaining backwards compatibility
72pub trait SerializableTransaction: Serialize {
73    fn get_signature(&self) -> &Signature;
74    fn get_recent_blockhash(&self) -> &Hash;
75    fn uses_durable_nonce(&self) -> bool;
76}
77impl SerializableTransaction for Transaction {
78    fn get_signature(&self) -> &Signature {
79        &self.signatures[0]
80    }
81    fn get_recent_blockhash(&self) -> &Hash {
82        &self.message.recent_blockhash
83    }
84    fn uses_durable_nonce(&self) -> bool {
85        uses_durable_nonce(self).is_some()
86    }
87}
88impl SerializableTransaction for VersionedTransaction {
89    fn get_signature(&self) -> &Signature {
90        &self.signatures[0]
91    }
92    fn get_recent_blockhash(&self) -> &Hash {
93        self.message.recent_blockhash()
94    }
95    fn uses_durable_nonce(&self) -> bool {
96        self.uses_durable_nonce()
97    }
98}
99
100#[derive(Debug, Default)]
101pub struct GetConfirmedSignaturesForAddress2Config {
102    pub before: Option<Signature>,
103    pub until: Option<Signature>,
104    pub limit: Option<usize>,
105    pub commitment: Option<CommitmentConfig>,
106}
107
108/// A client of a remote Solana node.
109///
110/// `RpcClient` communicates with a Solana node over [JSON-RPC], with the
111/// [Solana JSON-RPC protocol][jsonprot]. It is the primary Rust interface for
112/// querying and transacting with the network from external programs.
113///
114/// This type builds on the underlying RPC protocol, adding extra features such
115/// as timeout handling, retries, and waiting on transaction [commitment levels][cl].
116/// Some methods simply pass through to the underlying RPC protocol. Not all RPC
117/// methods are encapsulated by this type, but `RpcClient` does expose a generic
118/// [`send`](RpcClient::send) method for making any [`RpcRequest`].
119///
120/// The documentation for most `RpcClient` methods contains an "RPC Reference"
121/// section that links to the documentation for the underlying JSON-RPC method.
122/// The documentation for `RpcClient` does not reproduce the documentation for
123/// the underlying JSON-RPC methods. Thus reading both is necessary for complete
124/// understanding.
125///
126/// `RpcClient`s generally communicate over HTTP on port 8899, a typical server
127/// URL being "http://localhost:8899".
128///
129/// Methods that query information from recent [slots], including those that
130/// confirm transactions, decide the most recent slot to query based on a
131/// [commitment level][cl], which determines how committed or finalized a slot
132/// must be to be considered for the query. Unless specified otherwise, the
133/// commitment level is [`Finalized`], meaning the slot is definitely
134/// permanently committed. The default commitment level can be configured by
135/// creating `RpcClient` with an explicit [`CommitmentConfig`], and that default
136/// configured commitment level can be overridden by calling the various
137/// `_with_commitment` methods, like
138/// [`RpcClient::confirm_transaction_with_commitment`]. In some cases the
139/// configured commitment level is ignored and `Finalized` is used instead, as
140/// in [`RpcClient::get_blocks`], where it would be invalid to use the
141/// [`Processed`] commitment level. These exceptions are noted in the method
142/// documentation.
143///
144/// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
145/// [`Processed`]: solana_sdk::commitment_config::CommitmentLevel::Processed
146/// [jsonprot]: https://solana.com/docs/rpc
147/// [JSON-RPC]: https://www.jsonrpc.org/specification
148/// [slots]: https://solana.com/docs/terminology#slot
149/// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
150///
151/// # Errors
152///
153/// Methods on `RpcClient` return
154/// [`client_error::Result`][solana_rpc_client_api::client_error::Result], and many of them
155/// return the [`RpcResult`][solana_rpc_client_api::response::RpcResult] typedef, which
156/// contains [`Response<T>`][solana_rpc_client_api::response::Response] on `Ok`. Both
157/// `client_error::Result` and [`RpcResult`] contain `ClientError` on error. In
158/// the case of `RpcResult`, the actual return value is in the
159/// [`value`][solana_rpc_client_api::response::Response::value] field, with RPC contextual
160/// information in the [`context`][solana_rpc_client_api::response::Response::context]
161/// field, so it is common for the value to be accessed with `?.value`, as in
162///
163/// ```
164/// # use solana_sdk::system_transaction;
165/// # use solana_rpc_client_api::client_error::Error;
166/// # use solana_rpc_client::rpc_client::RpcClient;
167/// # use solana_sdk::signature::{Keypair, Signer};
168/// # use solana_sdk::hash::Hash;
169/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
170/// # let key = Keypair::new();
171/// # let to = solana_sdk::pubkey::new_rand();
172/// # let lamports = 50;
173/// # let latest_blockhash = Hash::default();
174/// # let tx = system_transaction::transfer(&key, &to, lamports, latest_blockhash);
175/// let signature = rpc_client.send_transaction(&tx)?;
176/// let statuses = rpc_client.get_signature_statuses(&[signature])?.value;
177/// # Ok::<(), Error>(())
178/// ```
179///
180/// Requests may timeout, in which case they return a [`ClientError`] where the
181/// [`ClientErrorKind`] is [`ClientErrorKind::Reqwest`], and where the interior
182/// [`reqwest::Error`](solana_rpc_client_api::client_error::reqwest::Error)s
183/// [`is_timeout`](solana_rpc_client_api::client_error::reqwest::Error::is_timeout) method
184/// returns `true`. The default timeout is 30 seconds, and may be changed by
185/// calling an appropriate constructor with a `timeout` parameter.
186///
187/// [`ClientError`]: solana_rpc_client_api::client_error::Error
188/// [`ClientErrorKind`]: solana_rpc_client_api::client_error::ErrorKind
189/// [`ClientErrorKind::Reqwest`]: solana_rpc_client_api::client_error::ErrorKind::Reqwest
190pub struct RpcClient {
191    rpc_client: Arc<nonblocking::rpc_client::RpcClient>,
192    runtime: Option<tokio::runtime::Runtime>,
193}
194
195impl Drop for RpcClient {
196    fn drop(&mut self) {
197        self.runtime.take().expect("runtime").shutdown_background();
198    }
199}
200
201impl RpcClient {
202    /// Create an `RpcClient` from an [`RpcSender`] and an [`RpcClientConfig`].
203    ///
204    /// This is the basic constructor, allowing construction with any type of
205    /// `RpcSender`. Most applications should use one of the other constructors,
206    /// such as [`RpcClient::new`], [`RpcClient::new_with_commitment`] or
207    /// [`RpcClient::new_with_timeout`].
208    pub fn new_sender<T: RpcSender + Send + Sync + 'static>(
209        sender: T,
210        config: RpcClientConfig,
211    ) -> Self {
212        Self {
213            rpc_client: Arc::new(nonblocking::rpc_client::RpcClient::new_sender(
214                sender, config,
215            )),
216            runtime: Some(
217                tokio::runtime::Builder::new_current_thread()
218                    .thread_name("solRpcClient")
219                    .enable_io()
220                    .enable_time()
221                    .build()
222                    .unwrap(),
223            ),
224        }
225    }
226
227    /// Create an HTTP `RpcClient`.
228    ///
229    /// The URL is an HTTP URL, usually for port 8899, as in
230    /// "http://localhost:8899".
231    ///
232    /// The client has a default timeout of 30 seconds, and a default [commitment
233    /// level][cl] of [`Finalized`].
234    ///
235    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
236    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
237    ///
238    /// # Examples
239    ///
240    /// ```
241    /// # use solana_rpc_client::rpc_client::RpcClient;
242    /// let url = "http://localhost:8899".to_string();
243    /// let client = RpcClient::new(url);
244    /// ```
245    pub fn new<U: ToString>(url: U) -> Self {
246        Self::new_with_commitment(url, CommitmentConfig::default())
247    }
248
249    /// Create an HTTP `RpcClient` with specified [commitment level][cl].
250    ///
251    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
252    ///
253    /// The URL is an HTTP URL, usually for port 8899, as in
254    /// "http://localhost:8899".
255    ///
256    /// The client has a default timeout of 30 seconds, and a user-specified
257    /// [`CommitmentLevel`] via [`CommitmentConfig`].
258    ///
259    /// [`CommitmentLevel`]: solana_sdk::commitment_config::CommitmentLevel
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// # use solana_sdk::commitment_config::CommitmentConfig;
265    /// # use solana_rpc_client::rpc_client::RpcClient;
266    /// let url = "http://localhost:8899".to_string();
267    /// let commitment_config = CommitmentConfig::processed();
268    /// let client = RpcClient::new_with_commitment(url, commitment_config);
269    /// ```
270    pub fn new_with_commitment<U: ToString>(url: U, commitment_config: CommitmentConfig) -> Self {
271        Self::new_sender(
272            HttpSender::new(url),
273            RpcClientConfig::with_commitment(commitment_config),
274        )
275    }
276
277    /// Create an HTTP `RpcClient` with specified timeout.
278    ///
279    /// The URL is an HTTP URL, usually for port 8899, as in
280    /// "http://localhost:8899".
281    ///
282    /// The client has and a default [commitment level][cl] of
283    /// [`Finalized`].
284    ///
285    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
286    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// # use std::time::Duration;
292    /// # use solana_rpc_client::rpc_client::RpcClient;
293    /// let url = "http://localhost::8899".to_string();
294    /// let timeout = Duration::from_secs(1);
295    /// let client = RpcClient::new_with_timeout(url, timeout);
296    /// ```
297    pub fn new_with_timeout<U: ToString>(url: U, timeout: Duration) -> Self {
298        Self::new_sender(
299            HttpSender::new_with_timeout(url, timeout),
300            RpcClientConfig::with_commitment(CommitmentConfig::default()),
301        )
302    }
303
304    /// Create an HTTP `RpcClient` with specified timeout and [commitment level][cl].
305    ///
306    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
307    ///
308    /// The URL is an HTTP URL, usually for port 8899, as in
309    /// "http://localhost:8899".
310    ///
311    /// # Examples
312    ///
313    /// ```
314    /// # use std::time::Duration;
315    /// # use solana_rpc_client::rpc_client::RpcClient;
316    /// # use solana_sdk::commitment_config::CommitmentConfig;
317    /// let url = "http://localhost::8899".to_string();
318    /// let timeout = Duration::from_secs(1);
319    /// let commitment_config = CommitmentConfig::processed();
320    /// let client = RpcClient::new_with_timeout_and_commitment(
321    ///     url,
322    ///     timeout,
323    ///     commitment_config,
324    /// );
325    /// ```
326    pub fn new_with_timeout_and_commitment<U: ToString>(
327        url: U,
328        timeout: Duration,
329        commitment_config: CommitmentConfig,
330    ) -> Self {
331        Self::new_sender(
332            HttpSender::new_with_timeout(url, timeout),
333            RpcClientConfig::with_commitment(commitment_config),
334        )
335    }
336
337    /// Create an HTTP `RpcClient` with specified timeout and [commitment level][cl].
338    ///
339    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
340    ///
341    /// The URL is an HTTP URL, usually for port 8899, as in
342    /// "http://localhost:8899".
343    ///
344    /// The `confirm_transaction_initial_timeout` argument specifies the amount of
345    /// time to allow for the server to initially process a transaction, when
346    /// confirming a transaction via one of the `_with_spinner` methods, like
347    /// [`RpcClient::send_and_confirm_transaction_with_spinner`]. In
348    /// other words, setting `confirm_transaction_initial_timeout` to > 0 allows
349    /// `RpcClient` to wait for confirmation of a transaction that the server
350    /// has not "seen" yet.
351    ///
352    /// # Examples
353    ///
354    /// ```
355    /// # use std::time::Duration;
356    /// # use solana_rpc_client::rpc_client::RpcClient;
357    /// # use solana_sdk::commitment_config::CommitmentConfig;
358    /// let url = "http://localhost::8899".to_string();
359    /// let timeout = Duration::from_secs(1);
360    /// let commitment_config = CommitmentConfig::processed();
361    /// let confirm_transaction_initial_timeout = Duration::from_secs(10);
362    /// let client = RpcClient::new_with_timeouts_and_commitment(
363    ///     url,
364    ///     timeout,
365    ///     commitment_config,
366    ///     confirm_transaction_initial_timeout,
367    /// );
368    /// ```
369    pub fn new_with_timeouts_and_commitment<U: ToString>(
370        url: U,
371        timeout: Duration,
372        commitment_config: CommitmentConfig,
373        confirm_transaction_initial_timeout: Duration,
374    ) -> Self {
375        Self::new_sender(
376            HttpSender::new_with_timeout(url, timeout),
377            RpcClientConfig {
378                commitment_config,
379                confirm_transaction_initial_timeout: Some(confirm_transaction_initial_timeout),
380            },
381        )
382    }
383
384    /// Create a mock `RpcClient`.
385    ///
386    /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does
387    /// not use the network, and instead returns synthetic responses, for use in
388    /// tests.
389    ///
390    /// It is primarily for internal use, with limited customizability, and
391    /// behaviors determined by internal Solana test cases. New users should
392    /// consider implementing `RpcSender` themselves and constructing
393    /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior.
394    ///
395    /// Unless directed otherwise, a mock `RpcClient` will generally return a
396    /// reasonable default response to any request, at least for [`RpcRequest`]
397    /// values for which responses have been implemented.
398    ///
399    /// This mock can be customized by changing the `url` argument, which is not
400    /// actually a URL, but a simple string directive that changes the mock
401    /// behavior in specific scenarios:
402    ///
403    /// - It is customary to set the `url` to "succeeds" for mocks that should
404    ///   return successfully, though this value is not actually interpreted.
405    ///
406    /// - If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`.
407    ///
408    /// - Other possible values of `url` are specific to different `RpcRequest`
409    ///   values. Read the implementation of (non-public) `MockSender` for
410    ///   details.
411    ///
412    /// The [`RpcClient::new_mock_with_mocks`] function offers further
413    /// customization options.
414    ///
415    /// # Examples
416    ///
417    /// ```
418    /// # use solana_rpc_client::rpc_client::RpcClient;
419    /// // Create an `RpcClient` that always succeeds
420    /// let url = "succeeds".to_string();
421    /// let successful_client = RpcClient::new_mock(url);
422    /// ```
423    ///
424    /// ```
425    /// # use solana_rpc_client::rpc_client::RpcClient;
426    /// // Create an `RpcClient` that always fails
427    /// let url = "fails".to_string();
428    /// let successful_client = RpcClient::new_mock(url);
429    /// ```
430    pub fn new_mock<U: ToString>(url: U) -> Self {
431        Self::new_sender(
432            MockSender::new(url),
433            RpcClientConfig::with_commitment(CommitmentConfig::default()),
434        )
435    }
436
437    /// Create a mock `RpcClient`.
438    ///
439    /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does
440    /// not use the network, and instead returns synthetic responses, for use in
441    /// tests.
442    ///
443    /// It is primarily for internal use, with limited customizability, and
444    /// behaviors determined by internal Solana test cases. New users should
445    /// consider implementing `RpcSender` themselves and constructing
446    /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior.
447    ///
448    /// Unless directed otherwise, a mock `RpcClient` will generally return a
449    /// reasonable default response to any request, at least for [`RpcRequest`]
450    /// values for which responses have been implemented.
451    ///
452    /// This mock can be customized in two ways:
453    ///
454    /// 1) By changing the `url` argument, which is not actually a URL, but a
455    ///    simple string directive that changes the mock behavior in specific
456    ///    scenarios.
457    ///
458    ///    It is customary to set the `url` to "succeeds" for mocks that should
459    ///    return successfully, though this value is not actually interpreted.
460    ///
461    ///    If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`.
462    ///
463    ///    Other possible values of `url` are specific to different `RpcRequest`
464    ///    values. Read the implementation of `MockSender` (which is non-public)
465    ///    for details.
466    ///
467    /// 2) Custom responses can be configured by providing [`Mocks`]. This type
468    ///    is a [`HashMap`] from [`RpcRequest`] to a JSON [`Value`] response,
469    ///    Any entries in this map override the default behavior for the given
470    ///    request.
471    ///
472    /// The [`RpcClient::new_mock_with_mocks`] function offers further
473    /// customization options.
474    ///
475    /// [`HashMap`]: std::collections::HashMap
476    ///
477    /// # Examples
478    ///
479    /// ```
480    /// # use solana_rpc_client_api::{
481    /// #     request::RpcRequest,
482    /// #     response::{Response, RpcResponseContext},
483    /// # };
484    /// # use solana_rpc_client::rpc_client::RpcClient;
485    /// # use std::collections::HashMap;
486    /// # use serde_json::json;
487    /// // Create a mock with a custom response to the `GetBalance` request
488    /// let account_balance = 50;
489    /// let account_balance_response = json!(Response {
490    ///     context: RpcResponseContext { slot: 1, api_version: None },
491    ///     value: json!(account_balance),
492    /// });
493    ///
494    /// let mut mocks = HashMap::new();
495    /// mocks.insert(RpcRequest::GetBalance, account_balance_response);
496    /// let url = "succeeds".to_string();
497    /// let client = RpcClient::new_mock_with_mocks(url, mocks);
498    /// ```
499    pub fn new_mock_with_mocks<U: ToString>(url: U, mocks: Mocks) -> Self {
500        Self::new_sender(
501            MockSender::new_with_mocks(url, mocks),
502            RpcClientConfig::with_commitment(CommitmentConfig::default()),
503        )
504    }
505
506    /// Create an HTTP `RpcClient` from a [`SocketAddr`].
507    ///
508    /// The client has a default timeout of 30 seconds, and a default [commitment
509    /// level][cl] of [`Finalized`].
510    ///
511    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
512    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
513    ///
514    /// # Examples
515    ///
516    /// ```
517    /// # use std::net::{Ipv4Addr, SocketAddr};
518    /// # use solana_rpc_client::rpc_client::RpcClient;
519    /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 8899));
520    /// let client = RpcClient::new_socket(addr);
521    /// ```
522    pub fn new_socket(addr: SocketAddr) -> Self {
523        Self::new(get_rpc_request_str(addr, false))
524    }
525
526    /// Create an HTTP `RpcClient` from a [`SocketAddr`] with specified [commitment level][cl].
527    ///
528    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
529    ///
530    /// The client has a default timeout of 30 seconds, and a user-specified
531    /// [`CommitmentLevel`] via [`CommitmentConfig`].
532    ///
533    /// [`CommitmentLevel`]: solana_sdk::commitment_config::CommitmentLevel
534    ///
535    /// # Examples
536    ///
537    /// ```
538    /// # use std::net::{Ipv4Addr, SocketAddr};
539    /// # use solana_rpc_client::rpc_client::RpcClient;
540    /// # use solana_sdk::commitment_config::CommitmentConfig;
541    /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 8899));
542    /// let commitment_config = CommitmentConfig::processed();
543    /// let client = RpcClient::new_socket_with_commitment(
544    ///     addr,
545    ///     commitment_config
546    /// );
547    /// ```
548    pub fn new_socket_with_commitment(
549        addr: SocketAddr,
550        commitment_config: CommitmentConfig,
551    ) -> Self {
552        Self::new_with_commitment(get_rpc_request_str(addr, false), commitment_config)
553    }
554
555    /// Create an HTTP `RpcClient` from a [`SocketAddr`] with specified timeout.
556    ///
557    /// The client has a default [commitment level][cl] of [`Finalized`].
558    ///
559    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
560    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
561    ///
562    /// # Examples
563    ///
564    /// ```
565    /// # use std::net::{Ipv4Addr, SocketAddr};
566    /// # use std::time::Duration;
567    /// # use solana_rpc_client::rpc_client::RpcClient;
568    /// let addr = SocketAddr::from((Ipv4Addr::LOCALHOST, 8899));
569    /// let timeout = Duration::from_secs(1);
570    /// let client = RpcClient::new_socket_with_timeout(addr, timeout);
571    /// ```
572    pub fn new_socket_with_timeout(addr: SocketAddr, timeout: Duration) -> Self {
573        let url = get_rpc_request_str(addr, false);
574        Self::new_with_timeout(url, timeout)
575    }
576
577    /// Get the configured url of the client's sender
578    pub fn url(&self) -> String {
579        (self.rpc_client.as_ref()).url()
580    }
581
582    /// Get the configured default [commitment level][cl].
583    ///
584    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
585    ///
586    /// The commitment config may be specified during construction, and
587    /// determines how thoroughly committed a transaction must be when waiting
588    /// for its confirmation or otherwise checking for confirmation. If not
589    /// specified, the default commitment level is
590    /// [`Finalized`].
591    ///
592    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
593    ///
594    /// The default commitment level is overridden when calling methods that
595    /// explicitly provide a [`CommitmentConfig`], like
596    /// [`RpcClient::confirm_transaction_with_commitment`].
597    pub fn commitment(&self) -> CommitmentConfig {
598        (self.rpc_client.as_ref()).commitment()
599    }
600
601    /// Submit a transaction and wait for confirmation.
602    ///
603    /// Once this function returns successfully, the given transaction is
604    /// guaranteed to be processed with the configured [commitment level][cl].
605    ///
606    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
607    ///
608    /// After sending the transaction, this method polls in a loop for the
609    /// status of the transaction until it has ben confirmed.
610    ///
611    /// # Errors
612    ///
613    /// If the transaction is not signed then an error with kind [`RpcError`] is
614    /// returned, containing an [`RpcResponseError`] with `code` set to
615    /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`].
616    ///
617    /// If the preflight transaction simulation fails then an error with kind
618    /// [`RpcError`] is returned, containing an [`RpcResponseError`] with `code`
619    /// set to [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`].
620    ///
621    /// If the receiving node is unhealthy, e.g. it is not fully synced to
622    /// the cluster, then an error with kind [`RpcError`] is returned,
623    /// containing an [`RpcResponseError`] with `code` set to
624    /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`].
625    ///
626    /// [`RpcError`]: solana_rpc_client_api::request::RpcError
627    /// [`RpcResponseError`]: solana_rpc_client_api::request::RpcError::RpcResponseError
628    /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE
629    /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE
630    /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY
631    ///
632    /// # RPC Reference
633    ///
634    /// This method is built on the [`sendTransaction`] RPC method, and the
635    /// [`getLatestBlockhash`] RPC method.
636    ///
637    /// [`sendTransaction`]: https://solana.com/docs/rpc/http/sendtransaction
638    /// [`getLatestBlockhash`]: https://solana.com/docs/rpc/http/getlatestblockhash
639    ///
640    /// # Examples
641    ///
642    /// ```
643    /// # use solana_rpc_client_api::client_error::Error;
644    /// # use solana_rpc_client::rpc_client::RpcClient;
645    /// # use solana_sdk::{
646    /// #     signature::Signer,
647    /// #     signature::Signature,
648    /// #     signer::keypair::Keypair,
649    /// #     system_transaction,
650    /// # };
651    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
652    /// # let alice = Keypair::new();
653    /// # let bob = Keypair::new();
654    /// # let lamports = 50;
655    /// # let latest_blockhash = rpc_client.get_latest_blockhash()?;
656    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
657    /// let signature = rpc_client.send_and_confirm_transaction(&tx)?;
658    /// # Ok::<(), Error>(())
659    /// ```
660    pub fn send_and_confirm_transaction(
661        &self,
662        transaction: &impl SerializableTransaction,
663    ) -> ClientResult<Signature> {
664        self.invoke((self.rpc_client.as_ref()).send_and_confirm_transaction(transaction))
665    }
666
667    #[cfg(feature = "spinner")]
668    pub fn send_and_confirm_transaction_with_spinner(
669        &self,
670        transaction: &impl SerializableTransaction,
671    ) -> ClientResult<Signature> {
672        self.invoke(
673            (self.rpc_client.as_ref()).send_and_confirm_transaction_with_spinner(transaction),
674        )
675    }
676
677    #[cfg(feature = "spinner")]
678    pub fn send_and_confirm_transaction_with_spinner_and_commitment(
679        &self,
680        transaction: &impl SerializableTransaction,
681        commitment: CommitmentConfig,
682    ) -> ClientResult<Signature> {
683        self.invoke(
684            (self.rpc_client.as_ref())
685                .send_and_confirm_transaction_with_spinner_and_commitment(transaction, commitment),
686        )
687    }
688
689    #[cfg(feature = "spinner")]
690    pub fn send_and_confirm_transaction_with_spinner_and_config(
691        &self,
692        transaction: &impl SerializableTransaction,
693        commitment: CommitmentConfig,
694        config: RpcSendTransactionConfig,
695    ) -> ClientResult<Signature> {
696        self.invoke(
697            (self.rpc_client.as_ref()).send_and_confirm_transaction_with_spinner_and_config(
698                transaction,
699                commitment,
700                config,
701            ),
702        )
703    }
704
705    /// Submits a signed transaction to the network.
706    ///
707    /// Before a transaction is processed, the receiving node runs a "preflight
708    /// check" which verifies signatures, checks that the node is healthy,
709    /// and simulates the transaction. If the preflight check fails then an
710    /// error is returned immediately. Preflight checks can be disabled by
711    /// calling [`send_transaction_with_config`] and setting the
712    /// [`skip_preflight`] field of [`RpcSendTransactionConfig`] to `true`.
713    ///
714    /// This method does not wait for the transaction to be processed or
715    /// confirmed before returning successfully. To wait for the transaction to
716    /// be processed or confirmed, use the [`send_and_confirm_transaction`]
717    /// method.
718    ///
719    /// [`send_transaction_with_config`]: RpcClient::send_transaction_with_config
720    /// [`skip_preflight`]: solana_rpc_client_api::config::RpcSendTransactionConfig::skip_preflight
721    /// [`RpcSendTransactionConfig`]: solana_rpc_client_api::config::RpcSendTransactionConfig
722    /// [`send_and_confirm_transaction`]: RpcClient::send_and_confirm_transaction
723    ///
724    /// # Errors
725    ///
726    /// If the transaction is not signed then an error with kind [`RpcError`] is
727    /// returned, containing an [`RpcResponseError`] with `code` set to
728    /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`].
729    ///
730    /// If the preflight transaction simulation fails then an error with kind
731    /// [`RpcError`] is returned, containing an [`RpcResponseError`] with `code`
732    /// set to [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`].
733    ///
734    /// If the receiving node is unhealthy, e.g. it is not fully synced to
735    /// the cluster, then an error with kind [`RpcError`] is returned,
736    /// containing an [`RpcResponseError`] with `code` set to
737    /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`].
738    ///
739    /// [`RpcError`]: solana_rpc_client_api::request::RpcError
740    /// [`RpcResponseError`]: solana_rpc_client_api::request::RpcError::RpcResponseError
741    /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE
742    /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE
743    /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY
744    ///
745    /// # RPC Reference
746    ///
747    /// This method is built on the [`sendTransaction`] RPC method.
748    ///
749    /// [`sendTransaction`]: https://solana.com/docs/rpc/http/sendtransaction
750    ///
751    /// # Examples
752    ///
753    /// ```
754    /// # use solana_rpc_client_api::client_error::Error;
755    /// # use solana_rpc_client::rpc_client::RpcClient;
756    /// # use solana_sdk::{
757    /// #     signature::Signer,
758    /// #     signature::Signature,
759    /// #     signer::keypair::Keypair,
760    /// #     hash::Hash,
761    /// #     system_transaction,
762    /// # };
763    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
764    /// // Transfer lamports from Alice to Bob
765    /// # let alice = Keypair::new();
766    /// # let bob = Keypair::new();
767    /// # let lamports = 50;
768    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
769    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
770    /// let signature = rpc_client.send_transaction(&tx)?;
771    /// # Ok::<(), Error>(())
772    /// ```
773    pub fn send_transaction(
774        &self,
775        transaction: &impl SerializableTransaction,
776    ) -> ClientResult<Signature> {
777        self.invoke((self.rpc_client.as_ref()).send_transaction(transaction))
778    }
779
780    /// Submits a signed transaction to the network.
781    ///
782    /// Before a transaction is processed, the receiving node runs a "preflight
783    /// check" which verifies signatures, checks that the node is healthy, and
784    /// simulates the transaction. If the preflight check fails then an error is
785    /// returned immediately. Preflight checks can be disabled by setting the
786    /// [`skip_preflight`] field of [`RpcSendTransactionConfig`] to `true`.
787    ///
788    /// This method does not wait for the transaction to be processed or
789    /// confirmed before returning successfully. To wait for the transaction to
790    /// be processed or confirmed, use the [`send_and_confirm_transaction`]
791    /// method.
792    ///
793    /// [`send_transaction_with_config`]: RpcClient::send_transaction_with_config
794    /// [`skip_preflight`]: solana_rpc_client_api::config::RpcSendTransactionConfig::skip_preflight
795    /// [`RpcSendTransactionConfig`]: solana_rpc_client_api::config::RpcSendTransactionConfig
796    /// [`send_and_confirm_transaction`]: RpcClient::send_and_confirm_transaction
797    ///
798    /// # Errors
799    ///
800    /// If preflight checks are enabled, if the transaction is not signed
801    /// then an error with kind [`RpcError`] is returned, containing an
802    /// [`RpcResponseError`] with `code` set to
803    /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`].
804    ///
805    /// If preflight checks are enabled, if the preflight transaction simulation
806    /// fails then an error with kind [`RpcError`] is returned, containing an
807    /// [`RpcResponseError`] with `code` set to
808    /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`].
809    ///
810    /// If the receiving node is unhealthy, e.g. it is not fully synced to
811    /// the cluster, then an error with kind [`RpcError`] is returned,
812    /// containing an [`RpcResponseError`] with `code` set to
813    /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`].
814    ///
815    /// [`RpcError`]: solana_rpc_client_api::request::RpcError
816    /// [`RpcResponseError`]: solana_rpc_client_api::request::RpcError::RpcResponseError
817    /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE
818    /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE
819    /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: solana_rpc_client_api::custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY
820    ///
821    /// # RPC Reference
822    ///
823    /// This method is built on the [`sendTransaction`] RPC method.
824    ///
825    /// [`sendTransaction`]: https://solana.com/docs/rpc/http/sendtransaction
826    ///
827    /// # Examples
828    ///
829    /// ```
830    /// # use solana_rpc_client_api::{
831    /// #     client_error::Error,
832    /// #     config::RpcSendTransactionConfig,
833    /// # };
834    /// # use solana_rpc_client::rpc_client::RpcClient;
835    /// # use solana_sdk::{
836    /// #     signature::Signer,
837    /// #     signature::Signature,
838    /// #     signer::keypair::Keypair,
839    /// #     hash::Hash,
840    /// #     system_transaction,
841    /// # };
842    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
843    /// // Transfer lamports from Alice to Bob
844    /// # let alice = Keypair::new();
845    /// # let bob = Keypair::new();
846    /// # let lamports = 50;
847    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
848    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
849    /// let config = RpcSendTransactionConfig {
850    ///     skip_preflight: true,
851    ///     .. RpcSendTransactionConfig::default()
852    /// };
853    /// let signature = rpc_client.send_transaction_with_config(
854    ///     &tx,
855    ///     config,
856    /// )?;
857    /// # Ok::<(), Error>(())
858    /// ```
859    pub fn send_transaction_with_config(
860        &self,
861        transaction: &impl SerializableTransaction,
862        config: RpcSendTransactionConfig,
863    ) -> ClientResult<Signature> {
864        self.invoke((self.rpc_client.as_ref()).send_transaction_with_config(transaction, config))
865    }
866
867    pub fn send<T>(&self, request: RpcRequest, params: Value) -> ClientResult<T>
868    where
869        T: serde::de::DeserializeOwned,
870    {
871        self.invoke((self.rpc_client.as_ref()).send(request, params))
872    }
873
874    /// Check the confirmation status of a transaction.
875    ///
876    /// Returns `true` if the given transaction succeeded and has been committed
877    /// with the configured [commitment level][cl], which can be retrieved with
878    /// the [`commitment`](RpcClient::commitment) method.
879    ///
880    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
881    ///
882    /// Note that this method does not wait for a transaction to be confirmed
883    /// &mdash; it only checks whether a transaction has been confirmed. To
884    /// submit a transaction and wait for it to confirm, use
885    /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
886    ///
887    /// _This method returns `false` if the transaction failed, even if it has
888    /// been confirmed._
889    ///
890    /// # RPC Reference
891    ///
892    /// This method is built on the [`getSignatureStatuses`] RPC method.
893    ///
894    /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses
895    ///
896    /// # Examples
897    ///
898    /// ```
899    /// # use solana_rpc_client_api::client_error::Error;
900    /// # use solana_rpc_client::rpc_client::RpcClient;
901    /// # use solana_sdk::{
902    /// #     signature::Signer,
903    /// #     signature::Signature,
904    /// #     signer::keypair::Keypair,
905    /// #     system_transaction,
906    /// # };
907    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
908    /// // Transfer lamports from Alice to Bob and wait for confirmation
909    /// # let alice = Keypair::new();
910    /// # let bob = Keypair::new();
911    /// # let lamports = 50;
912    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
913    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
914    /// let signature = rpc_client.send_transaction(&tx)?;
915    ///
916    /// loop {
917    ///     let confirmed = rpc_client.confirm_transaction(&signature)?;
918    ///     if confirmed {
919    ///         break;
920    ///     }
921    /// }
922    /// # Ok::<(), Error>(())
923    /// ```
924    pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult<bool> {
925        self.invoke((self.rpc_client.as_ref()).confirm_transaction(signature))
926    }
927
928    /// Check the confirmation status of a transaction.
929    ///
930    /// Returns an [`RpcResult`] with value `true` if the given transaction
931    /// succeeded and has been committed with the given [commitment level][cl].
932    ///
933    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
934    ///
935    /// Note that this method does not wait for a transaction to be confirmed
936    /// &mdash; it only checks whether a transaction has been confirmed. To
937    /// submit a transaction and wait for it to confirm, use
938    /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
939    ///
940    /// _This method returns an [`RpcResult`] with value `false` if the
941    /// transaction failed, even if it has been confirmed._
942    ///
943    /// # RPC Reference
944    ///
945    /// This method is built on the [`getSignatureStatuses`] RPC method.
946    ///
947    /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses
948    ///
949    /// # Examples
950    ///
951    /// ```
952    /// # use solana_rpc_client_api::client_error::Error;
953    /// # use solana_rpc_client::rpc_client::RpcClient;
954    /// # use solana_sdk::{
955    /// #     commitment_config::CommitmentConfig,
956    /// #     signature::Signer,
957    /// #     signature::Signature,
958    /// #     signer::keypair::Keypair,
959    /// #     system_transaction,
960    /// # };
961    /// # use std::time::Duration;
962    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
963    /// // Transfer lamports from Alice to Bob and wait for confirmation
964    /// # let alice = Keypair::new();
965    /// # let bob = Keypair::new();
966    /// # let lamports = 50;
967    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
968    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
969    /// let signature = rpc_client.send_transaction(&tx)?;
970    ///
971    /// loop {
972    ///     let commitment_config = CommitmentConfig::processed();
973    ///     let confirmed = rpc_client.confirm_transaction_with_commitment(&signature, commitment_config)?;
974    ///     if confirmed.value {
975    ///         break;
976    ///     }
977    /// }
978    /// # Ok::<(), Error>(())
979    /// ```
980    pub fn confirm_transaction_with_commitment(
981        &self,
982        signature: &Signature,
983        commitment_config: CommitmentConfig,
984    ) -> RpcResult<bool> {
985        self.invoke(
986            (self.rpc_client.as_ref())
987                .confirm_transaction_with_commitment(signature, commitment_config),
988        )
989    }
990
991    #[cfg(feature = "spinner")]
992    pub fn confirm_transaction_with_spinner(
993        &self,
994        signature: &Signature,
995        recent_blockhash: &Hash,
996        commitment_config: CommitmentConfig,
997    ) -> ClientResult<()> {
998        self.invoke((self.rpc_client.as_ref()).confirm_transaction_with_spinner(
999            signature,
1000            recent_blockhash,
1001            commitment_config,
1002        ))
1003    }
1004
1005    /// Simulates sending a transaction.
1006    ///
1007    /// If the transaction fails, then the [`err`] field of the returned
1008    /// [`RpcSimulateTransactionResult`] will be `Some`. Any logs emitted from
1009    /// the transaction are returned in the [`logs`] field.
1010    ///
1011    /// [`err`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::err
1012    /// [`logs`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::logs
1013    ///
1014    /// Simulating a transaction is similar to the ["preflight check"] that is
1015    /// run by default when sending a transaction.
1016    ///
1017    /// ["preflight check"]: https://solana.com/docs/rpc/http/sendtransaction
1018    ///
1019    /// By default, signatures are not verified during simulation. To verify
1020    /// signatures, call the [`simulate_transaction_with_config`] method, with
1021    /// the [`sig_verify`] field of [`RpcSimulateTransactionConfig`] set to
1022    /// `true`.
1023    ///
1024    /// [`simulate_transaction_with_config`]: RpcClient::simulate_transaction_with_config
1025    /// [`sig_verify`]: solana_rpc_client_api::config::RpcSimulateTransactionConfig::sig_verify
1026    ///
1027    /// # RPC Reference
1028    ///
1029    /// This method is built on the [`simulateTransaction`] RPC method.
1030    ///
1031    /// [`simulateTransaction`]: https://solana.com/docs/rpc/http/simulatetransaction
1032    ///
1033    /// # Examples
1034    ///
1035    /// ```
1036    /// # use solana_rpc_client_api::{
1037    /// #     client_error::Error,
1038    /// #     response::RpcSimulateTransactionResult,
1039    /// # };
1040    /// # use solana_rpc_client::rpc_client::RpcClient;
1041    /// # use solana_sdk::{
1042    /// #     signature::Signer,
1043    /// #     signature::Signature,
1044    /// #     signer::keypair::Keypair,
1045    /// #     hash::Hash,
1046    /// #     system_transaction,
1047    /// # };
1048    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1049    /// // Transfer lamports from Alice to Bob
1050    /// # let alice = Keypair::new();
1051    /// # let bob = Keypair::new();
1052    /// # let lamports = 50;
1053    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
1054    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
1055    /// let result = rpc_client.simulate_transaction(&tx)?;
1056    /// assert!(result.value.err.is_none());
1057    /// # Ok::<(), Error>(())
1058    /// ```
1059    pub fn simulate_transaction(
1060        &self,
1061        transaction: &impl SerializableTransaction,
1062    ) -> RpcResult<RpcSimulateTransactionResult> {
1063        self.invoke((self.rpc_client.as_ref()).simulate_transaction(transaction))
1064    }
1065
1066    /// Simulates sending a transaction.
1067    ///
1068    /// If the transaction fails, then the [`err`] field of the returned
1069    /// [`RpcSimulateTransactionResult`] will be `Some`. Any logs emitted from
1070    /// the transaction are returned in the [`logs`] field.
1071    ///
1072    /// [`err`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::err
1073    /// [`logs`]: solana_rpc_client_api::response::RpcSimulateTransactionResult::logs
1074    ///
1075    /// Simulating a transaction is similar to the ["preflight check"] that is
1076    /// run by default when sending a transaction.
1077    ///
1078    /// ["preflight check"]: https://solana.com/docs/rpc/http/sendtransaction
1079    ///
1080    /// By default, signatures are not verified during simulation. To verify
1081    /// signatures, call the [`simulate_transaction_with_config`] method, with
1082    /// the [`sig_verify`] field of [`RpcSimulateTransactionConfig`] set to
1083    /// `true`.
1084    ///
1085    /// [`simulate_transaction_with_config`]: RpcClient::simulate_transaction_with_config
1086    /// [`sig_verify`]: solana_rpc_client_api::config::RpcSimulateTransactionConfig::sig_verify
1087    ///
1088    /// This method can additionally query information about accounts by
1089    /// including them in the [`accounts`] field of the
1090    /// [`RpcSimulateTransactionConfig`] argument, in which case those results
1091    /// are reported in the [`accounts`][accounts2] field of the returned
1092    /// [`RpcSimulateTransactionResult`].
1093    ///
1094    /// [`accounts`]: solana_rpc_client_api::config::RpcSimulateTransactionConfig::accounts
1095    /// [accounts2]: solana_rpc_client_api::response::RpcSimulateTransactionResult::accounts
1096    ///
1097    /// # RPC Reference
1098    ///
1099    /// This method is built on the [`simulateTransaction`] RPC method.
1100    ///
1101    /// [`simulateTransaction`]: https://solana.com/docs/rpc/http/simulatetransaction
1102    ///
1103    /// # Examples
1104    ///
1105    /// ```
1106    /// # use solana_rpc_client_api::{
1107    /// #     client_error::Error,
1108    /// #     config::RpcSimulateTransactionConfig,
1109    /// #     response::RpcSimulateTransactionResult,
1110    /// # };
1111    /// # use solana_rpc_client::rpc_client::RpcClient;
1112    /// # use solana_sdk::{
1113    /// #     signature::Signer,
1114    /// #     signer::keypair::Keypair,
1115    /// #     hash::Hash,
1116    /// #     system_transaction,
1117    /// # };
1118    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1119    /// // Transfer lamports from Alice to Bob
1120    /// # let alice = Keypair::new();
1121    /// # let bob = Keypair::new();
1122    /// # let lamports = 50;
1123    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
1124    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
1125    /// let config = RpcSimulateTransactionConfig {
1126    ///     sig_verify: true,
1127    ///     .. RpcSimulateTransactionConfig::default()
1128    /// };
1129    /// let result = rpc_client.simulate_transaction_with_config(
1130    ///     &tx,
1131    ///     config,
1132    /// )?;
1133    /// assert!(result.value.err.is_none());
1134    /// # Ok::<(), Error>(())
1135    /// ```
1136    pub fn simulate_transaction_with_config(
1137        &self,
1138        transaction: &impl SerializableTransaction,
1139        config: RpcSimulateTransactionConfig,
1140    ) -> RpcResult<RpcSimulateTransactionResult> {
1141        self.invoke(
1142            (self.rpc_client.as_ref()).simulate_transaction_with_config(transaction, config),
1143        )
1144    }
1145
1146    /// Returns the highest slot information that the node has snapshots for.
1147    ///
1148    /// This will find the highest full snapshot slot, and the highest incremental snapshot slot
1149    /// _based on_ the full snapshot slot, if there is one.
1150    ///
1151    /// # RPC Reference
1152    ///
1153    /// This method corresponds directly to the [`getHighestSnapshotSlot`] RPC method.
1154    ///
1155    /// [`getHighestSnapshotSlot`]: https://solana.com/docs/rpc/http/gethighestsnapshotslot
1156    ///
1157    /// # Examples
1158    ///
1159    /// ```
1160    /// # use solana_rpc_client_api::client_error::Error;
1161    /// # use solana_rpc_client::rpc_client::RpcClient;
1162    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1163    /// let snapshot_slot_info = rpc_client.get_highest_snapshot_slot()?;
1164    /// # Ok::<(), Error>(())
1165    /// ```
1166    pub fn get_highest_snapshot_slot(&self) -> ClientResult<RpcSnapshotSlotInfo> {
1167        self.invoke((self.rpc_client.as_ref()).get_highest_snapshot_slot())
1168    }
1169
1170    /// Check if a transaction has been processed with the default [commitment level][cl].
1171    ///
1172    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1173    ///
1174    /// If the transaction has been processed with the default commitment level,
1175    /// then this method returns `Ok` of `Some`. If the transaction has not yet
1176    /// been processed with the default commitment level, it returns `Ok` of
1177    /// `None`.
1178    ///
1179    /// If the transaction has been processed with the default commitment level,
1180    /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`.
1181    /// If the transaction has been processed with the default commitment level,
1182    /// and the transaction failed, this method returns `Ok(Some(Err(_)))`,
1183    /// where the interior error is type [`TransactionError`].
1184    ///
1185    /// [`TransactionError`]: solana_sdk::transaction::TransactionError
1186    ///
1187    /// This function only searches a node's recent history, including all
1188    /// recent slots, plus up to
1189    /// [`MAX_RECENT_BLOCKHASHES`][solana_sdk::clock::MAX_RECENT_BLOCKHASHES]
1190    /// rooted slots. To search the full transaction history use the
1191    /// [`get_signature_status_with_commitment_and_history`][RpcClient::get_signature_status_with_commitment_and_history]
1192    /// method.
1193    ///
1194    /// # RPC Reference
1195    ///
1196    /// This method is built on the [`getSignatureStatuses`] RPC method.
1197    ///
1198    /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses
1199    ///
1200    /// # Examples
1201    ///
1202    /// ```
1203    /// # use solana_rpc_client_api::client_error::Error;
1204    /// # use solana_rpc_client::rpc_client::RpcClient;
1205    /// # use solana_sdk::{
1206    /// #     signature::Signer,
1207    /// #     signature::Signature,
1208    /// #     signer::keypair::Keypair,
1209    /// #     hash::Hash,
1210    /// #     system_transaction,
1211    /// # };
1212    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1213    /// # let alice = Keypair::new();
1214    /// # let bob = Keypair::new();
1215    /// # let lamports = 50;
1216    /// # let latest_blockhash = rpc_client.get_latest_blockhash()?;
1217    /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
1218    /// let signature = rpc_client.send_transaction(&tx)?;
1219    /// let status = rpc_client.get_signature_status(&signature)?;
1220    /// # Ok::<(), Error>(())
1221    /// ```
1222    pub fn get_signature_status(
1223        &self,
1224        signature: &Signature,
1225    ) -> ClientResult<Option<transaction::Result<()>>> {
1226        self.invoke((self.rpc_client.as_ref()).get_signature_status(signature))
1227    }
1228
1229    /// Gets the statuses of a list of transaction signatures.
1230    ///
1231    /// The returned vector of [`TransactionStatus`] has the same length as the
1232    /// input slice.
1233    ///
1234    /// For any transaction that has not been processed by the network, the
1235    /// value of the corresponding entry in the returned vector is `None`. As a
1236    /// result, a transaction that has recently been submitted will not have a
1237    /// status immediately.
1238    ///
1239    /// To submit a transaction and wait for it to confirm, use
1240    /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
1241    ///
1242    /// This function ignores the configured confirmation level, and returns the
1243    /// transaction status whatever it is. It does not wait for transactions to
1244    /// be processed.
1245    ///
1246    /// This function only searches a node's recent history, including all
1247    /// recent slots, plus up to
1248    /// [`MAX_RECENT_BLOCKHASHES`][solana_sdk::clock::MAX_RECENT_BLOCKHASHES]
1249    /// rooted slots. To search the full transaction history use the
1250    /// [`get_signature_statuses_with_history`][RpcClient::get_signature_statuses_with_history]
1251    /// method.
1252    ///
1253    /// # Errors
1254    ///
1255    /// Any individual `TransactionStatus` may have triggered an error during
1256    /// processing, in which case its [`err`][`TransactionStatus::err`] field
1257    /// will be `Some`.
1258    ///
1259    /// # RPC Reference
1260    ///
1261    /// This method corresponds directly to the [`getSignatureStatuses`] RPC method.
1262    ///
1263    /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses
1264    ///
1265    /// # Examples
1266    ///
1267    /// ```
1268    /// # use solana_rpc_client_api::client_error::Error;
1269    /// # use solana_rpc_client::rpc_client::RpcClient;
1270    /// # use solana_sdk::{
1271    /// #     signature::Signer,
1272    /// #     signature::Signature,
1273    /// #     signer::keypair::Keypair,
1274    /// #     hash::Hash,
1275    /// #     system_transaction,
1276    /// # };
1277    /// # use std::time::Duration;
1278    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1279    /// # let alice = Keypair::new();
1280    /// // Send lamports from Alice to Bob and wait for the transaction to be processed
1281    /// # let bob = Keypair::new();
1282    /// # let lamports = 50;
1283    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
1284    /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
1285    /// let signature = rpc_client.send_transaction(&tx)?;
1286    ///
1287    /// let status = loop {
1288    ///    let statuses = rpc_client.get_signature_statuses(&[signature])?.value;
1289    ///    if let Some(status) = statuses[0].clone() {
1290    ///        break status;
1291    ///    }
1292    ///    std::thread::sleep(Duration::from_millis(100));
1293    /// };
1294    ///
1295    /// assert!(status.err.is_none());
1296    /// # Ok::<(), Error>(())
1297    /// ```
1298    pub fn get_signature_statuses(
1299        &self,
1300        signatures: &[Signature],
1301    ) -> RpcResult<Vec<Option<TransactionStatus>>> {
1302        self.invoke((self.rpc_client.as_ref()).get_signature_statuses(signatures))
1303    }
1304
1305    /// Gets the statuses of a list of transaction signatures.
1306    ///
1307    /// The returned vector of [`TransactionStatus`] has the same length as the
1308    /// input slice.
1309    ///
1310    /// For any transaction that has not been processed by the network, the
1311    /// value of the corresponding entry in the returned vector is `None`. As a
1312    /// result, a transaction that has recently been submitted will not have a
1313    /// status immediately.
1314    ///
1315    /// To submit a transaction and wait for it to confirm, use
1316    /// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
1317    ///
1318    /// This function ignores the configured confirmation level, and returns the
1319    /// transaction status whatever it is. It does not wait for transactions to
1320    /// be processed.
1321    ///
1322    /// This function searches a node's full ledger history and (if implemented) long-term storage. To search for
1323    /// transactions in recent slots only use the
1324    /// [`get_signature_statuses`][RpcClient::get_signature_statuses] method.
1325    ///
1326    /// # Errors
1327    ///
1328    /// Any individual `TransactionStatus` may have triggered an error during
1329    /// processing, in which case its [`err`][`TransactionStatus::err`] field
1330    /// will be `Some`.
1331    ///
1332    /// # RPC Reference
1333    ///
1334    /// This method corresponds directly to the [`getSignatureStatuses`] RPC
1335    /// method, with the `searchTransactionHistory` configuration option set to
1336    /// `true`.
1337    ///
1338    /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses
1339    ///
1340    /// # Examples
1341    ///
1342    /// ```
1343    /// # use solana_rpc_client_api::client_error::Error;
1344    /// # use solana_rpc_client::rpc_client::RpcClient;
1345    /// # use solana_sdk::{
1346    /// #     signature::Signer,
1347    /// #     signature::Signature,
1348    /// #     signer::keypair::Keypair,
1349    /// #     hash::Hash,
1350    /// #     system_transaction,
1351    /// # };
1352    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1353    /// # let alice = Keypair::new();
1354    /// # fn get_old_transaction_signature() -> Signature { Signature::default() }
1355    /// // Check if an old transaction exists
1356    /// let signature = get_old_transaction_signature();
1357    /// let latest_blockhash = rpc_client.get_latest_blockhash()?;
1358    /// let statuses = rpc_client.get_signature_statuses_with_history(&[signature])?.value;
1359    /// if statuses[0].is_none() {
1360    ///     println!("old transaction does not exist");
1361    /// }
1362    /// # Ok::<(), Error>(())
1363    /// ```
1364    pub fn get_signature_statuses_with_history(
1365        &self,
1366        signatures: &[Signature],
1367    ) -> RpcResult<Vec<Option<TransactionStatus>>> {
1368        self.invoke((self.rpc_client.as_ref()).get_signature_statuses_with_history(signatures))
1369    }
1370
1371    /// Check if a transaction has been processed with the given [commitment level][cl].
1372    ///
1373    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1374    ///
1375    /// If the transaction has been processed with the given commitment level,
1376    /// then this method returns `Ok` of `Some`. If the transaction has not yet
1377    /// been processed with the given commitment level, it returns `Ok` of
1378    /// `None`.
1379    ///
1380    /// If the transaction has been processed with the given commitment level,
1381    /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`.
1382    /// If the transaction has been processed with the given commitment level,
1383    /// and the transaction failed, this method returns `Ok(Some(Err(_)))`,
1384    /// where the interior error is type [`TransactionError`].
1385    ///
1386    /// [`TransactionError`]: solana_sdk::transaction::TransactionError
1387    ///
1388    /// This function only searches a node's recent history, including all
1389    /// recent slots, plus up to
1390    /// [`MAX_RECENT_BLOCKHASHES`][solana_sdk::clock::MAX_RECENT_BLOCKHASHES]
1391    /// rooted slots. To search the full transaction history use the
1392    /// [`get_signature_status_with_commitment_and_history`][RpcClient::get_signature_status_with_commitment_and_history]
1393    /// method.
1394    ///
1395    /// # RPC Reference
1396    ///
1397    /// This method is built on the [`getSignatureStatuses`] RPC method.
1398    ///
1399    /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses
1400    ///
1401    /// # Examples
1402    ///
1403    /// ```
1404    /// # use solana_rpc_client_api::client_error::Error;
1405    /// # use solana_rpc_client::rpc_client::RpcClient;
1406    /// # use solana_sdk::{
1407    /// #     commitment_config::CommitmentConfig,
1408    /// #     signature::Signer,
1409    /// #     signature::Signature,
1410    /// #     signer::keypair::Keypair,
1411    /// #     system_transaction,
1412    /// # };
1413    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1414    /// # let alice = Keypair::new();
1415    /// # let bob = Keypair::new();
1416    /// # let lamports = 50;
1417    /// # let latest_blockhash = rpc_client.get_latest_blockhash()?;
1418    /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
1419    /// let signature = rpc_client.send_and_confirm_transaction(&tx)?;
1420    /// let commitment_config = CommitmentConfig::processed();
1421    /// let status = rpc_client.get_signature_status_with_commitment(
1422    ///     &signature,
1423    ///     commitment_config,
1424    /// )?;
1425    /// # Ok::<(), Error>(())
1426    /// ```
1427    pub fn get_signature_status_with_commitment(
1428        &self,
1429        signature: &Signature,
1430        commitment_config: CommitmentConfig,
1431    ) -> ClientResult<Option<transaction::Result<()>>> {
1432        self.invoke(
1433            (self.rpc_client.as_ref())
1434                .get_signature_status_with_commitment(signature, commitment_config),
1435        )
1436    }
1437
1438    /// Check if a transaction has been processed with the given [commitment level][cl].
1439    ///
1440    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1441    ///
1442    /// If the transaction has been processed with the given commitment level,
1443    /// then this method returns `Ok` of `Some`. If the transaction has not yet
1444    /// been processed with the given commitment level, it returns `Ok` of
1445    /// `None`.
1446    ///
1447    /// If the transaction has been processed with the given commitment level,
1448    /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`.
1449    /// If the transaction has been processed with the given commitment level,
1450    /// and the transaction failed, this method returns `Ok(Some(Err(_)))`,
1451    /// where the interior error is type [`TransactionError`].
1452    ///
1453    /// [`TransactionError`]: solana_sdk::transaction::TransactionError
1454    ///
1455    /// This method optionally searches a node's full ledger history and (if
1456    /// implemented) long-term storage.
1457    ///
1458    /// # RPC Reference
1459    ///
1460    /// This method is built on the [`getSignatureStatuses`] RPC method.
1461    ///
1462    /// [`getSignatureStatuses`]: https://solana.com/docs/rpc/http/getsignaturestatuses
1463    ///
1464    /// # Examples
1465    ///
1466    /// ```
1467    /// # use solana_rpc_client_api::client_error::Error;
1468    /// # use solana_rpc_client::rpc_client::RpcClient;
1469    /// # use solana_sdk::{
1470    /// #     commitment_config::CommitmentConfig,
1471    /// #     signature::Signer,
1472    /// #     signature::Signature,
1473    /// #     signer::keypair::Keypair,
1474    /// #     system_transaction,
1475    /// # };
1476    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1477    /// # let alice = Keypair::new();
1478    /// # let bob = Keypair::new();
1479    /// # let lamports = 50;
1480    /// # let latest_blockhash = rpc_client.get_latest_blockhash()?;
1481    /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
1482    /// let signature = rpc_client.send_transaction(&tx)?;
1483    /// let commitment_config = CommitmentConfig::processed();
1484    /// let search_transaction_history = true;
1485    /// let status = rpc_client.get_signature_status_with_commitment_and_history(
1486    ///     &signature,
1487    ///     commitment_config,
1488    ///     search_transaction_history,
1489    /// )?;
1490    /// # Ok::<(), Error>(())
1491    /// ```
1492    pub fn get_signature_status_with_commitment_and_history(
1493        &self,
1494        signature: &Signature,
1495        commitment_config: CommitmentConfig,
1496        search_transaction_history: bool,
1497    ) -> ClientResult<Option<transaction::Result<()>>> {
1498        self.invoke(
1499            (self.rpc_client.as_ref()).get_signature_status_with_commitment_and_history(
1500                signature,
1501                commitment_config,
1502                search_transaction_history,
1503            ),
1504        )
1505    }
1506
1507    /// Returns the slot that has reached the configured [commitment level][cl].
1508    ///
1509    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1510    ///
1511    /// # RPC Reference
1512    ///
1513    /// This method corresponds directly to the [`getSlot`] RPC method.
1514    ///
1515    /// [`getSlot`]: https://solana.com/docs/rpc/http/getslot
1516    ///
1517    /// # Examples
1518    ///
1519    /// ```
1520    /// # use solana_rpc_client_api::client_error::Error;
1521    /// # use solana_rpc_client::rpc_client::RpcClient;
1522    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1523    /// let slot = rpc_client.get_slot()?;
1524    /// # Ok::<(), Error>(())
1525    /// ```
1526    pub fn get_slot(&self) -> ClientResult<Slot> {
1527        self.invoke((self.rpc_client.as_ref()).get_slot())
1528    }
1529
1530    /// Returns the slot that has reached the given [commitment level][cl].
1531    ///
1532    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1533    ///
1534    /// # RPC Reference
1535    ///
1536    /// This method corresponds directly to the [`getSlot`] RPC method.
1537    ///
1538    /// [`getSlot`]: https://solana.com/docs/rpc/http/getslot
1539    ///
1540    /// # Examples
1541    ///
1542    /// ```
1543    /// # use solana_rpc_client_api::client_error::Error;
1544    /// # use solana_rpc_client::rpc_client::RpcClient;
1545    /// # use solana_sdk::commitment_config::CommitmentConfig;
1546    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1547    /// let commitment_config = CommitmentConfig::processed();
1548    /// let slot = rpc_client.get_slot_with_commitment(commitment_config)?;
1549    /// # Ok::<(), Error>(())
1550    /// ```
1551    pub fn get_slot_with_commitment(
1552        &self,
1553        commitment_config: CommitmentConfig,
1554    ) -> ClientResult<Slot> {
1555        self.invoke((self.rpc_client.as_ref()).get_slot_with_commitment(commitment_config))
1556    }
1557
1558    /// Returns the block height that has reached the configured [commitment level][cl].
1559    ///
1560    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1561    ///
1562    /// # RPC Reference
1563    ///
1564    /// This method is corresponds directly to the [`getBlockHeight`] RPC method.
1565    ///
1566    /// [`getBlockHeight`]: https://solana.com/docs/rpc/http/getblockheight
1567    ///
1568    /// # Examples
1569    ///
1570    /// ```
1571    /// # use solana_rpc_client_api::client_error::Error;
1572    /// # use solana_rpc_client::rpc_client::RpcClient;
1573    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1574    /// let block_height = rpc_client.get_block_height()?;
1575    /// # Ok::<(), Error>(())
1576    /// ```
1577    pub fn get_block_height(&self) -> ClientResult<u64> {
1578        self.invoke((self.rpc_client.as_ref()).get_block_height())
1579    }
1580
1581    /// Returns the block height that has reached the given [commitment level][cl].
1582    ///
1583    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1584    ///
1585    /// # RPC Reference
1586    ///
1587    /// This method is corresponds directly to the [`getBlockHeight`] RPC method.
1588    ///
1589    /// [`getBlockHeight`]: https://solana.com/docs/rpc/http/getblockheight
1590    ///
1591    /// # Examples
1592    ///
1593    /// ```
1594    /// # use solana_rpc_client_api::client_error::Error;
1595    /// # use solana_rpc_client::rpc_client::RpcClient;
1596    /// # use solana_sdk::commitment_config::CommitmentConfig;
1597    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1598    /// let commitment_config = CommitmentConfig::processed();
1599    /// let block_height = rpc_client.get_block_height_with_commitment(
1600    ///     commitment_config,
1601    /// )?;
1602    /// # Ok::<(), Error>(())
1603    /// ```
1604    pub fn get_block_height_with_commitment(
1605        &self,
1606        commitment_config: CommitmentConfig,
1607    ) -> ClientResult<u64> {
1608        self.invoke((self.rpc_client.as_ref()).get_block_height_with_commitment(commitment_config))
1609    }
1610
1611    /// Returns the slot leaders for a given slot range.
1612    ///
1613    /// # RPC Reference
1614    ///
1615    /// This method corresponds directly to the [`getSlotLeaders`] RPC method.
1616    ///
1617    /// [`getSlotLeaders`]: https://solana.com/docs/rpc/http/getslotleaders
1618    ///
1619    /// # Examples
1620    ///
1621    /// ```
1622    /// # use solana_rpc_client_api::client_error::Error;
1623    /// # use solana_rpc_client::rpc_client::RpcClient;
1624    /// # use solana_sdk::slot_history::Slot;
1625    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1626    /// let start_slot = 1;
1627    /// let limit = 3;
1628    /// let leaders = rpc_client.get_slot_leaders(start_slot, limit)?;
1629    /// # Ok::<(), Error>(())
1630    /// ```
1631    pub fn get_slot_leaders(&self, start_slot: Slot, limit: u64) -> ClientResult<Vec<Pubkey>> {
1632        self.invoke((self.rpc_client.as_ref()).get_slot_leaders(start_slot, limit))
1633    }
1634
1635    /// Get block production for the current epoch.
1636    ///
1637    /// # RPC Reference
1638    ///
1639    /// This method corresponds directly to the [`getBlockProduction`] RPC method.
1640    ///
1641    /// [`getBlockProduction`]: https://solana.com/docs/rpc/http/getblockproduction
1642    ///
1643    /// # Examples
1644    ///
1645    /// ```
1646    /// # use solana_rpc_client_api::client_error::Error;
1647    /// # use solana_rpc_client::rpc_client::RpcClient;
1648    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1649    /// let production = rpc_client.get_block_production()?;
1650    /// # Ok::<(), Error>(())
1651    /// ```
1652    pub fn get_block_production(&self) -> RpcResult<RpcBlockProduction> {
1653        self.invoke((self.rpc_client.as_ref()).get_block_production())
1654    }
1655
1656    /// Get block production for the current or previous epoch.
1657    ///
1658    /// # RPC Reference
1659    ///
1660    /// This method corresponds directly to the [`getBlockProduction`] RPC method.
1661    ///
1662    /// [`getBlockProduction`]: https://solana.com/docs/rpc/http/getblockproduction
1663    ///
1664    /// # Examples
1665    ///
1666    /// ```
1667    /// # use solana_rpc_client_api::{
1668    /// #     client_error::Error,
1669    /// #     config::{RpcBlockProductionConfig, RpcBlockProductionConfigRange},
1670    /// # };
1671    /// # use solana_rpc_client::rpc_client::RpcClient;
1672    /// # use solana_sdk::{
1673    /// #     signature::Signer,
1674    /// #     signer::keypair::Keypair,
1675    /// #     commitment_config::CommitmentConfig,
1676    /// # };
1677    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1678    /// # let start_slot = 1;
1679    /// # let limit = 3;
1680    /// let leader = rpc_client.get_slot_leaders(start_slot, limit)?;
1681    /// let leader = leader[0];
1682    /// let range = RpcBlockProductionConfigRange {
1683    ///     first_slot: start_slot,
1684    ///     last_slot: Some(start_slot + limit),
1685    /// };
1686    /// let config = RpcBlockProductionConfig {
1687    ///     identity: Some(leader.to_string()),
1688    ///     range: Some(range),
1689    ///     commitment: Some(CommitmentConfig::processed()),
1690    /// };
1691    /// let production = rpc_client.get_block_production_with_config(
1692    ///     config
1693    /// )?;
1694    /// # Ok::<(), Error>(())
1695    /// ```
1696    pub fn get_block_production_with_config(
1697        &self,
1698        config: RpcBlockProductionConfig,
1699    ) -> RpcResult<RpcBlockProduction> {
1700        self.invoke((self.rpc_client.as_ref()).get_block_production_with_config(config))
1701    }
1702
1703    /// Returns information about the current supply.
1704    ///
1705    /// This method uses the configured [commitment level][cl].
1706    ///
1707    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1708    ///
1709    /// # RPC Reference
1710    ///
1711    /// This method corresponds directly to the [`getSupply`] RPC method.
1712    ///
1713    /// [`getSupply`]: https://solana.com/docs/rpc/http/getsupply
1714    ///
1715    /// # Examples
1716    ///
1717    /// ```
1718    /// # use solana_rpc_client_api::client_error::Error;
1719    /// # use solana_rpc_client::rpc_client::RpcClient;
1720    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1721    /// let supply = rpc_client.supply()?;
1722    /// # Ok::<(), Error>(())
1723    /// ```
1724    pub fn supply(&self) -> RpcResult<RpcSupply> {
1725        self.invoke((self.rpc_client.as_ref()).supply())
1726    }
1727
1728    /// Returns information about the current supply.
1729    ///
1730    /// # RPC Reference
1731    ///
1732    /// This method corresponds directly to the [`getSupply`] RPC method.
1733    ///
1734    /// [`getSupply`]: https://solana.com/docs/rpc/http/getsupply
1735    ///
1736    /// # Examples
1737    ///
1738    /// ```
1739    /// # use solana_rpc_client_api::client_error::Error;
1740    /// # use solana_rpc_client::rpc_client::RpcClient;
1741    /// # use solana_sdk::commitment_config::CommitmentConfig;
1742    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1743    /// let commitment_config = CommitmentConfig::processed();
1744    /// let supply = rpc_client.supply_with_commitment(
1745    ///     commitment_config,
1746    /// )?;
1747    /// # Ok::<(), Error>(())
1748    /// ```
1749    pub fn supply_with_commitment(
1750        &self,
1751        commitment_config: CommitmentConfig,
1752    ) -> RpcResult<RpcSupply> {
1753        self.invoke((self.rpc_client.as_ref()).supply_with_commitment(commitment_config))
1754    }
1755
1756    /// Returns the 20 largest accounts, by lamport balance.
1757    ///
1758    /// # RPC Reference
1759    ///
1760    /// This method corresponds directly to the [`getLargestAccounts`] RPC
1761    /// method.
1762    ///
1763    /// [`getLargestAccounts`]: https://solana.com/docs/rpc/http/getlargestaccounts
1764    ///
1765    /// # Examples
1766    ///
1767    /// ```
1768    /// # use solana_rpc_client_api::{
1769    /// #     client_error::Error,
1770    /// #     config::{RpcLargestAccountsConfig, RpcLargestAccountsFilter},
1771    /// # };
1772    /// # use solana_rpc_client::rpc_client::RpcClient;
1773    /// # use solana_sdk::commitment_config::CommitmentConfig;
1774    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1775    /// let commitment_config = CommitmentConfig::processed();
1776    /// let config = RpcLargestAccountsConfig {
1777    ///     commitment: Some(commitment_config),
1778    ///     filter: Some(RpcLargestAccountsFilter::Circulating),
1779    ///     sort_results: None,
1780    /// };
1781    /// let accounts = rpc_client.get_largest_accounts_with_config(
1782    ///     config,
1783    /// )?;
1784    /// # Ok::<(), Error>(())
1785    /// ```
1786    pub fn get_largest_accounts_with_config(
1787        &self,
1788        config: RpcLargestAccountsConfig,
1789    ) -> RpcResult<Vec<RpcAccountBalance>> {
1790        self.invoke((self.rpc_client.as_ref()).get_largest_accounts_with_config(config))
1791    }
1792
1793    /// Returns the account info and associated stake for all the voting accounts
1794    /// that have reached the configured [commitment level][cl].
1795    ///
1796    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1797    ///
1798    /// # RPC Reference
1799    ///
1800    /// This method corresponds directly to the [`getVoteAccounts`]
1801    /// RPC method.
1802    ///
1803    /// [`getVoteAccounts`]: https://solana.com/docs/rpc/http/getvoteaccounts
1804    ///
1805    /// # Examples
1806    ///
1807    /// ```
1808    /// # use solana_rpc_client_api::client_error::Error;
1809    /// # use solana_rpc_client::rpc_client::RpcClient;
1810    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1811    /// let accounts = rpc_client.get_vote_accounts()?;
1812    /// # Ok::<(), Error>(())
1813    /// ```
1814    pub fn get_vote_accounts(&self) -> ClientResult<RpcVoteAccountStatus> {
1815        self.invoke((self.rpc_client.as_ref()).get_vote_accounts())
1816    }
1817
1818    /// Returns the account info and associated stake for all the voting accounts
1819    /// that have reached the given [commitment level][cl].
1820    ///
1821    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1822    ///
1823    /// # RPC Reference
1824    ///
1825    /// This method corresponds directly to the [`getVoteAccounts`] RPC method.
1826    ///
1827    /// [`getVoteAccounts`]: https://solana.com/docs/rpc/http/getvoteaccounts
1828    ///
1829    /// # Examples
1830    ///
1831    /// ```
1832    /// # use solana_rpc_client_api::client_error::Error;
1833    /// # use solana_rpc_client::rpc_client::RpcClient;
1834    /// # use solana_sdk::commitment_config::CommitmentConfig;
1835    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1836    /// let commitment_config = CommitmentConfig::processed();
1837    /// let accounts = rpc_client.get_vote_accounts_with_commitment(
1838    ///     commitment_config,
1839    /// )?;
1840    /// # Ok::<(), Error>(())
1841    /// ```
1842    pub fn get_vote_accounts_with_commitment(
1843        &self,
1844        commitment_config: CommitmentConfig,
1845    ) -> ClientResult<RpcVoteAccountStatus> {
1846        self.invoke((self.rpc_client.as_ref()).get_vote_accounts_with_commitment(commitment_config))
1847    }
1848
1849    /// Returns the account info and associated stake for all the voting accounts
1850    /// that have reached the given [commitment level][cl].
1851    ///
1852    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
1853    ///
1854    /// # RPC Reference
1855    ///
1856    /// This method corresponds directly to the [`getVoteAccounts`] RPC method.
1857    ///
1858    /// [`getVoteAccounts`]: https://solana.com/docs/rpc/http/getvoteaccounts
1859    ///
1860    /// # Examples
1861    ///
1862    /// ```
1863    /// # use solana_rpc_client_api::{
1864    /// #     client_error::Error,
1865    /// #     config::RpcGetVoteAccountsConfig,
1866    /// # };
1867    /// # use solana_rpc_client::rpc_client::RpcClient;
1868    /// # use solana_sdk::{
1869    /// #     signer::keypair::Keypair,
1870    /// #     signature::Signer,
1871    /// #     commitment_config::CommitmentConfig,
1872    /// # };
1873    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1874    /// # let vote_keypair = Keypair::new();
1875    /// let vote_pubkey = vote_keypair.pubkey();
1876    /// let commitment = CommitmentConfig::processed();
1877    /// let config = RpcGetVoteAccountsConfig {
1878    ///     vote_pubkey: Some(vote_pubkey.to_string()),
1879    ///     commitment: Some(commitment),
1880    ///     keep_unstaked_delinquents: Some(true),
1881    ///     delinquent_slot_distance: Some(10),
1882    /// };
1883    /// let accounts = rpc_client.get_vote_accounts_with_config(
1884    ///     config,
1885    /// )?;
1886    /// # Ok::<(), Error>(())
1887    /// ```
1888    pub fn get_vote_accounts_with_config(
1889        &self,
1890        config: RpcGetVoteAccountsConfig,
1891    ) -> ClientResult<RpcVoteAccountStatus> {
1892        self.invoke((self.rpc_client.as_ref()).get_vote_accounts_with_config(config))
1893    }
1894
1895    pub fn wait_for_max_stake(
1896        &self,
1897        commitment: CommitmentConfig,
1898        max_stake_percent: f32,
1899    ) -> ClientResult<()> {
1900        self.invoke((self.rpc_client.as_ref()).wait_for_max_stake(commitment, max_stake_percent))
1901    }
1902
1903    pub fn wait_for_max_stake_below_threshold_with_timeout(
1904        &self,
1905        commitment: CommitmentConfig,
1906        max_stake_percent: f32,
1907        timeout: Duration,
1908    ) -> ClientResult<()> {
1909        self.invoke(
1910            (self.rpc_client.as_ref()).wait_for_max_stake_below_threshold_with_timeout(
1911                commitment,
1912                max_stake_percent,
1913                timeout,
1914            ),
1915        )
1916    }
1917
1918    /// Returns information about all the nodes participating in the cluster.
1919    ///
1920    /// # RPC Reference
1921    ///
1922    /// This method corresponds directly to the [`getClusterNodes`]
1923    /// RPC method.
1924    ///
1925    /// [`getClusterNodes`]: https://solana.com/docs/rpc/http/getclusternodes
1926    ///
1927    /// # Examples
1928    ///
1929    /// ```
1930    /// # use solana_rpc_client_api::client_error::Error;
1931    /// # use solana_rpc_client::rpc_client::RpcClient;
1932    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1933    /// let cluster_nodes = rpc_client.get_cluster_nodes()?;
1934    /// # Ok::<(), Error>(())
1935    /// ```
1936    pub fn get_cluster_nodes(&self) -> ClientResult<Vec<RpcContactInfo>> {
1937        self.invoke((self.rpc_client.as_ref()).get_cluster_nodes())
1938    }
1939
1940    /// Returns identity and transaction information about a confirmed block in the ledger.
1941    ///
1942    /// The encodings are returned in [`UiTransactionEncoding::Json`][uite]
1943    /// format. To return transactions in other encodings, use
1944    /// [`get_block_with_encoding`].
1945    ///
1946    /// [`get_block_with_encoding`]: RpcClient::get_block_with_encoding
1947    /// [uite]: UiTransactionEncoding::Json
1948    ///
1949    /// # RPC Reference
1950    ///
1951    /// This method corresponds directly to the [`getBlock`] RPC
1952    /// method.
1953    ///
1954    /// [`getBlock`]: https://solana.com/docs/rpc/http/getblock
1955    ///
1956    /// # Examples
1957    ///
1958    /// ```
1959    /// # use solana_rpc_client_api::client_error::Error;
1960    /// # use solana_rpc_client::rpc_client::RpcClient;
1961    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1962    /// # let slot = rpc_client.get_slot()?;
1963    /// let block = rpc_client.get_block(slot)?;
1964    /// # Ok::<(), Error>(())
1965    /// ```
1966    pub fn get_block(&self, slot: Slot) -> ClientResult<EncodedConfirmedBlock> {
1967        self.invoke((self.rpc_client.as_ref()).get_block(slot))
1968    }
1969
1970    /// Returns identity and transaction information about a confirmed block in the ledger.
1971    ///
1972    /// # RPC Reference
1973    ///
1974    /// This method corresponds directly to the [`getBlock`] RPC method.
1975    ///
1976    /// [`getBlock`]: https://solana.com/docs/rpc/http/getblock
1977    ///
1978    /// # Examples
1979    ///
1980    /// ```
1981    /// # use solana_rpc_client_api::client_error::Error;
1982    /// # use solana_rpc_client::rpc_client::RpcClient;
1983    /// # use solana_transaction_status_client_types::UiTransactionEncoding;
1984    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
1985    /// # let slot = rpc_client.get_slot()?;
1986    /// let encoding = UiTransactionEncoding::Base58;
1987    /// let block = rpc_client.get_block_with_encoding(
1988    ///     slot,
1989    ///     encoding,
1990    /// )?;
1991    /// # Ok::<(), Error>(())
1992    /// ```
1993    pub fn get_block_with_encoding(
1994        &self,
1995        slot: Slot,
1996        encoding: UiTransactionEncoding,
1997    ) -> ClientResult<EncodedConfirmedBlock> {
1998        self.invoke((self.rpc_client.as_ref()).get_block_with_encoding(slot, encoding))
1999    }
2000
2001    /// Returns identity and transaction information about a confirmed block in the ledger.
2002    ///
2003    /// # RPC Reference
2004    ///
2005    /// This method corresponds directly to the [`getBlock`] RPC method.
2006    ///
2007    /// [`getBlock`]: https://solana.com/docs/rpc/http/getblock
2008    ///
2009    /// # Examples
2010    ///
2011    /// ```
2012    /// # use solana_rpc_client_api::{
2013    /// #     config::RpcBlockConfig,
2014    /// #     client_error::Error,
2015    /// # };
2016    /// # use solana_rpc_client::rpc_client::RpcClient;
2017    /// # use solana_transaction_status_client_types::{
2018    /// #     TransactionDetails,
2019    /// #     UiTransactionEncoding,
2020    /// # };
2021    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2022    /// # let slot = rpc_client.get_slot()?;
2023    /// let config = RpcBlockConfig {
2024    ///     encoding: Some(UiTransactionEncoding::Base58),
2025    ///     transaction_details: Some(TransactionDetails::None),
2026    ///     rewards: Some(true),
2027    ///     commitment: None,
2028    ///     max_supported_transaction_version: Some(0),
2029    /// };
2030    /// let block = rpc_client.get_block_with_config(
2031    ///     slot,
2032    ///     config,
2033    /// )?;
2034    /// # Ok::<(), Error>(())
2035    /// ```
2036    pub fn get_block_with_config(
2037        &self,
2038        slot: Slot,
2039        config: RpcBlockConfig,
2040    ) -> ClientResult<UiConfirmedBlock> {
2041        self.invoke((self.rpc_client.as_ref()).get_block_with_config(slot, config))
2042    }
2043
2044    /// Returns a list of finalized blocks between two slots.
2045    ///
2046    /// The range is inclusive, with results including the block for both
2047    /// `start_slot` and `end_slot`.
2048    ///
2049    /// If `end_slot` is not provided, then the end slot is for the latest
2050    /// finalized block.
2051    ///
2052    /// This method may not return blocks for the full range of slots if some
2053    /// slots do not have corresponding blocks. To simply get a specific number
2054    /// of sequential blocks, use the [`get_blocks_with_limit`] method.
2055    ///
2056    /// This method uses the [`Finalized`] [commitment level][cl].
2057    ///
2058    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
2059    /// [`get_blocks_with_limit`]: RpcClient::get_blocks_with_limit.
2060    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2061    ///
2062    /// # Errors
2063    ///
2064    /// This method returns an error if the range is greater than 500,000 slots.
2065    ///
2066    /// # RPC Reference
2067    ///
2068    /// This method corresponds directly to the [`getBlocks`] RPC method.
2069    ///
2070    /// [`getBlocks`]: https://solana.com/docs/rpc/http/getblocks
2071    ///
2072    /// # Examples
2073    ///
2074    /// ```
2075    /// # use solana_rpc_client_api::client_error::Error;
2076    /// # use solana_rpc_client::rpc_client::RpcClient;
2077    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2078    /// // Get up to the first 10 blocks
2079    /// let start_slot = 0;
2080    /// let end_slot = 9;
2081    /// let blocks = rpc_client.get_blocks(start_slot, Some(end_slot))?;
2082    /// # Ok::<(), Error>(())
2083    /// ```
2084    pub fn get_blocks(&self, start_slot: Slot, end_slot: Option<Slot>) -> ClientResult<Vec<Slot>> {
2085        self.invoke((self.rpc_client.as_ref()).get_blocks(start_slot, end_slot))
2086    }
2087
2088    /// Returns a list of confirmed blocks between two slots.
2089    ///
2090    /// The range is inclusive, with results including the block for both
2091    /// `start_slot` and `end_slot`.
2092    ///
2093    /// If `end_slot` is not provided, then the end slot is for the latest
2094    /// block with the given [commitment level][cl].
2095    ///
2096    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2097    ///
2098    /// This method may not return blocks for the full range of slots if some
2099    /// slots do not have corresponding blocks. To simply get a specific number
2100    /// of sequential blocks, use the [`get_blocks_with_limit_and_commitment`]
2101    /// method.
2102    ///
2103    /// [`get_blocks_with_limit_and_commitment`]: RpcClient::get_blocks_with_limit_and_commitment.
2104    ///
2105    /// # Errors
2106    ///
2107    /// This method returns an error if the range is greater than 500,000 slots.
2108    ///
2109    /// This method returns an error if the given commitment level is below
2110    /// [`Confirmed`].
2111    ///
2112    /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed
2113    ///
2114    /// # RPC Reference
2115    ///
2116    /// This method corresponds directly to the [`getBlocks`] RPC method.
2117    ///
2118    /// [`getBlocks`]: https://solana.com/docs/rpc/http/getblocks
2119    ///
2120    /// # Examples
2121    ///
2122    /// ```
2123    /// # use solana_rpc_client_api::client_error::Error;
2124    /// # use solana_rpc_client::rpc_client::RpcClient;
2125    /// # use solana_sdk::commitment_config::CommitmentConfig;
2126    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2127    /// // Get up to the first 10 blocks
2128    /// let start_slot = 0;
2129    /// let end_slot = 9;
2130    /// // Method does not support commitment below `confirmed`
2131    /// let commitment_config = CommitmentConfig::confirmed();
2132    /// let blocks = rpc_client.get_blocks_with_commitment(
2133    ///     start_slot,
2134    ///     Some(end_slot),
2135    ///     commitment_config,
2136    /// )?;
2137    /// # Ok::<(), Error>(())
2138    /// ```
2139    pub fn get_blocks_with_commitment(
2140        &self,
2141        start_slot: Slot,
2142        end_slot: Option<Slot>,
2143        commitment_config: CommitmentConfig,
2144    ) -> ClientResult<Vec<Slot>> {
2145        self.invoke((self.rpc_client.as_ref()).get_blocks_with_commitment(
2146            start_slot,
2147            end_slot,
2148            commitment_config,
2149        ))
2150    }
2151
2152    /// Returns a list of finalized blocks starting at the given slot.
2153    ///
2154    /// This method uses the [`Finalized`] [commitment level][cl].
2155    ///
2156    /// [`Finalized`]: CommitmentLevel::Finalized.
2157    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2158    ///
2159    /// # Errors
2160    ///
2161    /// This method returns an error if the limit is greater than 500,000 slots.
2162    ///
2163    /// # RPC Reference
2164    ///
2165    /// This method corresponds directly to the [`getBlocksWithLimit`] RPC
2166    /// method.
2167    ///
2168    /// [`getBlocksWithLimit`]: https://solana.com/docs/rpc/http/getblockswithlimit
2169    ///
2170    /// # Examples
2171    ///
2172    /// ```
2173    /// # use solana_rpc_client_api::client_error::Error;
2174    /// # use solana_rpc_client::rpc_client::RpcClient;
2175    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2176    /// // Get the first 10 blocks
2177    /// let start_slot = 0;
2178    /// let limit = 10;
2179    /// let blocks = rpc_client.get_blocks_with_limit(start_slot, limit)?;
2180    /// # Ok::<(), Error>(())
2181    /// ```
2182    pub fn get_blocks_with_limit(&self, start_slot: Slot, limit: usize) -> ClientResult<Vec<Slot>> {
2183        self.invoke((self.rpc_client.as_ref()).get_blocks_with_limit(start_slot, limit))
2184    }
2185
2186    /// Returns a list of confirmed blocks starting at the given slot.
2187    ///
2188    /// # Errors
2189    ///
2190    /// This method returns an error if the limit is greater than 500,000 slots.
2191    ///
2192    /// This method returns an error if the given [commitment level][cl] is below
2193    /// [`Confirmed`].
2194    ///
2195    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2196    /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed
2197    ///
2198    /// # RPC Reference
2199    ///
2200    /// This method corresponds directly to the [`getBlocksWithLimit`] RPC
2201    /// method.
2202    ///
2203    /// [`getBlocksWithLimit`]: https://solana.com/docs/rpc/http/getblockswithlimit
2204    ///
2205    /// # Examples
2206    ///
2207    /// ```
2208    /// # use solana_rpc_client_api::client_error::Error;
2209    /// # use solana_rpc_client::rpc_client::RpcClient;
2210    /// # use solana_sdk::commitment_config::CommitmentConfig;
2211    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2212    /// // Get the first 10 blocks
2213    /// let start_slot = 0;
2214    /// let limit = 10;
2215    /// let commitment_config = CommitmentConfig::confirmed();
2216    /// let blocks = rpc_client.get_blocks_with_limit_and_commitment(
2217    ///     start_slot,
2218    ///     limit,
2219    ///     commitment_config,
2220    /// )?;
2221    /// # Ok::<(), Error>(())
2222    /// ```
2223    pub fn get_blocks_with_limit_and_commitment(
2224        &self,
2225        start_slot: Slot,
2226        limit: usize,
2227        commitment_config: CommitmentConfig,
2228    ) -> ClientResult<Vec<Slot>> {
2229        self.invoke(
2230            (self.rpc_client.as_ref()).get_blocks_with_limit_and_commitment(
2231                start_slot,
2232                limit,
2233                commitment_config,
2234            ),
2235        )
2236    }
2237
2238    /// Get confirmed signatures for transactions involving an address.
2239    ///
2240    /// Returns up to 1000 signatures, ordered from newest to oldest.
2241    ///
2242    /// This method uses the [`Finalized`] [commitment level][cl].
2243    ///
2244    /// [`Finalized`]: CommitmentLevel::Finalized.
2245    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2246    ///
2247    /// # RPC Reference
2248    ///
2249    /// This method corresponds directly to the [`getSignaturesForAddress`] RPC
2250    /// method.
2251    ///
2252    /// [`getSignaturesForAddress`]: https://solana.com/docs/rpc/http/getsignaturesforaddress
2253    ///
2254    /// # Examples
2255    ///
2256    /// ```
2257    /// # use solana_rpc_client_api::client_error::Error;
2258    /// # use solana_rpc_client::rpc_client::RpcClient;
2259    /// # use solana_sdk::{
2260    /// #     signature::Signer,
2261    /// #     signer::keypair::Keypair,
2262    /// #     system_transaction,
2263    /// # };
2264    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2265    /// # let alice = Keypair::new();
2266    /// let signatures = rpc_client.get_signatures_for_address(
2267    ///     &alice.pubkey(),
2268    /// )?;
2269    /// # Ok::<(), Error>(())
2270    /// ```
2271    pub fn get_signatures_for_address(
2272        &self,
2273        address: &Pubkey,
2274    ) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
2275        self.invoke((self.rpc_client.as_ref()).get_signatures_for_address(address))
2276    }
2277
2278    /// Get confirmed signatures for transactions involving an address.
2279    ///
2280    /// # Errors
2281    ///
2282    /// This method returns an error if the given [commitment level][cl] is below
2283    /// [`Confirmed`].
2284    ///
2285    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2286    /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed
2287    ///
2288    /// # RPC Reference
2289    ///
2290    /// This method corresponds directly to the [`getSignaturesForAddress`] RPC
2291    /// method.
2292    ///
2293    /// [`getSignaturesForAddress`]: https://solana.com/docs/rpc/http/getsignaturesforaddress
2294    ///
2295    /// # Examples
2296    ///
2297    /// ```
2298    /// # use solana_rpc_client_api::client_error::Error;
2299    /// # use solana_rpc_client::rpc_client::{GetConfirmedSignaturesForAddress2Config, RpcClient};
2300    /// # use solana_sdk::{
2301    /// #     signature::Signer,
2302    /// #     signer::keypair::Keypair,
2303    /// #     system_transaction,
2304    /// #     commitment_config::CommitmentConfig,
2305    /// # };
2306    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2307    /// # let alice = Keypair::new();
2308    /// # let bob = Keypair::new();
2309    /// # let lamports = 50;
2310    /// # let latest_blockhash = rpc_client.get_latest_blockhash()?;
2311    /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
2312    /// # let signature = rpc_client.send_and_confirm_transaction(&tx)?;
2313    /// let config = GetConfirmedSignaturesForAddress2Config {
2314    ///     before: None,
2315    ///     until: None,
2316    ///     limit: Some(3),
2317    ///     commitment: Some(CommitmentConfig::confirmed()),
2318    /// };
2319    /// let signatures = rpc_client.get_signatures_for_address_with_config(
2320    ///     &alice.pubkey(),
2321    ///     config,
2322    /// )?;
2323    /// # Ok::<(), Error>(())
2324    /// ```
2325    pub fn get_signatures_for_address_with_config(
2326        &self,
2327        address: &Pubkey,
2328        config: GetConfirmedSignaturesForAddress2Config,
2329    ) -> ClientResult<Vec<RpcConfirmedTransactionStatusWithSignature>> {
2330        self.invoke(
2331            (self.rpc_client.as_ref()).get_signatures_for_address_with_config(address, config),
2332        )
2333    }
2334
2335    /// Returns transaction details for a confirmed transaction.
2336    ///
2337    /// This method uses the [`Finalized`] [commitment level][cl].
2338    ///
2339    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
2340    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2341    ///
2342    /// # RPC Reference
2343    ///
2344    /// This method corresponds directly to the [`getTransaction`] RPC method.
2345    ///
2346    /// [`getTransaction`]: https://solana.com/docs/rpc/http/gettransaction
2347    ///
2348    /// # Examples
2349    ///
2350    /// ```
2351    /// # use solana_rpc_client_api::client_error::Error;
2352    /// # use solana_rpc_client::rpc_client::RpcClient;
2353    /// # use solana_sdk::{
2354    /// #     signature::Signer,
2355    /// #     signature::Signature,
2356    /// #     signer::keypair::Keypair,
2357    /// #     system_transaction,
2358    /// # };
2359    /// # use solana_transaction_status_client_types::UiTransactionEncoding;
2360    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2361    /// # let alice = Keypair::new();
2362    /// # let bob = Keypair::new();
2363    /// # let lamports = 50;
2364    /// # let latest_blockhash = rpc_client.get_latest_blockhash()?;
2365    /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
2366    /// let signature = rpc_client.send_and_confirm_transaction(&tx)?;
2367    /// let transaction = rpc_client.get_transaction(
2368    ///     &signature,
2369    ///     UiTransactionEncoding::Json,
2370    /// )?;
2371    /// # Ok::<(), Error>(())
2372    /// ```
2373    pub fn get_transaction(
2374        &self,
2375        signature: &Signature,
2376        encoding: UiTransactionEncoding,
2377    ) -> ClientResult<EncodedConfirmedTransactionWithStatusMeta> {
2378        self.invoke((self.rpc_client.as_ref()).get_transaction(signature, encoding))
2379    }
2380
2381    /// Returns transaction details for a confirmed transaction.
2382    ///
2383    /// # Errors
2384    ///
2385    /// This method returns an error if the given [commitment level][cl] is below
2386    /// [`Confirmed`].
2387    ///
2388    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2389    /// [`Confirmed`]: solana_sdk::commitment_config::CommitmentLevel::Confirmed
2390    ///
2391    /// # RPC Reference
2392    ///
2393    /// This method corresponds directly to the [`getTransaction`] RPC method.
2394    ///
2395    /// [`getTransaction`]: https://solana.com/docs/rpc/http/gettransaction
2396    ///
2397    /// # Examples
2398    ///
2399    /// ```
2400    /// # use solana_rpc_client_api::{
2401    /// #     client_error::Error,
2402    /// #     config::RpcTransactionConfig,
2403    /// # };
2404    /// # use solana_rpc_client::rpc_client::RpcClient;
2405    /// # use solana_sdk::{
2406    /// #     signature::Signer,
2407    /// #     signature::Signature,
2408    /// #     signer::keypair::Keypair,
2409    /// #     system_transaction,
2410    /// #     commitment_config::CommitmentConfig,
2411    /// # };
2412    /// # use solana_transaction_status_client_types::UiTransactionEncoding;
2413    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2414    /// # let alice = Keypair::new();
2415    /// # let bob = Keypair::new();
2416    /// # let lamports = 50;
2417    /// # let latest_blockhash = rpc_client.get_latest_blockhash()?;
2418    /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash);
2419    /// let signature = rpc_client.send_and_confirm_transaction(&tx)?;
2420    /// let config = RpcTransactionConfig {
2421    ///     encoding: Some(UiTransactionEncoding::Json),
2422    ///     commitment: Some(CommitmentConfig::confirmed()),
2423    ///     max_supported_transaction_version: Some(0),
2424    /// };
2425    /// let transaction = rpc_client.get_transaction_with_config(
2426    ///     &signature,
2427    ///     config,
2428    /// )?;
2429    /// # Ok::<(), Error>(())
2430    /// ```
2431    pub fn get_transaction_with_config(
2432        &self,
2433        signature: &Signature,
2434        config: RpcTransactionConfig,
2435    ) -> ClientResult<EncodedConfirmedTransactionWithStatusMeta> {
2436        self.invoke((self.rpc_client.as_ref()).get_transaction_with_config(signature, config))
2437    }
2438
2439    /// Returns the estimated production time of a block.
2440    ///
2441    /// # RPC Reference
2442    ///
2443    /// This method corresponds directly to the [`getBlockTime`] RPC method.
2444    ///
2445    /// [`getBlockTime`]: https://solana.com/docs/rpc/http/getblocktime
2446    ///
2447    /// # Examples
2448    ///
2449    /// ```
2450    /// # use solana_rpc_client_api::client_error::Error;
2451    /// # use solana_rpc_client::rpc_client::RpcClient;
2452    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2453    /// // Get the time of the most recent finalized block
2454    /// let slot = rpc_client.get_slot()?;
2455    /// let block_time = rpc_client.get_block_time(slot)?;
2456    /// # Ok::<(), Error>(())
2457    /// ```
2458    pub fn get_block_time(&self, slot: Slot) -> ClientResult<UnixTimestamp> {
2459        self.invoke((self.rpc_client.as_ref()).get_block_time(slot))
2460    }
2461
2462    /// Returns information about the current epoch.
2463    ///
2464    /// This method uses the configured default [commitment level][cl].
2465    ///
2466    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2467    ///
2468    /// # RPC Reference
2469    ///
2470    /// This method corresponds directly to the [`getEpochInfo`] RPC method.
2471    ///
2472    /// [`getEpochInfo`]: https://solana.com/docs/rpc/http/getepochinfo
2473    ///
2474    /// # Examples
2475    ///
2476    /// ```
2477    /// # use solana_rpc_client_api::client_error::Error;
2478    /// # use solana_rpc_client::rpc_client::RpcClient;
2479    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2480    /// let epoch_info = rpc_client.get_epoch_info()?;
2481    /// # Ok::<(), Error>(())
2482    /// ```
2483    pub fn get_epoch_info(&self) -> ClientResult<EpochInfo> {
2484        self.invoke((self.rpc_client.as_ref()).get_epoch_info())
2485    }
2486
2487    /// Returns information about the current epoch.
2488    ///
2489    /// # RPC Reference
2490    ///
2491    /// This method corresponds directly to the [`getEpochInfo`] RPC method.
2492    ///
2493    /// [`getEpochInfo`]: https://solana.com/docs/rpc/http/getepochinfo
2494    ///
2495    /// # Examples
2496    ///
2497    /// ```
2498    /// # use solana_rpc_client_api::client_error::Error;
2499    /// # use solana_rpc_client::rpc_client::RpcClient;
2500    /// # use solana_sdk::commitment_config::CommitmentConfig;
2501    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2502    /// let commitment_config = CommitmentConfig::confirmed();
2503    /// let epoch_info = rpc_client.get_epoch_info_with_commitment(
2504    ///     commitment_config,
2505    /// )?;
2506    /// # Ok::<(), Error>(())
2507    /// ```
2508    pub fn get_epoch_info_with_commitment(
2509        &self,
2510        commitment_config: CommitmentConfig,
2511    ) -> ClientResult<EpochInfo> {
2512        self.invoke((self.rpc_client.as_ref()).get_epoch_info_with_commitment(commitment_config))
2513    }
2514
2515    /// Returns the leader schedule for an epoch.
2516    ///
2517    /// This method uses the configured default [commitment level][cl].
2518    ///
2519    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2520    ///
2521    /// # RPC Reference
2522    ///
2523    /// This method corresponds directly to the [`getLeaderSchedule`] RPC method.
2524    ///
2525    /// [`getLeaderSchedule`]: https://solana.com/docs/rpc/http/getleaderschedule
2526    ///
2527    /// # Examples
2528    ///
2529    /// ```
2530    /// # use solana_rpc_client_api::client_error::Error;
2531    /// # use solana_rpc_client::rpc_client::RpcClient;
2532    /// # use solana_sdk::commitment_config::CommitmentConfig;
2533    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2534    /// # let slot = rpc_client.get_slot()?;
2535    /// let leader_schedule = rpc_client.get_leader_schedule(
2536    ///     Some(slot),
2537    /// )?;
2538    /// # Ok::<(), Error>(())
2539    /// ```
2540    pub fn get_leader_schedule(
2541        &self,
2542        slot: Option<Slot>,
2543    ) -> ClientResult<Option<RpcLeaderSchedule>> {
2544        self.invoke((self.rpc_client.as_ref()).get_leader_schedule(slot))
2545    }
2546
2547    /// Returns the leader schedule for an epoch.
2548    ///
2549    /// # RPC Reference
2550    ///
2551    /// This method corresponds directly to the [`getLeaderSchedule`] RPC method.
2552    ///
2553    /// [`getLeaderSchedule`]: https://solana.com/docs/rpc/http/getleaderschedule
2554    ///
2555    /// # Examples
2556    ///
2557    /// ```
2558    /// # use solana_rpc_client_api::client_error::Error;
2559    /// # use solana_rpc_client::rpc_client::RpcClient;
2560    /// # use solana_sdk::commitment_config::CommitmentConfig;
2561    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2562    /// # let slot = rpc_client.get_slot()?;
2563    /// let commitment_config = CommitmentConfig::processed();
2564    /// let leader_schedule = rpc_client.get_leader_schedule_with_commitment(
2565    ///     Some(slot),
2566    ///     commitment_config,
2567    /// )?;
2568    /// # Ok::<(), Error>(())
2569    /// ```
2570    pub fn get_leader_schedule_with_commitment(
2571        &self,
2572        slot: Option<Slot>,
2573        commitment_config: CommitmentConfig,
2574    ) -> ClientResult<Option<RpcLeaderSchedule>> {
2575        self.invoke(
2576            (self.rpc_client.as_ref()).get_leader_schedule_with_commitment(slot, commitment_config),
2577        )
2578    }
2579
2580    /// Returns the leader schedule for an epoch.
2581    ///
2582    /// # RPC Reference
2583    ///
2584    /// This method corresponds directly to the [`getLeaderSchedule`] RPC method.
2585    ///
2586    /// [`getLeaderSchedule`]: https://solana.com/docs/rpc/http/getleaderschedule
2587    ///
2588    /// # Examples
2589    ///
2590    /// ```
2591    /// # use solana_rpc_client_api::{
2592    /// #     client_error::Error,
2593    /// #     config::RpcLeaderScheduleConfig,
2594    /// # };
2595    /// # use solana_rpc_client::rpc_client::RpcClient;
2596    /// # use solana_sdk::commitment_config::CommitmentConfig;
2597    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2598    /// # let slot = rpc_client.get_slot()?;
2599    /// # let validator_pubkey_str = "7AYmEYBBetok8h5L3Eo3vi3bDWnjNnaFbSXfSNYV5ewB".to_string();
2600    /// let config = RpcLeaderScheduleConfig {
2601    ///     identity: Some(validator_pubkey_str),
2602    ///     commitment: Some(CommitmentConfig::processed()),
2603    /// };
2604    /// let leader_schedule = rpc_client.get_leader_schedule_with_config(
2605    ///     Some(slot),
2606    ///     config,
2607    /// )?;
2608    /// # Ok::<(), Error>(())
2609    /// ```
2610    pub fn get_leader_schedule_with_config(
2611        &self,
2612        slot: Option<Slot>,
2613        config: RpcLeaderScheduleConfig,
2614    ) -> ClientResult<Option<RpcLeaderSchedule>> {
2615        self.invoke((self.rpc_client.as_ref()).get_leader_schedule_with_config(slot, config))
2616    }
2617
2618    /// Returns epoch schedule information from this cluster's genesis config.
2619    ///
2620    /// # RPC Reference
2621    ///
2622    /// This method corresponds directly to the [`getEpochSchedule`] RPC method.
2623    ///
2624    /// [`getEpochSchedule`]: https://solana.com/docs/rpc/http/getepochschedule
2625    ///
2626    /// # Examples
2627    ///
2628    /// ```
2629    /// # use solana_rpc_client_api::client_error::Error;
2630    /// # use solana_rpc_client::rpc_client::RpcClient;
2631    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2632    /// let epoch_schedule = rpc_client.get_epoch_schedule()?;
2633    /// # Ok::<(), Error>(())
2634    /// ```
2635    pub fn get_epoch_schedule(&self) -> ClientResult<EpochSchedule> {
2636        self.invoke((self.rpc_client.as_ref()).get_epoch_schedule())
2637    }
2638
2639    /// Returns a list of recent performance samples, in reverse slot order.
2640    ///
2641    /// Performance samples are taken every 60 seconds and include the number of
2642    /// transactions and slots that occur in a given time window.
2643    ///
2644    /// # RPC Reference
2645    ///
2646    /// This method corresponds directly to the [`getRecentPerformanceSamples`] RPC method.
2647    ///
2648    /// [`getRecentPerformanceSamples`]: https://solana.com/docs/rpc/http/getrecentperformancesamples
2649    ///
2650    /// # Examples
2651    ///
2652    /// ```
2653    /// # use solana_rpc_client_api::client_error::Error;
2654    /// # use solana_rpc_client::rpc_client::RpcClient;
2655    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2656    /// let limit = 10;
2657    /// let performance_samples = rpc_client.get_recent_performance_samples(
2658    ///     Some(limit),
2659    /// )?;
2660    /// # Ok::<(), Error>(())
2661    /// ```
2662    pub fn get_recent_performance_samples(
2663        &self,
2664        limit: Option<usize>,
2665    ) -> ClientResult<Vec<RpcPerfSample>> {
2666        self.invoke((self.rpc_client.as_ref()).get_recent_performance_samples(limit))
2667    }
2668
2669    /// Returns a list of minimum prioritization fees from recent blocks.
2670    /// Takes an optional vector of addresses; if any addresses are provided, the response will
2671    /// reflect the minimum prioritization fee to land a transaction locking all of the provided
2672    /// accounts as writable.
2673    ///
2674    /// Currently, a node's prioritization-fee cache stores data from up to 150 blocks.
2675    ///
2676    /// # RPC Reference
2677    ///
2678    /// This method corresponds directly to the [`getRecentPrioritizationFees`] RPC method.
2679    ///
2680    /// [`getRecentPrioritizationFees`]: https://solana.com/docs/rpc/http/getrecentprioritizationfees
2681    ///
2682    /// # Examples
2683    ///
2684    /// ```
2685    /// # use solana_rpc_client_api::client_error::Error;
2686    /// # use solana_rpc_client::rpc_client::RpcClient;
2687    /// # use solana_sdk::signature::{Keypair, Signer};
2688    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2689    /// # let alice = Keypair::new();
2690    /// # let bob = Keypair::new();
2691    /// let addresses = vec![alice.pubkey(), bob.pubkey()];
2692    /// let prioritization_fees = rpc_client.get_recent_prioritization_fees(
2693    ///     &addresses,
2694    /// )?;
2695    /// # Ok::<(), Error>(())
2696    /// ```
2697    pub fn get_recent_prioritization_fees(
2698        &self,
2699        addresses: &[Pubkey],
2700    ) -> ClientResult<Vec<RpcPrioritizationFee>> {
2701        self.invoke((self.rpc_client.as_ref()).get_recent_prioritization_fees(addresses))
2702    }
2703
2704    /// Returns the identity pubkey for the current node.
2705    ///
2706    /// # RPC Reference
2707    ///
2708    /// This method corresponds directly to the [`getIdentity`] RPC method.
2709    ///
2710    /// [`getIdentity`]: https://solana.com/docs/rpc/http/getidentity
2711    ///
2712    /// # Examples
2713    ///
2714    /// ```
2715    /// # use solana_rpc_client_api::client_error::Error;
2716    /// # use solana_rpc_client::rpc_client::RpcClient;
2717    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2718    /// let identity = rpc_client.get_identity()?;
2719    /// # Ok::<(), Error>(())
2720    /// ```
2721    pub fn get_identity(&self) -> ClientResult<Pubkey> {
2722        self.invoke((self.rpc_client.as_ref()).get_identity())
2723    }
2724
2725    /// Returns the current inflation governor.
2726    ///
2727    /// This method uses the [`Finalized`] [commitment level][cl].
2728    ///
2729    /// [`Finalized`]: solana_sdk::commitment_config::CommitmentLevel::Finalized
2730    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2731    ///
2732    /// # RPC Reference
2733    ///
2734    /// This method corresponds directly to the [`getInflationGovernor`] RPC
2735    /// method.
2736    ///
2737    /// [`getInflationGovernor`]: https://solana.com/docs/rpc/http/getinflationgovernor
2738    ///
2739    /// # Examples
2740    ///
2741    /// ```
2742    /// # use solana_rpc_client_api::client_error::Error;
2743    /// # use solana_rpc_client::rpc_client::RpcClient;
2744    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2745    /// let inflation_governor = rpc_client.get_inflation_governor()?;
2746    /// # Ok::<(), Error>(())
2747    /// ```
2748    pub fn get_inflation_governor(&self) -> ClientResult<RpcInflationGovernor> {
2749        self.invoke((self.rpc_client.as_ref()).get_inflation_governor())
2750    }
2751
2752    /// Returns the specific inflation values for the current epoch.
2753    ///
2754    /// # RPC Reference
2755    ///
2756    /// This method corresponds directly to the [`getInflationRate`] RPC method.
2757    ///
2758    /// [`getInflationRate`]: https://solana.com/docs/rpc/http/getinflationrate
2759    ///
2760    /// # Examples
2761    ///
2762    /// ```
2763    /// # use solana_rpc_client_api::client_error::Error;
2764    /// # use solana_rpc_client::rpc_client::RpcClient;
2765    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2766    /// let inflation_rate = rpc_client.get_inflation_rate()?;
2767    /// # Ok::<(), Error>(())
2768    /// ```
2769    pub fn get_inflation_rate(&self) -> ClientResult<RpcInflationRate> {
2770        self.invoke((self.rpc_client.as_ref()).get_inflation_rate())
2771    }
2772
2773    /// Returns the inflation reward for a list of addresses for an epoch.
2774    ///
2775    /// This method uses the configured [commitment level][cl].
2776    ///
2777    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2778    ///
2779    /// # RPC Reference
2780    ///
2781    /// This method corresponds directly to the [`getInflationReward`] RPC method.
2782    ///
2783    /// [`getInflationReward`]: https://solana.com/docs/rpc/http/getinflationreward
2784    ///
2785    /// # Examples
2786    ///
2787    /// ```
2788    /// # use solana_rpc_client_api::client_error::Error;
2789    /// # use solana_rpc_client::rpc_client::RpcClient;
2790    /// # use solana_sdk::signature::{Keypair, Signer};
2791    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2792    /// # let epoch_info = rpc_client.get_epoch_info()?;
2793    /// # let epoch = epoch_info.epoch;
2794    /// # let alice = Keypair::new();
2795    /// # let bob = Keypair::new();
2796    /// let addresses = vec![alice.pubkey(), bob.pubkey()];
2797    /// let inflation_reward = rpc_client.get_inflation_reward(
2798    ///     &addresses,
2799    ///     Some(epoch),
2800    /// )?;
2801    /// # Ok::<(), Error>(())
2802    /// ```
2803    pub fn get_inflation_reward(
2804        &self,
2805        addresses: &[Pubkey],
2806        epoch: Option<Epoch>,
2807    ) -> ClientResult<Vec<Option<RpcInflationReward>>> {
2808        self.invoke((self.rpc_client.as_ref()).get_inflation_reward(addresses, epoch))
2809    }
2810
2811    /// Returns the current solana version running on the node.
2812    ///
2813    /// # RPC Reference
2814    ///
2815    /// This method corresponds directly to the [`getVersion`] RPC method.
2816    ///
2817    /// [`getVersion`]: https://solana.com/docs/rpc/http/getversion
2818    ///
2819    /// # Examples
2820    ///
2821    /// ```
2822    /// # use solana_rpc_client_api::client_error::Error;
2823    /// # use solana_rpc_client::rpc_client::RpcClient;
2824    /// # use solana_sdk::signature::{Keypair, Signer};
2825    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2826    /// let expected_version = semver::Version::new(1, 7, 0);
2827    /// let version = rpc_client.get_version()?;
2828    /// let version = semver::Version::parse(&version.solana_core)?;
2829    /// assert!(version >= expected_version);
2830    /// # Ok::<(), Box<dyn std::error::Error>>(())
2831    /// ```
2832    pub fn get_version(&self) -> ClientResult<RpcVersionInfo> {
2833        self.invoke((self.rpc_client.as_ref()).get_version())
2834    }
2835
2836    /// Returns the lowest slot that the node has information about in its ledger.
2837    ///
2838    /// This value may increase over time if the node is configured to purge
2839    /// older ledger data.
2840    ///
2841    /// # RPC Reference
2842    ///
2843    /// This method corresponds directly to the [`minimumLedgerSlot`] RPC
2844    /// method.
2845    ///
2846    /// [`minimumLedgerSlot`]: https://solana.com/docs/rpc/http/minimumledgerslot
2847    ///
2848    /// # Examples
2849    ///
2850    /// ```
2851    /// # use solana_rpc_client_api::client_error::Error;
2852    /// # use solana_rpc_client::rpc_client::RpcClient;
2853    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
2854    /// let slot = rpc_client.minimum_ledger_slot()?;
2855    /// # Ok::<(), Error>(())
2856    /// ```
2857    pub fn minimum_ledger_slot(&self) -> ClientResult<Slot> {
2858        self.invoke((self.rpc_client.as_ref()).minimum_ledger_slot())
2859    }
2860
2861    /// Returns all information associated with the account of the provided pubkey.
2862    ///
2863    /// This method uses the configured [commitment level][cl].
2864    ///
2865    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
2866    ///
2867    /// To get multiple accounts at once, use the [`get_multiple_accounts`] method.
2868    ///
2869    /// [`get_multiple_accounts`]: RpcClient::get_multiple_accounts
2870    ///
2871    /// # Errors
2872    ///
2873    /// If the account does not exist, this method returns
2874    /// [`RpcError::ForUser`]. This is unlike [`get_account_with_commitment`],
2875    /// which returns `Ok(None)` if the account does not exist.
2876    ///
2877    /// [`RpcError::ForUser`]: solana_rpc_client_api::request::RpcError::ForUser
2878    /// [`get_account_with_commitment`]: RpcClient::get_account_with_commitment
2879    ///
2880    /// # RPC Reference
2881    ///
2882    /// This method is built on the [`getAccountInfo`] RPC method.
2883    ///
2884    /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo
2885    ///
2886    /// # Examples
2887    ///
2888    /// ```
2889    /// # use solana_rpc_client_api::client_error::Error;
2890    /// # use solana_rpc_client::rpc_client::{self, RpcClient};
2891    /// # use solana_sdk::{
2892    /// #     signature::Signer,
2893    /// #     signer::keypair::Keypair,
2894    /// #     pubkey::Pubkey,
2895    /// # };
2896    /// # use std::str::FromStr;
2897    /// # let mocks = rpc_client::create_rpc_client_mocks();
2898    /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks);
2899    /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap();
2900    /// let account = rpc_client.get_account(&alice_pubkey)?;
2901    /// # Ok::<(), Error>(())
2902    /// ```
2903    pub fn get_account(&self, pubkey: &Pubkey) -> ClientResult<Account> {
2904        self.invoke((self.rpc_client.as_ref()).get_account(pubkey))
2905    }
2906
2907    /// Returns all information associated with the account of the provided pubkey.
2908    ///
2909    /// If the account does not exist, this method returns `Ok(None)`.
2910    ///
2911    /// To get multiple accounts at once, use the [`get_multiple_accounts_with_commitment`] method.
2912    ///
2913    /// [`get_multiple_accounts_with_commitment`]: RpcClient::get_multiple_accounts_with_commitment
2914    ///
2915    /// # RPC Reference
2916    ///
2917    /// This method is built on the [`getAccountInfo`] RPC method.
2918    ///
2919    /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo
2920    ///
2921    /// # Examples
2922    ///
2923    /// ```
2924    /// # use solana_rpc_client_api::client_error::Error;
2925    /// # use solana_rpc_client::rpc_client::{self, RpcClient};
2926    /// # use solana_sdk::{
2927    /// #     signature::Signer,
2928    /// #     signer::keypair::Keypair,
2929    /// #     pubkey::Pubkey,
2930    /// #     commitment_config::CommitmentConfig,
2931    /// # };
2932    /// # use std::str::FromStr;
2933    /// # let mocks = rpc_client::create_rpc_client_mocks();
2934    /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks);
2935    /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap();
2936    /// let commitment_config = CommitmentConfig::processed();
2937    /// let account = rpc_client.get_account_with_commitment(
2938    ///     &alice_pubkey,
2939    ///     commitment_config,
2940    /// )?;
2941    /// assert!(account.value.is_some());
2942    /// # Ok::<(), Error>(())
2943    /// ```
2944    pub fn get_account_with_commitment(
2945        &self,
2946        pubkey: &Pubkey,
2947        commitment_config: CommitmentConfig,
2948    ) -> RpcResult<Option<Account>> {
2949        self.invoke(
2950            (self.rpc_client.as_ref()).get_account_with_commitment(pubkey, commitment_config),
2951        )
2952    }
2953
2954    /// Returns all information associated with the account of the provided pubkey.
2955    ///
2956    /// If the account does not exist, this method returns `Ok(None)`.
2957    ///
2958    /// To get multiple accounts at once, use the [`get_multiple_accounts_with_config`] method.
2959    ///
2960    /// [`get_multiple_accounts_with_config`]: RpcClient::get_multiple_accounts_with_config
2961    ///
2962    /// # RPC Reference
2963    ///
2964    /// This method is built on the [`getAccountInfo`] RPC method.
2965    ///
2966    /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo
2967    ///
2968    /// # Examples
2969    ///
2970    /// ```
2971    /// # use solana_rpc_client_api::{
2972    /// #     config::RpcAccountInfoConfig,
2973    /// #     client_error::Error,
2974    /// # };
2975    /// # use solana_rpc_client::rpc_client::{self, RpcClient};
2976    /// # use solana_sdk::{
2977    /// #     signature::Signer,
2978    /// #     signer::keypair::Keypair,
2979    /// #     pubkey::Pubkey,
2980    /// #     commitment_config::CommitmentConfig,
2981    /// # };
2982    /// # use solana_account_decoder_client_types::UiAccountEncoding;
2983    /// # use std::str::FromStr;
2984    /// # let mocks = rpc_client::create_rpc_client_mocks();
2985    /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks);
2986    /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap();
2987    /// let commitment_config = CommitmentConfig::processed();
2988    /// let config = RpcAccountInfoConfig {
2989    ///     encoding: Some(UiAccountEncoding::Base64),
2990    ///     commitment: Some(commitment_config),
2991    ///     .. RpcAccountInfoConfig::default()
2992    /// };
2993    /// let account = rpc_client.get_account_with_config(
2994    ///     &alice_pubkey,
2995    ///     config,
2996    /// )?;
2997    /// assert!(account.value.is_some());
2998    /// # Ok::<(), Error>(())
2999    /// ```
3000    pub fn get_account_with_config(
3001        &self,
3002        pubkey: &Pubkey,
3003        config: RpcAccountInfoConfig,
3004    ) -> RpcResult<Option<Account>> {
3005        self.invoke((self.rpc_client.as_ref()).get_account_with_config(pubkey, config))
3006    }
3007
3008    /// Get the max slot seen from retransmit stage.
3009    ///
3010    /// # RPC Reference
3011    ///
3012    /// This method corresponds directly to the [`getMaxRetransmitSlot`] RPC
3013    /// method.
3014    ///
3015    /// [`getMaxRetransmitSlot`]: https://solana.com/docs/rpc/http/getmaxretransmitslot
3016    ///
3017    /// # Examples
3018    ///
3019    /// ```
3020    /// # use solana_rpc_client_api::client_error::Error;
3021    /// # use solana_rpc_client::rpc_client::RpcClient;
3022    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3023    /// let slot = rpc_client.get_max_retransmit_slot()?;
3024    /// # Ok::<(), Error>(())
3025    pub fn get_max_retransmit_slot(&self) -> ClientResult<Slot> {
3026        self.invoke((self.rpc_client.as_ref()).get_max_retransmit_slot())
3027    }
3028
3029    /// Get the max slot seen from after [shred](https://solana.com/docs/terminology#shred) insert.
3030    ///
3031    /// # RPC Reference
3032    ///
3033    /// This method corresponds directly to the
3034    /// [`getMaxShredInsertSlot`] RPC method.
3035    ///
3036    /// [`getMaxShredInsertSlot`]: https://solana.com/docs/rpc/http/getmaxshredinsertslot
3037    ///
3038    /// # Examples
3039    ///
3040    /// ```
3041    /// # use solana_rpc_client_api::client_error::Error;
3042    /// # use solana_rpc_client::rpc_client::RpcClient;
3043    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3044    /// let slot = rpc_client.get_max_shred_insert_slot()?;
3045    /// # Ok::<(), Error>(())
3046    pub fn get_max_shred_insert_slot(&self) -> ClientResult<Slot> {
3047        self.invoke((self.rpc_client.as_ref()).get_max_shred_insert_slot())
3048    }
3049
3050    /// Returns the account information for a list of pubkeys.
3051    ///
3052    /// This method uses the configured [commitment level][cl].
3053    ///
3054    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
3055    ///
3056    /// # RPC Reference
3057    ///
3058    /// This method is built on the [`getMultipleAccounts`] RPC method.
3059    ///
3060    /// [`getMultipleAccounts`]: https://solana.com/docs/rpc/http/getmultipleaccounts
3061    ///
3062    /// # Examples
3063    ///
3064    /// ```
3065    /// # use solana_rpc_client_api::client_error::Error;
3066    /// # use solana_rpc_client::rpc_client::RpcClient;
3067    /// # use solana_sdk::{
3068    /// #     signature::Signer,
3069    /// #     signer::keypair::Keypair,
3070    /// # };
3071    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3072    /// # let alice = Keypair::new();
3073    /// # let bob = Keypair::new();
3074    /// let pubkeys = vec![alice.pubkey(), bob.pubkey()];
3075    /// let accounts = rpc_client.get_multiple_accounts(&pubkeys)?;
3076    /// # Ok::<(), Error>(())
3077    /// ```
3078    pub fn get_multiple_accounts(&self, pubkeys: &[Pubkey]) -> ClientResult<Vec<Option<Account>>> {
3079        self.invoke((self.rpc_client.as_ref()).get_multiple_accounts(pubkeys))
3080    }
3081
3082    /// Returns the account information for a list of pubkeys.
3083    ///
3084    /// # RPC Reference
3085    ///
3086    /// This method is built on the [`getMultipleAccounts`] RPC method.
3087    ///
3088    /// [`getMultipleAccounts`]: https://solana.com/docs/rpc/http/getmultipleaccounts
3089    ///
3090    /// # Examples
3091    ///
3092    /// ```
3093    /// # use solana_rpc_client_api::client_error::Error;
3094    /// # use solana_rpc_client::rpc_client::RpcClient;
3095    /// # use solana_sdk::{
3096    /// #     signature::Signer,
3097    /// #     signer::keypair::Keypair,
3098    /// #     commitment_config::CommitmentConfig,
3099    /// # };
3100    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3101    /// # let alice = Keypair::new();
3102    /// # let bob = Keypair::new();
3103    /// let pubkeys = vec![alice.pubkey(), bob.pubkey()];
3104    /// let commitment_config = CommitmentConfig::processed();
3105    /// let accounts = rpc_client.get_multiple_accounts_with_commitment(
3106    ///     &pubkeys,
3107    ///     commitment_config,
3108    /// )?;
3109    /// # Ok::<(), Error>(())
3110    /// ```
3111    pub fn get_multiple_accounts_with_commitment(
3112        &self,
3113        pubkeys: &[Pubkey],
3114        commitment_config: CommitmentConfig,
3115    ) -> RpcResult<Vec<Option<Account>>> {
3116        self.invoke(
3117            (self.rpc_client.as_ref())
3118                .get_multiple_accounts_with_commitment(pubkeys, commitment_config),
3119        )
3120    }
3121
3122    /// Returns the account information for a list of pubkeys.
3123    ///
3124    /// # RPC Reference
3125    ///
3126    /// This method is built on the [`getMultipleAccounts`] RPC method.
3127    ///
3128    /// [`getMultipleAccounts`]: https://solana.com/docs/rpc/http/getmultipleaccounts
3129    ///
3130    /// # Examples
3131    ///
3132    /// ```
3133    /// # use solana_rpc_client_api::{
3134    /// #     config::RpcAccountInfoConfig,
3135    /// #     client_error::Error,
3136    /// # };
3137    /// # use solana_rpc_client::rpc_client::RpcClient;
3138    /// # use solana_sdk::{
3139    /// #     signature::Signer,
3140    /// #     signer::keypair::Keypair,
3141    /// #     commitment_config::CommitmentConfig,
3142    /// # };
3143    /// # use solana_account_decoder_client_types::UiAccountEncoding;
3144    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3145    /// # let alice = Keypair::new();
3146    /// # let bob = Keypair::new();
3147    /// let pubkeys = vec![alice.pubkey(), bob.pubkey()];
3148    /// let commitment_config = CommitmentConfig::processed();
3149    /// let config = RpcAccountInfoConfig {
3150    ///     encoding: Some(UiAccountEncoding::Base64),
3151    ///     commitment: Some(commitment_config),
3152    ///     .. RpcAccountInfoConfig::default()
3153    /// };
3154    /// let accounts = rpc_client.get_multiple_accounts_with_config(
3155    ///     &pubkeys,
3156    ///     config,
3157    /// )?;
3158    /// # Ok::<(), Error>(())
3159    /// ```
3160    pub fn get_multiple_accounts_with_config(
3161        &self,
3162        pubkeys: &[Pubkey],
3163        config: RpcAccountInfoConfig,
3164    ) -> RpcResult<Vec<Option<Account>>> {
3165        self.invoke((self.rpc_client.as_ref()).get_multiple_accounts_with_config(pubkeys, config))
3166    }
3167
3168    /// Gets the raw data associated with an account.
3169    ///
3170    /// This is equivalent to calling [`get_account`] and then accessing the
3171    /// [`data`] field of the returned [`Account`].
3172    ///
3173    /// [`get_account`]: RpcClient::get_account
3174    /// [`data`]: Account::data
3175    ///
3176    /// # RPC Reference
3177    ///
3178    /// This method is built on the [`getAccountInfo`] RPC method.
3179    ///
3180    /// [`getAccountInfo`]: https://solana.com/docs/rpc/http/getaccountinfo
3181    ///
3182    /// # Examples
3183    ///
3184    /// ```
3185    /// # use solana_rpc_client_api::client_error::Error;
3186    /// # use solana_rpc_client::rpc_client::{self, RpcClient};
3187    /// # use solana_sdk::{
3188    /// #     signature::Signer,
3189    /// #     signer::keypair::Keypair,
3190    /// #     pubkey::Pubkey,
3191    /// # };
3192    /// # use std::str::FromStr;
3193    /// # let mocks = rpc_client::create_rpc_client_mocks();
3194    /// # let rpc_client = RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks);
3195    /// let alice_pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap();
3196    /// let account_data = rpc_client.get_account_data(&alice_pubkey)?;
3197    /// # Ok::<(), Error>(())
3198    /// ```
3199    pub fn get_account_data(&self, pubkey: &Pubkey) -> ClientResult<Vec<u8>> {
3200        self.invoke((self.rpc_client.as_ref()).get_account_data(pubkey))
3201    }
3202
3203    /// Returns minimum balance required to make an account with specified data length rent exempt.
3204    ///
3205    /// # RPC Reference
3206    ///
3207    /// This method corresponds directly to the
3208    /// [`getMinimumBalanceForRentExemption`] RPC method.
3209    ///
3210    /// [`getMinimumBalanceForRentExemption`]: https://solana.com/docs/rpc/http/getminimumbalanceforrentexemption
3211    ///
3212    /// # Examples
3213    ///
3214    /// ```
3215    /// # use solana_rpc_client_api::client_error::Error;
3216    /// # use solana_rpc_client::rpc_client::RpcClient;
3217    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3218    /// let data_len = 300;
3219    /// let balance = rpc_client.get_minimum_balance_for_rent_exemption(data_len)?;
3220    /// # Ok::<(), Error>(())
3221    /// ```
3222    pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> ClientResult<u64> {
3223        self.invoke((self.rpc_client.as_ref()).get_minimum_balance_for_rent_exemption(data_len))
3224    }
3225
3226    /// Request the balance of the provided account pubkey.
3227    ///
3228    /// This method uses the configured [commitment level][cl].
3229    ///
3230    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
3231    ///
3232    /// # RPC Reference
3233    ///
3234    /// This method corresponds directly to the [`getBalance`] RPC method.
3235    ///
3236    /// [`getBalance`]: https://solana.com/docs/rpc/http/getbalance
3237    ///
3238    /// # Examples
3239    ///
3240    /// ```
3241    /// # use solana_rpc_client_api::client_error::Error;
3242    /// # use solana_rpc_client::rpc_client::RpcClient;
3243    /// # use solana_sdk::{
3244    /// #     signature::Signer,
3245    /// #     signer::keypair::Keypair,
3246    /// # };
3247    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3248    /// # let alice = Keypair::new();
3249    /// let balance = rpc_client.get_balance(&alice.pubkey())?;
3250    /// # Ok::<(), Error>(())
3251    /// ```
3252    pub fn get_balance(&self, pubkey: &Pubkey) -> ClientResult<u64> {
3253        self.invoke((self.rpc_client.as_ref()).get_balance(pubkey))
3254    }
3255
3256    /// Request the balance of the provided account pubkey.
3257    ///
3258    /// # RPC Reference
3259    ///
3260    /// This method corresponds directly to the [`getBalance`] RPC method.
3261    ///
3262    /// [`getBalance`]: https://solana.com/docs/rpc/http/getbalance
3263    ///
3264    /// # Examples
3265    ///
3266    /// ```
3267    /// # use solana_rpc_client_api::client_error::Error;
3268    /// # use solana_rpc_client::rpc_client::RpcClient;
3269    /// # use solana_sdk::{
3270    /// #     signature::Signer,
3271    /// #     signer::keypair::Keypair,
3272    /// #     commitment_config::CommitmentConfig,
3273    /// # };
3274    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3275    /// # let alice = Keypair::new();
3276    /// let commitment_config = CommitmentConfig::processed();
3277    /// let balance = rpc_client.get_balance_with_commitment(
3278    ///     &alice.pubkey(),
3279    ///     commitment_config,
3280    /// )?;
3281    /// # Ok::<(), Error>(())
3282    /// ```
3283    pub fn get_balance_with_commitment(
3284        &self,
3285        pubkey: &Pubkey,
3286        commitment_config: CommitmentConfig,
3287    ) -> RpcResult<u64> {
3288        self.invoke(
3289            (self.rpc_client.as_ref()).get_balance_with_commitment(pubkey, commitment_config),
3290        )
3291    }
3292
3293    /// Returns all accounts owned by the provided program pubkey.
3294    ///
3295    /// This method uses the configured [commitment level][cl].
3296    ///
3297    /// [cl]: https://solana.com/docs/rpc#configuring-state-commitment
3298    ///
3299    /// # RPC Reference
3300    ///
3301    /// This method corresponds directly to the [`getProgramAccounts`] RPC
3302    /// method.
3303    ///
3304    /// [`getProgramAccounts`]: https://solana.com/docs/rpc/http/getprogramaccounts
3305    ///
3306    /// # Examples
3307    ///
3308    /// ```
3309    /// # use solana_rpc_client_api::client_error::Error;
3310    /// # use solana_rpc_client::rpc_client::RpcClient;
3311    /// # use solana_sdk::{
3312    /// #     signature::Signer,
3313    /// #     signer::keypair::Keypair,
3314    /// # };
3315    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3316    /// # let alice = Keypair::new();
3317    /// let accounts = rpc_client.get_program_accounts(&alice.pubkey())?;
3318    /// # Ok::<(), Error>(())
3319    /// ```
3320    pub fn get_program_accounts(&self, pubkey: &Pubkey) -> ClientResult<Vec<(Pubkey, Account)>> {
3321        self.invoke((self.rpc_client.as_ref()).get_program_accounts(pubkey))
3322    }
3323
3324    /// Returns all accounts owned by the provided program pubkey.
3325    ///
3326    /// # RPC Reference
3327    ///
3328    /// This method is built on the [`getProgramAccounts`] RPC method.
3329    ///
3330    /// [`getProgramAccounts`]: https://solana.com/docs/rpc/http/getprogramaccounts
3331    ///
3332    /// # Examples
3333    ///
3334    /// ```
3335    /// # use solana_rpc_client_api::{
3336    /// #     client_error::Error,
3337    /// #     config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
3338    /// #     filter::{MemcmpEncodedBytes, RpcFilterType, Memcmp},
3339    /// # };
3340    /// # use solana_rpc_client::rpc_client::RpcClient;
3341    /// # use solana_sdk::{
3342    /// #     signature::Signer,
3343    /// #     signer::keypair::Keypair,
3344    /// #     commitment_config::CommitmentConfig,
3345    /// # };
3346    /// # use solana_account_decoder_client_types::{UiDataSliceConfig, UiAccountEncoding};
3347    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3348    /// # let alice = Keypair::new();
3349    /// # let base64_bytes = "\
3350    /// #     AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
3351    /// #     AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
3352    /// #     AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
3353    /// let memcmp = RpcFilterType::Memcmp(Memcmp::new(
3354    ///     0,                                                    // offset
3355    ///     MemcmpEncodedBytes::Base64(base64_bytes.to_string()), // encoded bytes
3356    /// ));
3357    /// let config = RpcProgramAccountsConfig {
3358    ///     filters: Some(vec![
3359    ///         RpcFilterType::DataSize(128),
3360    ///         memcmp,
3361    ///     ]),
3362    ///     account_config: RpcAccountInfoConfig {
3363    ///         encoding: Some(UiAccountEncoding::Base64),
3364    ///         data_slice: Some(UiDataSliceConfig {
3365    ///             offset: 0,
3366    ///             length: 5,
3367    ///         }),
3368    ///         commitment: Some(CommitmentConfig::processed()),
3369    ///         min_context_slot: Some(1234),
3370    ///     },
3371    ///     with_context: Some(false),
3372    ///     sort_results: Some(true),
3373    /// };
3374    /// let accounts = rpc_client.get_program_accounts_with_config(
3375    ///     &alice.pubkey(),
3376    ///     config,
3377    /// )?;
3378    /// # Ok::<(), Error>(())
3379    /// ```
3380    pub fn get_program_accounts_with_config(
3381        &self,
3382        pubkey: &Pubkey,
3383        config: RpcProgramAccountsConfig,
3384    ) -> ClientResult<Vec<(Pubkey, Account)>> {
3385        self.invoke((self.rpc_client.as_ref()).get_program_accounts_with_config(pubkey, config))
3386    }
3387
3388    /// Returns the stake minimum delegation, in lamports.
3389    ///
3390    /// # RPC Reference
3391    ///
3392    /// This method corresponds directly to the [`getStakeMinimumDelegation`] RPC method.
3393    ///
3394    /// [`getStakeMinimumDelegation`]: https://solana.com/docs/rpc/http/getstakeminimumdelegation
3395    ///
3396    /// # Examples
3397    ///
3398    /// ```
3399    /// # use solana_rpc_client_api::client_error::Error;
3400    /// # use solana_rpc_client::rpc_client::RpcClient;
3401    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3402    /// let stake_minimum_delegation = rpc_client.get_stake_minimum_delegation()?;
3403    /// # Ok::<(), Error>(())
3404    /// ```
3405    pub fn get_stake_minimum_delegation(&self) -> ClientResult<u64> {
3406        self.invoke((self.rpc_client.as_ref()).get_stake_minimum_delegation())
3407    }
3408
3409    /// Returns the stake minimum delegation, in lamports, based on the commitment level.
3410    ///
3411    /// # RPC Reference
3412    ///
3413    /// This method corresponds directly to the [`getStakeMinimumDelegation`] RPC method.
3414    ///
3415    /// [`getStakeMinimumDelegation`]: https://solana.com/docs/rpc/http/getstakeminimumdelegation
3416    ///
3417    /// # Examples
3418    ///
3419    /// ```
3420    /// # use solana_rpc_client_api::client_error::Error;
3421    /// # use solana_rpc_client::rpc_client::RpcClient;
3422    /// # use solana_sdk::commitment_config::CommitmentConfig;
3423    /// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
3424    /// let stake_minimum_delegation =
3425    /// rpc_client.get_stake_minimum_delegation_with_commitment(CommitmentConfig::confirmed())?;
3426    /// # Ok::<(), Error>(())
3427    /// ```
3428    pub fn get_stake_minimum_delegation_with_commitment(
3429        &self,
3430        commitment_config: CommitmentConfig,
3431    ) -> ClientResult<u64> {
3432        self.invoke(
3433            self.rpc_client
3434                .get_stake_minimum_delegation_with_commitment(commitment_config),
3435        )
3436    }
3437
3438    /// Request the transaction count.
3439    pub fn get_transaction_count(&self) -> ClientResult<u64> {
3440        self.invoke((self.rpc_client.as_ref()).get_transaction_count())
3441    }
3442
3443    pub fn get_transaction_count_with_commitment(
3444        &self,
3445        commitment_config: CommitmentConfig,
3446    ) -> ClientResult<u64> {
3447        self.invoke(
3448            (self.rpc_client.as_ref()).get_transaction_count_with_commitment(commitment_config),
3449        )
3450    }
3451
3452    pub fn get_first_available_block(&self) -> ClientResult<Slot> {
3453        self.invoke((self.rpc_client.as_ref()).get_first_available_block())
3454    }
3455
3456    pub fn get_genesis_hash(&self) -> ClientResult<Hash> {
3457        self.invoke((self.rpc_client.as_ref()).get_genesis_hash())
3458    }
3459
3460    pub fn get_health(&self) -> ClientResult<()> {
3461        self.invoke((self.rpc_client.as_ref()).get_health())
3462    }
3463
3464    pub fn get_token_account(&self, pubkey: &Pubkey) -> ClientResult<Option<UiTokenAccount>> {
3465        self.invoke((self.rpc_client.as_ref()).get_token_account(pubkey))
3466    }
3467
3468    pub fn get_token_account_with_commitment(
3469        &self,
3470        pubkey: &Pubkey,
3471        commitment_config: CommitmentConfig,
3472    ) -> RpcResult<Option<UiTokenAccount>> {
3473        self.invoke(
3474            (self.rpc_client.as_ref()).get_token_account_with_commitment(pubkey, commitment_config),
3475        )
3476    }
3477
3478    pub fn get_token_account_balance(&self, pubkey: &Pubkey) -> ClientResult<UiTokenAmount> {
3479        self.invoke((self.rpc_client.as_ref()).get_token_account_balance(pubkey))
3480    }
3481
3482    pub fn get_token_account_balance_with_commitment(
3483        &self,
3484        pubkey: &Pubkey,
3485        commitment_config: CommitmentConfig,
3486    ) -> RpcResult<UiTokenAmount> {
3487        self.invoke(
3488            (self.rpc_client.as_ref())
3489                .get_token_account_balance_with_commitment(pubkey, commitment_config),
3490        )
3491    }
3492
3493    pub fn get_token_accounts_by_delegate(
3494        &self,
3495        delegate: &Pubkey,
3496        token_account_filter: TokenAccountsFilter,
3497    ) -> ClientResult<Vec<RpcKeyedAccount>> {
3498        self.invoke(
3499            (self.rpc_client.as_ref())
3500                .get_token_accounts_by_delegate(delegate, token_account_filter),
3501        )
3502    }
3503
3504    pub fn get_token_accounts_by_delegate_with_commitment(
3505        &self,
3506        delegate: &Pubkey,
3507        token_account_filter: TokenAccountsFilter,
3508        commitment_config: CommitmentConfig,
3509    ) -> RpcResult<Vec<RpcKeyedAccount>> {
3510        self.invoke(
3511            (self.rpc_client.as_ref()).get_token_accounts_by_delegate_with_commitment(
3512                delegate,
3513                token_account_filter,
3514                commitment_config,
3515            ),
3516        )
3517    }
3518
3519    pub fn get_token_accounts_by_owner(
3520        &self,
3521        owner: &Pubkey,
3522        token_account_filter: TokenAccountsFilter,
3523    ) -> ClientResult<Vec<RpcKeyedAccount>> {
3524        self.invoke(
3525            (self.rpc_client.as_ref()).get_token_accounts_by_owner(owner, token_account_filter),
3526        )
3527    }
3528
3529    pub fn get_token_accounts_by_owner_with_commitment(
3530        &self,
3531        owner: &Pubkey,
3532        token_account_filter: TokenAccountsFilter,
3533        commitment_config: CommitmentConfig,
3534    ) -> RpcResult<Vec<RpcKeyedAccount>> {
3535        self.invoke(
3536            (self.rpc_client.as_ref()).get_token_accounts_by_owner_with_commitment(
3537                owner,
3538                token_account_filter,
3539                commitment_config,
3540            ),
3541        )
3542    }
3543
3544    pub fn get_token_largest_accounts(
3545        &self,
3546        mint: &Pubkey,
3547    ) -> ClientResult<Vec<RpcTokenAccountBalance>> {
3548        self.invoke((self.rpc_client.as_ref()).get_token_largest_accounts(mint))
3549    }
3550
3551    pub fn get_token_largest_accounts_with_commitment(
3552        &self,
3553        mint: &Pubkey,
3554        commitment_config: CommitmentConfig,
3555    ) -> RpcResult<Vec<RpcTokenAccountBalance>> {
3556        self.invoke(
3557            (self.rpc_client.as_ref())
3558                .get_token_largest_accounts_with_commitment(mint, commitment_config),
3559        )
3560    }
3561
3562    pub fn get_token_supply(&self, mint: &Pubkey) -> ClientResult<UiTokenAmount> {
3563        self.invoke((self.rpc_client.as_ref()).get_token_supply(mint))
3564    }
3565
3566    pub fn get_token_supply_with_commitment(
3567        &self,
3568        mint: &Pubkey,
3569        commitment_config: CommitmentConfig,
3570    ) -> RpcResult<UiTokenAmount> {
3571        self.invoke(
3572            (self.rpc_client.as_ref()).get_token_supply_with_commitment(mint, commitment_config),
3573        )
3574    }
3575
3576    pub fn request_airdrop(&self, pubkey: &Pubkey, lamports: u64) -> ClientResult<Signature> {
3577        self.invoke((self.rpc_client.as_ref()).request_airdrop(pubkey, lamports))
3578    }
3579
3580    pub fn request_airdrop_with_blockhash(
3581        &self,
3582        pubkey: &Pubkey,
3583        lamports: u64,
3584        recent_blockhash: &Hash,
3585    ) -> ClientResult<Signature> {
3586        self.invoke((self.rpc_client.as_ref()).request_airdrop_with_blockhash(
3587            pubkey,
3588            lamports,
3589            recent_blockhash,
3590        ))
3591    }
3592
3593    pub fn request_airdrop_with_config(
3594        &self,
3595        pubkey: &Pubkey,
3596        lamports: u64,
3597        config: RpcRequestAirdropConfig,
3598    ) -> ClientResult<Signature> {
3599        self.invoke(
3600            (self.rpc_client.as_ref()).request_airdrop_with_config(pubkey, lamports, config),
3601        )
3602    }
3603
3604    pub fn poll_get_balance_with_commitment(
3605        &self,
3606        pubkey: &Pubkey,
3607        commitment_config: CommitmentConfig,
3608    ) -> ClientResult<u64> {
3609        self.invoke(
3610            (self.rpc_client.as_ref()).poll_get_balance_with_commitment(pubkey, commitment_config),
3611        )
3612    }
3613
3614    pub fn wait_for_balance_with_commitment(
3615        &self,
3616        pubkey: &Pubkey,
3617        expected_balance: Option<u64>,
3618        commitment_config: CommitmentConfig,
3619    ) -> Option<u64> {
3620        self.invoke((self.rpc_client.as_ref()).wait_for_balance_with_commitment(
3621            pubkey,
3622            expected_balance,
3623            commitment_config,
3624        ))
3625        .ok()
3626    }
3627
3628    /// Poll the server to confirm a transaction.
3629    pub fn poll_for_signature(&self, signature: &Signature) -> ClientResult<()> {
3630        self.invoke((self.rpc_client.as_ref()).poll_for_signature(signature))
3631    }
3632
3633    /// Poll the server to confirm a transaction.
3634    pub fn poll_for_signature_with_commitment(
3635        &self,
3636        signature: &Signature,
3637        commitment_config: CommitmentConfig,
3638    ) -> ClientResult<()> {
3639        self.invoke(
3640            (self.rpc_client.as_ref())
3641                .poll_for_signature_with_commitment(signature, commitment_config),
3642        )
3643    }
3644
3645    /// Poll the server to confirm a transaction.
3646    pub fn poll_for_signature_confirmation(
3647        &self,
3648        signature: &Signature,
3649        min_confirmed_blocks: usize,
3650    ) -> ClientResult<usize> {
3651        self.invoke(
3652            (self.rpc_client.as_ref())
3653                .poll_for_signature_confirmation(signature, min_confirmed_blocks),
3654        )
3655    }
3656
3657    pub fn get_num_blocks_since_signature_confirmation(
3658        &self,
3659        signature: &Signature,
3660    ) -> ClientResult<usize> {
3661        self.invoke(
3662            (self.rpc_client.as_ref()).get_num_blocks_since_signature_confirmation(signature),
3663        )
3664    }
3665
3666    pub fn get_latest_blockhash(&self) -> ClientResult<Hash> {
3667        self.invoke((self.rpc_client.as_ref()).get_latest_blockhash())
3668    }
3669
3670    pub fn get_latest_blockhash_with_commitment(
3671        &self,
3672        commitment: CommitmentConfig,
3673    ) -> ClientResult<(Hash, u64)> {
3674        self.invoke((self.rpc_client.as_ref()).get_latest_blockhash_with_commitment(commitment))
3675    }
3676
3677    pub fn is_blockhash_valid(
3678        &self,
3679        blockhash: &Hash,
3680        commitment: CommitmentConfig,
3681    ) -> ClientResult<bool> {
3682        self.invoke((self.rpc_client.as_ref()).is_blockhash_valid(blockhash, commitment))
3683    }
3684
3685    pub fn get_fee_for_message(&self, message: &impl SerializableMessage) -> ClientResult<u64> {
3686        self.invoke((self.rpc_client.as_ref()).get_fee_for_message(message))
3687    }
3688
3689    pub fn get_new_latest_blockhash(&self, blockhash: &Hash) -> ClientResult<Hash> {
3690        self.invoke((self.rpc_client.as_ref()).get_new_latest_blockhash(blockhash))
3691    }
3692
3693    pub fn get_transport_stats(&self) -> RpcTransportStats {
3694        (self.rpc_client.as_ref()).get_transport_stats()
3695    }
3696
3697    pub fn get_feature_activation_slot(&self, feature_id: &Pubkey) -> ClientResult<Option<Slot>> {
3698        self.get_account_with_commitment(feature_id, self.commitment())
3699            .and_then(|maybe_feature_account| {
3700                maybe_feature_account
3701                    .value
3702                    .map(|feature_account| {
3703                        bincode::deserialize(feature_account.data()).map_err(|_| {
3704                            ClientError::from(ErrorKind::Custom(
3705                                "Failed to deserialize feature account".to_string(),
3706                            ))
3707                        })
3708                    })
3709                    .transpose()
3710            })
3711            .map(|maybe_feature: Option<Feature>| {
3712                maybe_feature.and_then(|feature| feature.activated_at)
3713            })
3714    }
3715
3716    fn invoke<T, F: std::future::Future<Output = ClientResult<T>>>(&self, f: F) -> ClientResult<T> {
3717        // `block_on()` panics if called within an asynchronous execution context. Whereas
3718        // `block_in_place()` only panics if called from a current_thread runtime, which is the
3719        // lesser evil.
3720        tokio::task::block_in_place(move || self.runtime.as_ref().expect("runtime").block_on(f))
3721    }
3722
3723    pub fn get_inner_client(&self) -> &Arc<nonblocking::rpc_client::RpcClient> {
3724        &self.rpc_client
3725    }
3726
3727    pub fn runtime(&self) -> &tokio::runtime::Runtime {
3728        self.runtime.as_ref().expect("runtime")
3729    }
3730}
3731
3732/// Mocks for documentation examples
3733#[doc(hidden)]
3734pub fn create_rpc_client_mocks() -> crate::mock_sender::Mocks {
3735    let mut mocks = std::collections::HashMap::new();
3736
3737    let get_account_request = RpcRequest::GetAccountInfo;
3738    let get_account_response = serde_json::to_value(Response {
3739        context: RpcResponseContext {
3740            slot: 1,
3741            api_version: None,
3742        },
3743        value: {
3744            let pubkey = Pubkey::from_str("BgvYtJEfmZYdVKiptmMjxGzv8iQoo4MWjsP3QsTkhhxa").unwrap();
3745            mock_encoded_account(&pubkey)
3746        },
3747    })
3748    .unwrap();
3749
3750    mocks.insert(get_account_request, get_account_response);
3751
3752    mocks
3753}
3754
3755#[cfg(test)]
3756mod tests {
3757    use {
3758        super::*,
3759        crate::mock_sender::PUBKEY,
3760        assert_matches::assert_matches,
3761        crossbeam_channel::unbounded,
3762        jsonrpc_core::{futures::prelude::*, Error, IoHandler, Params},
3763        jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder},
3764        serde_json::{json, Number},
3765        solana_account_decoder::encode_ui_account,
3766        solana_account_decoder_client_types::UiAccountEncoding,
3767        solana_rpc_client_api::client_error::ErrorKind,
3768        solana_sdk::{
3769            instruction::InstructionError,
3770            signature::{Keypair, Signer},
3771            system_transaction,
3772            transaction::TransactionError,
3773        },
3774        std::{io, thread},
3775    };
3776
3777    #[test]
3778    fn test_send() {
3779        _test_send();
3780    }
3781
3782    #[tokio::test(flavor = "current_thread")]
3783    #[should_panic(expected = "can call blocking only when running on the multi-threaded runtime")]
3784    async fn test_send_async_current_thread() {
3785        _test_send();
3786    }
3787
3788    #[tokio::test(flavor = "multi_thread")]
3789    async fn test_send_async_multi_thread() {
3790        _test_send();
3791    }
3792
3793    fn _test_send() {
3794        let (sender, receiver) = unbounded();
3795        thread::spawn(move || {
3796            let rpc_addr = "0.0.0.0:0".parse().unwrap();
3797            let mut io = IoHandler::default();
3798            // Successful request
3799            io.add_method("getBalance", |_params: Params| {
3800                future::ok(Value::Number(Number::from(50)))
3801            });
3802            // Failed request
3803            io.add_method("getLatestBlockhash", |params: Params| {
3804                if params != Params::None {
3805                    future::err(Error::invalid_request())
3806                } else {
3807                    future::ok(Value::String(
3808                        "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx".to_string(),
3809                    ))
3810                }
3811            });
3812
3813            let server = ServerBuilder::new(io)
3814                .threads(1)
3815                .cors(DomainsValidation::AllowOnly(vec![
3816                    AccessControlAllowOrigin::Any,
3817                ]))
3818                .start_http(&rpc_addr)
3819                .expect("Unable to start RPC server");
3820            sender.send(*server.address()).unwrap();
3821            server.wait();
3822        });
3823
3824        let rpc_addr = receiver.recv().unwrap();
3825        let rpc_client = RpcClient::new_socket(rpc_addr);
3826
3827        let balance: u64 = rpc_client
3828            .send(
3829                RpcRequest::GetBalance,
3830                json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"]),
3831            )
3832            .unwrap();
3833        assert_eq!(balance, 50);
3834
3835        let blockhash: String = rpc_client
3836            .send(RpcRequest::GetLatestBlockhash, Value::Null)
3837            .unwrap();
3838        assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
3839
3840        // Send erroneous parameter
3841        let blockhash: ClientResult<String> =
3842            rpc_client.send(RpcRequest::GetLatestBlockhash, json!(["parameter"]));
3843        assert!(blockhash.is_err());
3844    }
3845
3846    #[test]
3847    fn test_send_transaction() {
3848        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3849
3850        let key = Keypair::new();
3851        let to = solana_sdk::pubkey::new_rand();
3852        let blockhash = Hash::default();
3853        let tx = system_transaction::transfer(&key, &to, 50, blockhash);
3854
3855        let signature = rpc_client.send_transaction(&tx);
3856        assert_eq!(signature.unwrap(), tx.signatures[0]);
3857
3858        let rpc_client = RpcClient::new_mock("fails".to_string());
3859
3860        let signature = rpc_client.send_transaction(&tx);
3861        assert!(signature.is_err());
3862
3863        // Test bad signature returned from rpc node
3864        let rpc_client = RpcClient::new_mock("malicious".to_string());
3865        let signature = rpc_client.send_transaction(&tx);
3866        assert!(signature.is_err());
3867    }
3868
3869    #[test]
3870    fn test_custom_request() {
3871        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3872
3873        let slot = rpc_client.get_slot().unwrap();
3874        assert_eq!(slot, 0);
3875
3876        let custom_slot = rpc_client
3877            .send::<Slot>(RpcRequest::Custom { method: "getSlot" }, Value::Null)
3878            .unwrap();
3879
3880        assert_eq!(slot, custom_slot);
3881    }
3882
3883    #[test]
3884    fn test_get_signature_status() {
3885        let signature = Signature::default();
3886
3887        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3888        let status = rpc_client.get_signature_status(&signature).unwrap();
3889        assert_eq!(status, Some(Ok(())));
3890
3891        let rpc_client = RpcClient::new_mock("sig_not_found".to_string());
3892        let status = rpc_client.get_signature_status(&signature).unwrap();
3893        assert_eq!(status, None);
3894
3895        let rpc_client = RpcClient::new_mock("account_in_use".to_string());
3896        let status = rpc_client.get_signature_status(&signature).unwrap();
3897        assert_eq!(status, Some(Err(TransactionError::AccountInUse)));
3898    }
3899
3900    #[test]
3901    fn test_send_and_confirm_transaction() {
3902        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3903
3904        let key = Keypair::new();
3905        let to = solana_sdk::pubkey::new_rand();
3906        let blockhash = Hash::default();
3907        let tx = system_transaction::transfer(&key, &to, 50, blockhash);
3908        let result = rpc_client.send_and_confirm_transaction(&tx);
3909        result.unwrap();
3910
3911        let rpc_client = RpcClient::new_mock("account_in_use".to_string());
3912        let result = rpc_client.send_and_confirm_transaction(&tx);
3913        assert!(result.is_err());
3914
3915        let rpc_client = RpcClient::new_mock("instruction_error".to_string());
3916        let result = rpc_client.send_and_confirm_transaction(&tx);
3917        assert_matches!(
3918            result.unwrap_err().kind(),
3919            ErrorKind::TransactionError(TransactionError::InstructionError(
3920                0,
3921                InstructionError::UninitializedAccount
3922            ))
3923        );
3924
3925        let rpc_client = RpcClient::new_mock("sig_not_found".to_string());
3926        let result = rpc_client.send_and_confirm_transaction(&tx);
3927        if let ErrorKind::Io(err) = result.unwrap_err().kind() {
3928            assert_eq!(err.kind(), io::ErrorKind::Other);
3929        }
3930    }
3931
3932    #[test]
3933    fn test_rpc_client_thread() {
3934        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3935        thread::spawn(move || rpc_client);
3936    }
3937
3938    // Regression test that the get_block_production_with_config
3939    // method internally creates the json params array correctly.
3940    #[test]
3941    fn get_block_production_with_config_no_error() -> ClientResult<()> {
3942        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3943
3944        let config = RpcBlockProductionConfig {
3945            identity: Some(Keypair::new().pubkey().to_string()),
3946            range: None,
3947            commitment: None,
3948        };
3949
3950        let prod = rpc_client.get_block_production_with_config(config)?.value;
3951
3952        assert!(!prod.by_identity.is_empty());
3953
3954        Ok(())
3955    }
3956
3957    #[test]
3958    fn test_get_latest_blockhash() {
3959        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3960
3961        let expected_blockhash: Hash = PUBKEY.parse().unwrap();
3962
3963        let blockhash = rpc_client.get_latest_blockhash().expect("blockhash ok");
3964        assert_eq!(blockhash, expected_blockhash);
3965
3966        let rpc_client = RpcClient::new_mock("fails".to_string());
3967
3968        let is_err = rpc_client.get_latest_blockhash().is_err();
3969        assert!(is_err);
3970    }
3971
3972    #[test]
3973    fn test_get_stake_minimum_delegation() {
3974        let expected_minimum_delegation: u64 = 123_456_789;
3975        let rpc_client = RpcClient::new_mock("succeeds".to_string());
3976
3977        // Test: without commitment
3978        {
3979            let actual_minimum_delegation = rpc_client.get_stake_minimum_delegation().unwrap();
3980            assert_eq!(expected_minimum_delegation, actual_minimum_delegation);
3981        }
3982
3983        // Test: with commitment
3984        {
3985            let actual_minimum_delegation = rpc_client
3986                .get_stake_minimum_delegation_with_commitment(CommitmentConfig::confirmed())
3987                .unwrap();
3988            assert_eq!(expected_minimum_delegation, actual_minimum_delegation);
3989        }
3990    }
3991
3992    #[test]
3993    fn test_get_program_accounts_with_config() {
3994        let program_id = Pubkey::new_unique();
3995        let pubkey = Pubkey::new_unique();
3996        let account = Account {
3997            lamports: 1_000_000,
3998            data: vec![],
3999            owner: program_id,
4000            executable: false,
4001            rent_epoch: 0,
4002        };
4003        let keyed_account = RpcKeyedAccount {
4004            pubkey: pubkey.to_string(),
4005            account: encode_ui_account(&pubkey, &account, UiAccountEncoding::Base64, None, None),
4006        };
4007        let expected_result = vec![(pubkey, account)];
4008        // Test: without context
4009        {
4010            let mocks: Mocks = [(
4011                RpcRequest::GetProgramAccounts,
4012                serde_json::to_value(OptionalContext::NoContext(vec![keyed_account.clone()]))
4013                    .unwrap(),
4014            )]
4015            .into_iter()
4016            .collect();
4017            let rpc_client = RpcClient::new_mock_with_mocks("mock_client".to_string(), mocks);
4018            let result = rpc_client
4019                .get_program_accounts_with_config(
4020                    &program_id,
4021                    RpcProgramAccountsConfig {
4022                        filters: None,
4023                        account_config: RpcAccountInfoConfig {
4024                            encoding: Some(UiAccountEncoding::Base64),
4025                            data_slice: None,
4026                            commitment: None,
4027                            min_context_slot: None,
4028                        },
4029                        with_context: None,
4030                        sort_results: None,
4031                    },
4032                )
4033                .unwrap();
4034            assert_eq!(expected_result, result);
4035        }
4036
4037        // Test: with context
4038        {
4039            let mocks: Mocks = [(
4040                RpcRequest::GetProgramAccounts,
4041                serde_json::to_value(OptionalContext::Context(Response {
4042                    context: RpcResponseContext {
4043                        slot: 1,
4044                        api_version: None,
4045                    },
4046                    value: vec![keyed_account],
4047                }))
4048                .unwrap(),
4049            )]
4050            .into_iter()
4051            .collect();
4052            let rpc_client = RpcClient::new_mock_with_mocks("mock_client".to_string(), mocks);
4053            let result = rpc_client
4054                .get_program_accounts_with_config(
4055                    &program_id,
4056                    RpcProgramAccountsConfig {
4057                        filters: None,
4058                        account_config: RpcAccountInfoConfig {
4059                            encoding: Some(UiAccountEncoding::Base64),
4060                            data_slice: None,
4061                            commitment: None,
4062                            min_context_slot: None,
4063                        },
4064                        with_context: Some(true),
4065                        sort_results: None,
4066                    },
4067                )
4068                .unwrap();
4069            assert_eq!(expected_result, result);
4070        }
4071    }
4072}