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