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