Add more API documentation for Rust RpcClient (#19021)
* Add doc links to Transaction API docs * Add more RpcClient API docs * Reflow some rpc_client docs * Update client/src/rpc_client.rs Co-authored-by: Tyera Eulberg <teulberg@gmail.com> * Update client/src/rpc_client.rs Co-authored-by: Tyera Eulberg <teulberg@gmail.com> * Update client/src/rpc_client.rs Co-authored-by: Tyera Eulberg <teulberg@gmail.com> * Update sdk/src/transaction.rs Co-authored-by: Tyera Eulberg <teulberg@gmail.com> * Update RpcClient docs per review Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
This commit is contained in:
@ -3,10 +3,12 @@
|
|||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
client_error::Result,
|
client_error::Result,
|
||||||
|
rpc_config::RpcBlockProductionConfig,
|
||||||
rpc_request::RpcRequest,
|
rpc_request::RpcRequest,
|
||||||
rpc_response::{
|
rpc_response::{
|
||||||
Response, RpcBlockProduction, RpcBlockProductionRange, RpcResponseContext,
|
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange,
|
||||||
RpcSimulateTransactionResult, RpcVersionInfo,
|
RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, RpcSupply,
|
||||||
|
RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState,
|
||||||
},
|
},
|
||||||
rpc_sender::RpcSender,
|
rpc_sender::RpcSender,
|
||||||
},
|
},
|
||||||
@ -159,6 +161,78 @@ impl RpcSender for MockSender {
|
|||||||
"getSlot" => json![0],
|
"getSlot" => json![0],
|
||||||
"getMaxShredInsertSlot" => json![0],
|
"getMaxShredInsertSlot" => json![0],
|
||||||
"requestAirdrop" => Value::String(Signature::new(&[8; 64]).to_string()),
|
"requestAirdrop" => Value::String(Signature::new(&[8; 64]).to_string()),
|
||||||
|
"getSnapshotSlot" => Value::Number(Number::from(0)),
|
||||||
|
"getBlockHeight" => Value::Number(Number::from(1234)),
|
||||||
|
"getSlotLeaders" => json!([PUBKEY]),
|
||||||
|
"getBlockProduction" => {
|
||||||
|
if params.is_null() {
|
||||||
|
json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: RpcBlockProduction {
|
||||||
|
by_identity: HashMap::new(),
|
||||||
|
range: RpcBlockProductionRange {
|
||||||
|
first_slot: 1,
|
||||||
|
last_slot: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let config: Vec<RpcBlockProductionConfig> =
|
||||||
|
serde_json::from_value(params).unwrap();
|
||||||
|
let config = config[0].clone();
|
||||||
|
let mut by_identity = HashMap::new();
|
||||||
|
by_identity.insert(config.identity.unwrap(), (1, 123));
|
||||||
|
let config_range = config.range.unwrap_or_default();
|
||||||
|
|
||||||
|
json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: RpcBlockProduction {
|
||||||
|
by_identity,
|
||||||
|
range: RpcBlockProductionRange {
|
||||||
|
first_slot: config_range.first_slot,
|
||||||
|
last_slot: {
|
||||||
|
if let Some(last_slot) = config_range.last_slot {
|
||||||
|
last_slot
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"getStakeActivation" => json!(RpcStakeActivation {
|
||||||
|
state: StakeActivationState::Active,
|
||||||
|
active: 123,
|
||||||
|
inactive: 12,
|
||||||
|
}),
|
||||||
|
"getSupply" => json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: RpcSupply {
|
||||||
|
total: 100000000,
|
||||||
|
circulating: 50000,
|
||||||
|
non_circulating: 20000,
|
||||||
|
non_circulating_accounts: vec![PUBKEY.to_string()],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
"getLargestAccounts" => {
|
||||||
|
let rpc_account_balance = RpcAccountBalance {
|
||||||
|
address: PUBKEY.to_string(),
|
||||||
|
lamports: 10000,
|
||||||
|
};
|
||||||
|
|
||||||
|
json!(Response {
|
||||||
|
context: RpcResponseContext { slot: 1 },
|
||||||
|
value: vec![rpc_account_balance],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"getVoteAccounts" => {
|
||||||
|
json!(RpcVoteAccountStatus {
|
||||||
|
current: vec![],
|
||||||
|
delinquent: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
"sendTransaction" => {
|
"sendTransaction" => {
|
||||||
let signature = if self.url == "malicious" {
|
let signature = if self.url == "malicious" {
|
||||||
Signature::new(&[8; 64]).to_string()
|
Signature::new(&[8; 64]).to_string()
|
||||||
@ -187,19 +261,6 @@ impl RpcSender for MockSender {
|
|||||||
feature_set: Some(version.feature_set),
|
feature_set: Some(version.feature_set),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
"getBlockProduction" => {
|
|
||||||
let map = vec![(PUBKEY.to_string(), (1, 1))].into_iter().collect();
|
|
||||||
json!(Response {
|
|
||||||
context: RpcResponseContext { slot: 1 },
|
|
||||||
value: RpcBlockProduction {
|
|
||||||
by_identity: map,
|
|
||||||
range: RpcBlockProductionRange {
|
|
||||||
first_slot: 0,
|
|
||||||
last_slot: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => Value::Null,
|
_ => Value::Null,
|
||||||
};
|
};
|
||||||
Ok(val)
|
Ok(val)
|
||||||
|
@ -78,34 +78,66 @@ impl RpcClientConfig {
|
|||||||
/// [Solana JSON-RPC protocol][jsonprot]. It is the primary Rust interface for
|
/// [Solana JSON-RPC protocol][jsonprot]. It is the primary Rust interface for
|
||||||
/// querying and transacting with the network from external programs.
|
/// querying and transacting with the network from external programs.
|
||||||
///
|
///
|
||||||
|
/// This type builds on the underlying RPC protocol, adding extra features such
|
||||||
|
/// as timeout handling, retries, and waiting on transaction commitment levels.
|
||||||
|
/// Some methods simply pass through to the underlying RPC protocol. Not all RPC
|
||||||
|
/// methods are encapsulated by this type, but `RpcClient` does expose a generic
|
||||||
|
/// [`send`](RpcClient::send) method for making any [`RpcRequest`].
|
||||||
|
///
|
||||||
|
/// The documentation for most `RpcClient` methods contains an "RPC Reference"
|
||||||
|
/// section that links to the documentation for the underlying JSON-RPC method.
|
||||||
|
/// The documentation for `RpcClient` does not reproduce the documentation for
|
||||||
|
/// the underlying JSON-RPC methods. Thus reading both is necessary for complete
|
||||||
|
/// understanding.
|
||||||
|
///
|
||||||
/// `RpcClient`s generally communicate over HTTP on port 8899, a typical server
|
/// `RpcClient`s generally communicate over HTTP on port 8899, a typical server
|
||||||
/// URL being "http://localhost:8899".
|
/// URL being "http://localhost:8899".
|
||||||
///
|
///
|
||||||
/// By default, requests to confirm transactions are only completed once those
|
/// By default, requests to confirm transactions only succeed once those
|
||||||
/// transactions are finalized, meaning they are definitely permanently
|
/// transactions are finalized, meaning they are definitely permanently
|
||||||
/// committed. Transactions can be confirmed with less finality by creating
|
/// committed. Transactions can be confirmed with less finality by creating
|
||||||
/// `RpcClient` with an explicit [`CommitmentConfig`], or by calling the various
|
/// `RpcClient` with an explicit [`CommitmentConfig`], or by calling the various
|
||||||
/// `_with_commitment` methods, like
|
/// `_with_commitment` methods, like
|
||||||
/// [`RpcClient::confirm_transaction_with_commitment`].
|
/// [`RpcClient::confirm_transaction_with_commitment`].
|
||||||
///
|
///
|
||||||
|
/// [jsonprot]: https://docs.solana.com/developing/clients/jsonrpc-api
|
||||||
|
/// [JSON-RPC]: https://www.jsonrpc.org/specification
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Methods on `RpcClient` return
|
||||||
|
/// [`client_error::Result`][crate::client_error::Result], and many of them
|
||||||
|
/// return the [`RpcResult`][crate::rpc_response::RpcResult] typedef, which
|
||||||
|
/// contains [`Response<T>`][crate::rpc_response::Response] on `Ok`. Both
|
||||||
|
/// `client_error::Result` and [`RpcResult`] contain `ClientError` on error. In
|
||||||
|
/// the case of `RpcResult`, the actual return value is in the
|
||||||
|
/// [`value`][crate::rpc_response::Response::value] field, with RPC contextual
|
||||||
|
/// information in the [`context`][crate::rpc_response::Response::context]
|
||||||
|
/// field, so it is common for the value to be accessed with `?.value`, as in
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_sdk::system_transaction;
|
||||||
|
/// # use solana_client::rpc_client::RpcClient;
|
||||||
|
/// # use solana_client::client_error::ClientError;
|
||||||
|
/// # use solana_sdk::signature::{Keypair, Signer};
|
||||||
|
/// # use solana_sdk::hash::Hash;
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let key = Keypair::new();
|
||||||
|
/// # let to = solana_sdk::pubkey::new_rand();
|
||||||
|
/// # let lamports = 50;
|
||||||
|
/// # let recent_blockhash = Hash::default();
|
||||||
|
/// # let tx = system_transaction::transfer(&key, &to, lamports, recent_blockhash);
|
||||||
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
|
/// let statuses = rpc_client.get_signature_statuses(&[signature])?.value;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// Requests may timeout, in which case they return a [`ClientError`] where the
|
/// Requests may timeout, in which case they return a [`ClientError`] where the
|
||||||
/// [`ClientErrorKind`] is [`ClientErrorKind::Reqwest`], and where the interior
|
/// [`ClientErrorKind`] is [`ClientErrorKind::Reqwest`], and where the interior
|
||||||
/// [`reqwest::Error`](crate::client_error::reqwest::Error)s
|
/// [`reqwest::Error`](crate::client_error::reqwest::Error)s
|
||||||
/// [`is_timeout`](crate::client_error::reqwest::Error::is_timeout) method
|
/// [`is_timeout`](crate::client_error::reqwest::Error::is_timeout) method
|
||||||
/// returns `true`. The default timeout is 30 seconds, and may be changed by
|
/// returns `true`. The default timeout is 30 seconds, and may be changed by
|
||||||
/// calling an appropriate constructor with a `timeout` parameter.
|
/// calling an appropriate constructor with a `timeout` parameter.
|
||||||
///
|
|
||||||
/// `RpcClient` encapsulates an [`RpcSender`], which implements the underlying
|
|
||||||
/// RPC protocol. On top of `RpcSender` it adds methods for common tasks, while
|
|
||||||
/// re-exposing the underlying RPC sending functionality through the
|
|
||||||
/// [`send`][RpcClient::send] method.
|
|
||||||
///
|
|
||||||
/// [jsonprot]: https://docs.solana.com/developing/clients/jsonrpc-api
|
|
||||||
/// [JSON-RPC]: https://www.jsonrpc.org/specification
|
|
||||||
///
|
|
||||||
/// While `RpcClient` encapsulates an abstract `RpcSender`, it is most commonly
|
|
||||||
/// created with an [`HttpSender`], communicating over HTTP, usually on port
|
|
||||||
/// 8899. It can also be created with [`MockSender`] during testing.
|
|
||||||
pub struct RpcClient {
|
pub struct RpcClient {
|
||||||
sender: Box<dyn RpcSender + Send + Sync + 'static>,
|
sender: Box<dyn RpcSender + Send + Sync + 'static>,
|
||||||
config: RpcClientConfig,
|
config: RpcClientConfig,
|
||||||
@ -311,11 +343,10 @@ impl RpcClient {
|
|||||||
/// # use solana_client::{
|
/// # use solana_client::{
|
||||||
/// # rpc_client::RpcClient,
|
/// # rpc_client::RpcClient,
|
||||||
/// # rpc_request::RpcRequest,
|
/// # rpc_request::RpcRequest,
|
||||||
|
/// # rpc_response::{Response, RpcResponseContext},
|
||||||
/// # };
|
/// # };
|
||||||
/// # use std::collections::HashMap;
|
/// # use std::collections::HashMap;
|
||||||
/// # use serde_json::json;
|
/// # use serde_json::json;
|
||||||
/// use solana_client::rpc_response::{Response, RpcResponseContext};
|
|
||||||
///
|
|
||||||
/// // Create a mock with a custom repsonse to the `GetBalance` request
|
/// // Create a mock with a custom repsonse to the `GetBalance` request
|
||||||
/// let account_balance = 50;
|
/// let account_balance = 50;
|
||||||
/// let account_balance_response = json!(Response {
|
/// let account_balance_response = json!(Response {
|
||||||
@ -414,6 +445,17 @@ impl RpcClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the configured default commitment level.
|
||||||
|
///
|
||||||
|
/// The commitment config may be specified during construction, and
|
||||||
|
/// determines how thoroughly committed a transaction must be when waiting
|
||||||
|
/// for its confirmation or otherwise checking for confirmation. If not
|
||||||
|
/// specified, the default commitment level is
|
||||||
|
/// [`Finalized`](CommitmentLevel::Finalized).
|
||||||
|
///
|
||||||
|
/// The default commitment level is overridden when calling methods that
|
||||||
|
/// explicitly provide a [`CommitmentConfig`], like
|
||||||
|
/// [`RpcClient::confirm_transaction_with_commitment`].
|
||||||
pub fn commitment(&self) -> CommitmentConfig {
|
pub fn commitment(&self) -> CommitmentConfig {
|
||||||
self.config.commitment_config
|
self.config.commitment_config
|
||||||
}
|
}
|
||||||
@ -455,6 +497,26 @@ impl RpcClient {
|
|||||||
Ok(request)
|
Ok(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check the confirmation status of a transaction.
|
||||||
|
///
|
||||||
|
/// Returns `true` if the given transaction succeeded and has been committed
|
||||||
|
/// with the configured commitment level, which can be retrieved with
|
||||||
|
/// the [`commitment`](RpcClient::commitment) method.
|
||||||
|
///
|
||||||
|
/// Note that this method does not wait for a transaction to be confirmed
|
||||||
|
/// — it only checks whether a transaction has been confirmed. To
|
||||||
|
/// submit a transaction and wait for it to confirm, use
|
||||||
|
/// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
|
||||||
|
///
|
||||||
|
/// _This method returns `false` if the transaction failed, even if it has
|
||||||
|
/// been confirmed._
|
||||||
|
///
|
||||||
|
/// # RPC Reference
|
||||||
|
///
|
||||||
|
/// This method is built on the [`getSignatureStatuses`] RPC method.
|
||||||
|
///
|
||||||
|
/// [`getSignatureStatuses`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturestatuses
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -464,21 +526,28 @@ impl RpcClient {
|
|||||||
/// # rpc_config::RpcSimulateTransactionConfig,
|
/// # rpc_config::RpcSimulateTransactionConfig,
|
||||||
/// # };
|
/// # };
|
||||||
/// # use solana_sdk::{
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
/// # signature::Signature,
|
/// # signature::Signature,
|
||||||
/// # signer::keypair::Keypair,
|
/// # signer::keypair::Keypair,
|
||||||
/// # hash::Hash,
|
/// # hash::Hash,
|
||||||
/// # system_transaction,
|
/// # system_transaction,
|
||||||
/// # };
|
/// # };
|
||||||
|
/// # use std::time::Duration;
|
||||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
/// // Transfer lamports from some account to a random account
|
/// // Transfer lamports from Alice to Bob and wait for confirmation
|
||||||
/// let key = Keypair::new();
|
/// # let alice = Keypair::new();
|
||||||
/// let to = solana_sdk::pubkey::new_rand();
|
/// # let bob = Keypair::new();
|
||||||
/// let lamports = 50;
|
/// # let lamports = 50;
|
||||||
/// # let recent_blockhash = Hash::default();
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
/// let tx = system_transaction::transfer(&key, &to, lamports, recent_blockhash);
|
/// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
/// let signature = rpc_client.send_transaction(&tx)?;
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
/// let confirmed = rpc_client.confirm_transaction(&signature)?;
|
///
|
||||||
/// assert!(confirmed);
|
/// loop {
|
||||||
|
/// let confirmed = rpc_client.confirm_transaction(&signature)?;
|
||||||
|
/// if confirmed {
|
||||||
|
/// break;
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
/// # Ok::<(), ClientError>(())
|
/// # Ok::<(), ClientError>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult<bool> {
|
pub fn confirm_transaction(&self, signature: &Signature) -> ClientResult<bool> {
|
||||||
@ -487,6 +556,25 @@ impl RpcClient {
|
|||||||
.value)
|
.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check the confirmation status of a transaction.
|
||||||
|
///
|
||||||
|
/// Returns an [`RpcResult`] with value `true` if the given transaction
|
||||||
|
/// succeeded and has been committed with the given commitment level.
|
||||||
|
///
|
||||||
|
/// Note that this method does not wait for a transaction to be confirmed
|
||||||
|
/// — it only checks whether a transaction has been confirmed. To
|
||||||
|
/// submit a transaction and wait for it to confirm, use
|
||||||
|
/// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
|
||||||
|
///
|
||||||
|
/// _This method returns an [`RpcResult`] with value `false` if the
|
||||||
|
/// transaction failed, even if it has been confirmed._
|
||||||
|
///
|
||||||
|
/// # RPC Reference
|
||||||
|
///
|
||||||
|
/// This method is built on the [`getSignatureStatuses`] RPC method.
|
||||||
|
///
|
||||||
|
/// [`getSignatureStatuses`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturestatuses
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@ -497,25 +585,29 @@ impl RpcClient {
|
|||||||
/// # };
|
/// # };
|
||||||
/// # use solana_sdk::{
|
/// # use solana_sdk::{
|
||||||
/// # commitment_config::CommitmentConfig,
|
/// # commitment_config::CommitmentConfig,
|
||||||
|
/// # signature::Signer,
|
||||||
/// # signature::Signature,
|
/// # signature::Signature,
|
||||||
/// # signer::keypair::Keypair,
|
/// # signer::keypair::Keypair,
|
||||||
/// # hash::Hash,
|
/// # hash::Hash,
|
||||||
/// # system_transaction,
|
/// # system_transaction,
|
||||||
/// # };
|
/// # };
|
||||||
|
/// # use std::time::Duration;
|
||||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
/// // Transfer lamports from some account to a random account
|
/// // Transfer lamports from Alice to Bob and wait for confirmation
|
||||||
/// let key = Keypair::new();
|
/// # let alice = Keypair::new();
|
||||||
/// let to = solana_sdk::pubkey::new_rand();
|
/// # let bob = Keypair::new();
|
||||||
/// let lamports = 50;
|
/// # let lamports = 50;
|
||||||
/// # let recent_blockhash = Hash::default();
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
/// let tx = system_transaction::transfer(&key, &to, lamports, recent_blockhash);
|
/// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
/// let signature = rpc_client.send_transaction(&tx)?;
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
/// let commitment_config = CommitmentConfig::confirmed();
|
///
|
||||||
/// let confirmed = rpc_client.confirm_transaction_with_commitment(
|
/// loop {
|
||||||
/// &signature,
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
/// commitment_config,
|
/// let confirmed = rpc_client.confirm_transaction_with_commitment(&signature, commitment_config)?;
|
||||||
/// )?;
|
/// if confirmed.value {
|
||||||
/// assert!(confirmed.value);
|
/// break;
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
/// # Ok::<(), ClientError>(())
|
/// # Ok::<(), ClientError>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub fn confirm_transaction_with_commitment(
|
pub fn confirm_transaction_with_commitment(
|
||||||
@ -543,21 +635,20 @@ impl RpcClient {
|
|||||||
/// # rpc_client::RpcClient,
|
/// # rpc_client::RpcClient,
|
||||||
/// # };
|
/// # };
|
||||||
/// # use solana_sdk::{
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
/// # signature::Signature,
|
/// # signature::Signature,
|
||||||
/// # signer::keypair::Keypair,
|
/// # signer::keypair::Keypair,
|
||||||
/// # hash::Hash,
|
/// # hash::Hash,
|
||||||
/// # system_transaction,
|
/// # system_transaction,
|
||||||
/// # };
|
/// # };
|
||||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
/// // Transfer lamports from some account to a random account
|
/// // Transfer lamports from Alice to Bob
|
||||||
/// let key = Keypair::new();
|
/// # let alice = Keypair::new();
|
||||||
/// let to = solana_sdk::pubkey::new_rand();
|
/// # let bob = Keypair::new();
|
||||||
/// let lamports = 50;
|
/// # let lamports = 50;
|
||||||
/// # let recent_blockhash = Hash::default();
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
/// let tx = system_transaction::transfer(&key, &to, lamports, recent_blockhash);
|
/// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
/// let signature = rpc_client.send_transaction(&tx)?;
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
/// let confirmed = rpc_client.confirm_transaction(&signature)?;
|
|
||||||
/// assert!(confirmed);
|
|
||||||
/// # Ok::<(), ClientError>(())
|
/// # Ok::<(), ClientError>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult<Signature> {
|
pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult<Signature> {
|
||||||
@ -589,18 +680,19 @@ impl RpcClient {
|
|||||||
/// # rpc_config::RpcSendTransactionConfig,
|
/// # rpc_config::RpcSendTransactionConfig,
|
||||||
/// # };
|
/// # };
|
||||||
/// # use solana_sdk::{
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
/// # signature::Signature,
|
/// # signature::Signature,
|
||||||
/// # signer::keypair::Keypair,
|
/// # signer::keypair::Keypair,
|
||||||
/// # hash::Hash,
|
/// # hash::Hash,
|
||||||
/// # system_transaction,
|
/// # system_transaction,
|
||||||
/// # };
|
/// # };
|
||||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
/// // Transfer lamports from some account to a random account
|
/// // Transfer lamports from Alice to Bob
|
||||||
/// let key = Keypair::new();
|
/// # let alice = Keypair::new();
|
||||||
/// let to = solana_sdk::pubkey::new_rand();
|
/// # let bob = Keypair::new();
|
||||||
/// let lamports = 50;
|
/// # let lamports = 50;
|
||||||
/// # let recent_blockhash = Hash::default();
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
/// let tx = system_transaction::transfer(&key, &to, lamports, recent_blockhash);
|
/// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
/// let config = RpcSendTransactionConfig {
|
/// let config = RpcSendTransactionConfig {
|
||||||
/// skip_preflight: true,
|
/// skip_preflight: true,
|
||||||
/// .. RpcSendTransactionConfig::default()
|
/// .. RpcSendTransactionConfig::default()
|
||||||
@ -609,8 +701,6 @@ impl RpcClient {
|
|||||||
/// &tx,
|
/// &tx,
|
||||||
/// config,
|
/// config,
|
||||||
/// )?;
|
/// )?;
|
||||||
/// let confirmed = rpc_client.confirm_transaction(&signature)?;
|
|
||||||
/// assert!(confirmed);
|
|
||||||
/// # Ok::<(), ClientError>(())
|
/// # Ok::<(), ClientError>(())
|
||||||
/// ```
|
/// ```
|
||||||
pub fn send_transaction_with_config(
|
pub fn send_transaction_with_config(
|
||||||
@ -689,18 +779,19 @@ impl RpcClient {
|
|||||||
/// # rpc_response::RpcSimulateTransactionResult,
|
/// # rpc_response::RpcSimulateTransactionResult,
|
||||||
/// # };
|
/// # };
|
||||||
/// # use solana_sdk::{
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
/// # signature::Signature,
|
/// # signature::Signature,
|
||||||
/// # signer::keypair::Keypair,
|
/// # signer::keypair::Keypair,
|
||||||
/// # hash::Hash,
|
/// # hash::Hash,
|
||||||
/// # system_transaction,
|
/// # system_transaction,
|
||||||
/// # };
|
/// # };
|
||||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
/// // Transfer lamports from some account to a random account
|
/// // Transfer lamports from Alice to Bob
|
||||||
/// let key = Keypair::new();
|
/// # let alice = Keypair::new();
|
||||||
/// let to = solana_sdk::pubkey::new_rand();
|
/// # let bob = Keypair::new();
|
||||||
/// let lamports = 50;
|
/// # let lamports = 50;
|
||||||
/// # let recent_blockhash = Hash::default();
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
/// let tx = system_transaction::transfer(&key, &to, lamports, recent_blockhash);
|
/// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
/// let result = rpc_client.simulate_transaction(&tx)?;
|
/// let result = rpc_client.simulate_transaction(&tx)?;
|
||||||
/// assert!(result.value.err.is_none());
|
/// assert!(result.value.err.is_none());
|
||||||
/// # Ok::<(), ClientError>(())
|
/// # Ok::<(), ClientError>(())
|
||||||
@ -728,18 +819,18 @@ impl RpcClient {
|
|||||||
/// # rpc_response::RpcSimulateTransactionResult,
|
/// # rpc_response::RpcSimulateTransactionResult,
|
||||||
/// # };
|
/// # };
|
||||||
/// # use solana_sdk::{
|
/// # use solana_sdk::{
|
||||||
/// # signature::Signature,
|
/// # signature::Signer,
|
||||||
/// # signer::keypair::Keypair,
|
/// # signer::keypair::Keypair,
|
||||||
/// # hash::Hash,
|
/// # hash::Hash,
|
||||||
/// # system_transaction,
|
/// # system_transaction,
|
||||||
/// # };
|
/// # };
|
||||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
/// // Transfer lamports from some account to a random account
|
/// // Transfer lamports from Alice to Bob
|
||||||
/// let key = Keypair::new();
|
/// # let alice = Keypair::new();
|
||||||
/// let to = solana_sdk::pubkey::new_rand();
|
/// # let bob = Keypair::new();
|
||||||
/// let lamports = 50;
|
/// # let lamports = 50;
|
||||||
/// # let recent_blockhash = Hash::default();
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
/// let tx = system_transaction::transfer(&key, &to, lamports, recent_blockhash);
|
/// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
/// let config = RpcSimulateTransactionConfig {
|
/// let config = RpcSimulateTransactionConfig {
|
||||||
/// sig_verify: false,
|
/// sig_verify: false,
|
||||||
/// .. RpcSimulateTransactionConfig::default()
|
/// .. RpcSimulateTransactionConfig::default()
|
||||||
@ -775,10 +866,45 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let slot = rpc_client.get_snapshot_slot()?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_snapshot_slot(&self) -> ClientResult<Slot> {
|
pub fn get_snapshot_slot(&self) -> ClientResult<Slot> {
|
||||||
self.send(RpcRequest::GetSnapshotSlot, Value::Null)
|
self.send(RpcRequest::GetSnapshotSlot, Value::Null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # signature::Signature,
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # hash::Hash,
|
||||||
|
/// # system_transaction,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let alice = Keypair::new();
|
||||||
|
/// # let bob = Keypair::new();
|
||||||
|
/// # let lamports = 50;
|
||||||
|
/// # let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
|
/// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
|
/// let status = rpc_client.get_signature_status(&signature)?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_signature_status(
|
pub fn get_signature_status(
|
||||||
&self,
|
&self,
|
||||||
signature: &Signature,
|
signature: &Signature,
|
||||||
@ -786,6 +912,77 @@ impl RpcClient {
|
|||||||
self.get_signature_status_with_commitment(signature, self.commitment())
|
self.get_signature_status_with_commitment(signature, self.commitment())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the statuses of a list of transaction signatures.
|
||||||
|
///
|
||||||
|
/// The returned vector of [`TransactionStatus`] has the same length as the
|
||||||
|
/// input slice.
|
||||||
|
///
|
||||||
|
/// For any transaction that has not been processed by the network, the
|
||||||
|
/// value of the corresponding entry in the returned vector is `None`. As a
|
||||||
|
/// result, a transaction that has recently been submitted will not have a
|
||||||
|
/// status immediately.
|
||||||
|
///
|
||||||
|
/// To submit a transaction and wait for it to confirm, use
|
||||||
|
/// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
|
||||||
|
///
|
||||||
|
/// This function ignores the configured confirmation level, and returns the
|
||||||
|
/// transaction status whatever it is. It does not wait for transactions to
|
||||||
|
/// be processed.
|
||||||
|
///
|
||||||
|
/// This function only searches a node's recent history, including all
|
||||||
|
/// recent slots, plus up to
|
||||||
|
/// [`MAX_RECENT_BLOCKHASHES`][solana_sdk::clock::MAX_RECENT_BLOCKHASHES]
|
||||||
|
/// rooted slots. To search the full transaction history use the
|
||||||
|
/// [`get_signature_statuses_with_history`][RpcClient::get_signature_statuses_with_history]
|
||||||
|
/// method.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Any individual `TransactionStatus` may have triggered an error during
|
||||||
|
/// processing, in which case its [`err`][`TransactionStatus::err`] field
|
||||||
|
/// will be `Some`.
|
||||||
|
///
|
||||||
|
/// # RPC Reference
|
||||||
|
///
|
||||||
|
/// This method corresponds directly to the [`getSignatureStatuses`] RPC method.
|
||||||
|
///
|
||||||
|
/// [`getSignatureStatuses`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturestatuses
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # signature::Signature,
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # hash::Hash,
|
||||||
|
/// # system_transaction,
|
||||||
|
/// # };
|
||||||
|
/// # use std::time::Duration;
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let alice = Keypair::new();
|
||||||
|
/// // Send lamports from Alice to Bob and wait for the transaction to be processed
|
||||||
|
/// # let bob = Keypair::new();
|
||||||
|
/// # let lamports = 50;
|
||||||
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
|
/// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
|
///
|
||||||
|
/// let status = loop {
|
||||||
|
/// let statuses = rpc_client.get_signature_statuses(&[signature])?.value;
|
||||||
|
/// if let Some(status) = statuses[0].clone() {
|
||||||
|
/// break status;
|
||||||
|
/// }
|
||||||
|
/// std::thread::sleep(Duration::from_millis(100));
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// assert!(status.err.is_none());
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_signature_statuses(
|
pub fn get_signature_statuses(
|
||||||
&self,
|
&self,
|
||||||
signatures: &[Signature],
|
signatures: &[Signature],
|
||||||
@ -794,6 +991,67 @@ impl RpcClient {
|
|||||||
self.send(RpcRequest::GetSignatureStatuses, json!([signatures]))
|
self.send(RpcRequest::GetSignatureStatuses, json!([signatures]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the statuses of a list of transaction signatures.
|
||||||
|
///
|
||||||
|
/// The returned vector of [`TransactionStatus`] has the same length as the
|
||||||
|
/// input slice.
|
||||||
|
///
|
||||||
|
/// For any transaction that has not been processed by the network, the
|
||||||
|
/// value of the corresponding entry in the returned vector is `None`. As a
|
||||||
|
/// result, a transaction that has recently been submitted will not have a
|
||||||
|
/// status immediately.
|
||||||
|
///
|
||||||
|
/// To submit a transaction and wait for it to confirm, use
|
||||||
|
/// [`send_and_confirm_transaction`][RpcClient::send_and_confirm_transaction].
|
||||||
|
///
|
||||||
|
/// This function ignores the configured confirmation level, and returns the
|
||||||
|
/// transaction status whatever it is. It does not wait for transactions to
|
||||||
|
/// be processed.
|
||||||
|
///
|
||||||
|
/// This function searches a node's full ledger history and (if implemented) long-term storage. To search for
|
||||||
|
/// transactions in recent slots only use the
|
||||||
|
/// [`get_signature_statuses`][RpcClient::get_signature_statuses] method.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Any individual `TransactionStatus` may have triggered an error during
|
||||||
|
/// processing, in which case its [`err`][`TransactionStatus::err`] field
|
||||||
|
/// will be `Some`.
|
||||||
|
///
|
||||||
|
/// # RPC Reference
|
||||||
|
///
|
||||||
|
/// This method corresponds directly to the [`getSignatureStatuses`] RPC
|
||||||
|
/// method, with the `searchTransactionHistory` configuration option set to
|
||||||
|
/// `true`.
|
||||||
|
///
|
||||||
|
/// [`getSignatureStatuses`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturestatuses
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # signature::Signature,
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # hash::Hash,
|
||||||
|
/// # system_transaction,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let alice = Keypair::new();
|
||||||
|
/// # fn get_old_transaction_signature() -> Signature { Signature::default() }
|
||||||
|
/// // Check if an old transaction exists
|
||||||
|
/// let signature = get_old_transaction_signature();
|
||||||
|
/// let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
|
/// let statuses = rpc_client.get_signature_statuses_with_history(&[signature])?.value;
|
||||||
|
/// if statuses[0].is_none() {
|
||||||
|
/// println!("old transaction does not exist");
|
||||||
|
/// }
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_signature_statuses_with_history(
|
pub fn get_signature_statuses_with_history(
|
||||||
&self,
|
&self,
|
||||||
signatures: &[Signature],
|
signatures: &[Signature],
|
||||||
@ -807,6 +1065,35 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # commitment_config::CommitmentConfig,
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # signature::Signature,
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # hash::Hash,
|
||||||
|
/// # system_transaction,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let alice = Keypair::new();
|
||||||
|
/// # let bob = Keypair::new();
|
||||||
|
/// # let lamports = 50;
|
||||||
|
/// # let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
|
/// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
|
/// let status = rpc_client.get_signature_status_with_commitment(
|
||||||
|
/// &signature,
|
||||||
|
/// commitment_config,
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_signature_status_with_commitment(
|
pub fn get_signature_status_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
signature: &Signature,
|
signature: &Signature,
|
||||||
@ -822,6 +1109,37 @@ impl RpcClient {
|
|||||||
.map(|status_meta| status_meta.status))
|
.map(|status_meta| status_meta.status))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # commitment_config::CommitmentConfig,
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # signature::Signature,
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # hash::Hash,
|
||||||
|
/// # system_transaction,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let alice = Keypair::new();
|
||||||
|
/// # let bob = Keypair::new();
|
||||||
|
/// # let lamports = 50;
|
||||||
|
/// # let (recent_blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||||
|
/// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, recent_blockhash);
|
||||||
|
/// let signature = rpc_client.send_transaction(&tx)?;
|
||||||
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
|
/// let search_transaction_history = true;
|
||||||
|
/// let status = rpc_client.get_signature_status_with_commitment_and_history(
|
||||||
|
/// &signature,
|
||||||
|
/// commitment_config,
|
||||||
|
/// search_transaction_history,
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_signature_status_with_commitment_and_history(
|
pub fn get_signature_status_with_commitment_and_history(
|
||||||
&self,
|
&self,
|
||||||
signature: &Signature,
|
signature: &Signature,
|
||||||
@ -840,10 +1158,34 @@ impl RpcClient {
|
|||||||
.map(|status_meta| status_meta.status))
|
.map(|status_meta| status_meta.status))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let slot = rpc_client.get_slot()?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_slot(&self) -> ClientResult<Slot> {
|
pub fn get_slot(&self) -> ClientResult<Slot> {
|
||||||
self.get_slot_with_commitment(self.commitment())
|
self.get_slot_with_commitment(self.commitment())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::commitment_config::CommitmentConfig;
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
|
/// let slot = rpc_client.get_slot_with_commitment(commitment_config)?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_slot_with_commitment(
|
pub fn get_slot_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
@ -854,10 +1196,36 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let block_height = rpc_client.get_block_height()?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_block_height(&self) -> ClientResult<u64> {
|
pub fn get_block_height(&self) -> ClientResult<u64> {
|
||||||
self.get_block_height_with_commitment(self.commitment())
|
self.get_block_height_with_commitment(self.commitment())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::commitment_config::CommitmentConfig;
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
|
/// let block_height = rpc_client.get_block_height_with_commitment(
|
||||||
|
/// commitment_config,
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_block_height_with_commitment(
|
pub fn get_block_height_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
@ -868,6 +1236,20 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::slot_history::Slot;
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let start_slot = 1;
|
||||||
|
/// let limit = 3;
|
||||||
|
/// let leaders = rpc_client.get_slot_leaders(start_slot, limit)?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_slot_leaders(&self, start_slot: Slot, limit: u64) -> ClientResult<Vec<Pubkey>> {
|
pub fn get_slot_leaders(&self, start_slot: Slot, limit: u64) -> ClientResult<Vec<Pubkey>> {
|
||||||
self.send(RpcRequest::GetSlotLeaders, json!([start_slot, limit]))
|
self.send(RpcRequest::GetSlotLeaders, json!([start_slot, limit]))
|
||||||
.and_then(|slot_leaders: Vec<String>| {
|
.and_then(|slot_leaders: Vec<String>| {
|
||||||
@ -886,11 +1268,56 @@ impl RpcClient {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get block production for the current epoch
|
/// Get block production for the current epoch.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let production = rpc_client.get_block_production()?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_block_production(&self) -> RpcResult<RpcBlockProduction> {
|
pub fn get_block_production(&self) -> RpcResult<RpcBlockProduction> {
|
||||||
self.send(RpcRequest::GetBlockProduction, Value::Null)
|
self.send(RpcRequest::GetBlockProduction, Value::Null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # rpc_config::RpcBlockProductionConfig,
|
||||||
|
/// # rpc_config::RpcBlockProductionConfigRange,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # commitment_config::CommitmentConfig,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let start_slot = 1;
|
||||||
|
/// # let limit = 3;
|
||||||
|
/// let leader = rpc_client.get_slot_leaders(start_slot, limit)?;
|
||||||
|
/// let leader = leader[0];
|
||||||
|
/// let range = RpcBlockProductionConfigRange {
|
||||||
|
/// first_slot: 0,
|
||||||
|
/// last_slot: Some(0),
|
||||||
|
/// };
|
||||||
|
/// let config = RpcBlockProductionConfig {
|
||||||
|
/// identity: Some(leader.to_string()),
|
||||||
|
/// range: Some(range),
|
||||||
|
/// commitment: Some(CommitmentConfig::processed()),
|
||||||
|
/// };
|
||||||
|
/// let production = rpc_client.get_block_production_with_config(
|
||||||
|
/// config
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_block_production_with_config(
|
pub fn get_block_production_with_config(
|
||||||
&self,
|
&self,
|
||||||
config: RpcBlockProductionConfig,
|
config: RpcBlockProductionConfig,
|
||||||
@ -898,6 +1325,27 @@ impl RpcClient {
|
|||||||
self.send(RpcRequest::GetBlockProduction, json!([config]))
|
self.send(RpcRequest::GetBlockProduction, json!([config]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let stake_account_keypair = Keypair::new();
|
||||||
|
/// let stake_account = stake_account_keypair.pubkey();
|
||||||
|
/// let epoch = rpc_client.get_epoch_info()?;
|
||||||
|
/// let activation = rpc_client.get_stake_activation(
|
||||||
|
/// stake_account,
|
||||||
|
/// Some(epoch.epoch),
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_stake_activation(
|
pub fn get_stake_activation(
|
||||||
&self,
|
&self,
|
||||||
stake_account: Pubkey,
|
stake_account: Pubkey,
|
||||||
@ -915,10 +1363,36 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let supply = rpc_client.supply()?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn supply(&self) -> RpcResult<RpcSupply> {
|
pub fn supply(&self) -> RpcResult<RpcSupply> {
|
||||||
self.supply_with_commitment(self.commitment())
|
self.supply_with_commitment(self.commitment())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::commitment_config::CommitmentConfig;
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
|
/// let supply = rpc_client.supply_with_commitment(
|
||||||
|
/// commitment_config,
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn supply_with_commitment(
|
pub fn supply_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
@ -929,6 +1403,27 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # rpc_config::RpcLargestAccountsConfig,
|
||||||
|
/// # rpc_config::RpcLargestAccountsFilter,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::commitment_config::CommitmentConfig;
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
|
/// let config = RpcLargestAccountsConfig {
|
||||||
|
/// commitment: Some(commitment_config),
|
||||||
|
/// filter: Some(RpcLargestAccountsFilter::Circulating),
|
||||||
|
/// };
|
||||||
|
/// let accounts = rpc_client.get_largest_accounts_with_config(
|
||||||
|
/// config,
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_largest_accounts_with_config(
|
pub fn get_largest_accounts_with_config(
|
||||||
&self,
|
&self,
|
||||||
config: RpcLargestAccountsConfig,
|
config: RpcLargestAccountsConfig,
|
||||||
@ -942,10 +1437,36 @@ impl RpcClient {
|
|||||||
self.send(RpcRequest::GetLargestAccounts, json!([config]))
|
self.send(RpcRequest::GetLargestAccounts, json!([config]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let accounts = rpc_client.get_vote_accounts()?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_vote_accounts(&self) -> ClientResult<RpcVoteAccountStatus> {
|
pub fn get_vote_accounts(&self) -> ClientResult<RpcVoteAccountStatus> {
|
||||||
self.get_vote_accounts_with_commitment(self.commitment())
|
self.get_vote_accounts_with_commitment(self.commitment())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_sdk::commitment_config::CommitmentConfig;
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// let commitment_config = CommitmentConfig::processed();
|
||||||
|
/// let accounts = rpc_client.get_vote_accounts_with_commitment(
|
||||||
|
/// commitment_config,
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_vote_accounts_with_commitment(
|
pub fn get_vote_accounts_with_commitment(
|
||||||
&self,
|
&self,
|
||||||
commitment_config: CommitmentConfig,
|
commitment_config: CommitmentConfig,
|
||||||
@ -956,6 +1477,34 @@ impl RpcClient {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use solana_client::{
|
||||||
|
/// # rpc_client::RpcClient,
|
||||||
|
/// # client_error::ClientError,
|
||||||
|
/// # rpc_config::RpcGetVoteAccountsConfig,
|
||||||
|
/// # };
|
||||||
|
/// # use solana_sdk::{
|
||||||
|
/// # signer::keypair::Keypair,
|
||||||
|
/// # signature::Signer,
|
||||||
|
/// # commitment_config::CommitmentConfig,
|
||||||
|
/// # };
|
||||||
|
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
/// # let vote_keypair = Keypair::new();
|
||||||
|
/// let vote_pubkey = vote_keypair.pubkey();
|
||||||
|
/// let commitment = CommitmentConfig::processed();
|
||||||
|
/// let config = RpcGetVoteAccountsConfig {
|
||||||
|
/// vote_pubkey: Some(vote_pubkey.to_string()),
|
||||||
|
/// commitment: Some(commitment),
|
||||||
|
/// keep_unstaked_delinquents: Some(true),
|
||||||
|
/// delinquent_slot_distance: Some(10),
|
||||||
|
/// };
|
||||||
|
/// let accounts = rpc_client.get_vote_accounts_with_config(
|
||||||
|
/// config,
|
||||||
|
/// )?;
|
||||||
|
/// # Ok::<(), ClientError>(())
|
||||||
|
/// ```
|
||||||
pub fn get_vote_accounts_with_config(
|
pub fn get_vote_accounts_with_config(
|
||||||
&self,
|
&self,
|
||||||
config: RpcGetVoteAccountsConfig,
|
config: RpcGetVoteAccountsConfig,
|
||||||
@ -2392,6 +2941,7 @@ impl RpcClient {
|
|||||||
T: serde::de::DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
assert!(params.is_array() || params.is_null());
|
assert!(params.is_array() || params.is_null());
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.sender
|
.sender
|
||||||
.send(request, params)
|
.send(request, params)
|
||||||
@ -2479,7 +3029,9 @@ mod tests {
|
|||||||
use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder};
|
use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder};
|
||||||
use serde_json::Number;
|
use serde_json::Number;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
instruction::InstructionError, signature::Keypair, system_transaction,
|
instruction::InstructionError,
|
||||||
|
signature::{Keypair, Signer},
|
||||||
|
system_transaction,
|
||||||
transaction::TransactionError,
|
transaction::TransactionError,
|
||||||
};
|
};
|
||||||
use std::{io, sync::mpsc::channel, thread};
|
use std::{io, sync::mpsc::channel, thread};
|
||||||
@ -2666,7 +3218,7 @@ mod tests {
|
|||||||
let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||||
|
|
||||||
let config = RpcBlockProductionConfig {
|
let config = RpcBlockProductionConfig {
|
||||||
identity: None,
|
identity: Some(Keypair::new().pubkey().to_string()),
|
||||||
range: None,
|
range: None,
|
||||||
commitment: None,
|
commitment: None,
|
||||||
};
|
};
|
||||||
|
@ -113,9 +113,12 @@ impl From<SanitizeError> for TransactionError {
|
|||||||
#[frozen_abi(digest = "AAeVxvWiiotwxDLxKLxsfgkA6ndW74nVbaAEb6cwJYqR")]
|
#[frozen_abi(digest = "AAeVxvWiiotwxDLxKLxsfgkA6ndW74nVbaAEb6cwJYqR")]
|
||||||
#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize, AbiExample)]
|
#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize, AbiExample)]
|
||||||
pub struct Transaction {
|
pub struct Transaction {
|
||||||
/// A set of digital signatures of `account_keys`, `program_ids`, `recent_blockhash`, and `instructions`, signed by the first
|
/// A set of digital signatures of a serialized [`Message`], signed by the
|
||||||
/// signatures.len() keys of account_keys
|
/// first `signatures.len()` keys of [`account_keys`].
|
||||||
/// NOTE: Serialization-related changes must be paired with the direct read at sigverify.
|
///
|
||||||
|
/// [`account_keys`]: Message::account_keys
|
||||||
|
///
|
||||||
|
// NOTE: Serialization-related changes must be paired with the direct read at sigverify.
|
||||||
#[serde(with = "short_vec")]
|
#[serde(with = "short_vec")]
|
||||||
pub signatures: Vec<Signature>,
|
pub signatures: Vec<Signature>,
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user