safecoin_client/
rpc_client.rs

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