From 628ad589128fec113153e08b68ab6175af5550d9 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 23 Aug 2021 19:49:37 -0500 Subject: [PATCH] Document more RpcClient methods (#19236) * Document more RpcClient methods * Update client/src/rpc_client.rs Co-authored-by: Tyera Eulberg * Update RpcClient docs per feedback * Address review feedback Co-authored-by: Tyera Eulberg --- client/src/mock_sender.rs | 119 ++++- client/src/rpc_client.rs | 931 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 1007 insertions(+), 43 deletions(-) diff --git a/client/src/mock_sender.rs b/client/src/mock_sender.rs index 53db4f3290..bea3a9e99b 100644 --- a/client/src/mock_sender.rs +++ b/client/src/mock_sender.rs @@ -7,22 +7,31 @@ use { rpc_request::RpcRequest, rpc_response::{ Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcBlockhash, - RpcFees, RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, - RpcSupply, RpcVersionInfo, RpcVoteAccountStatus, StakeActivationState, + RpcConfirmedTransactionStatusWithSignature, RpcContactInfo, RpcFees, RpcPerfSample, + RpcResponseContext, RpcSimulateTransactionResult, RpcStakeActivation, RpcSupply, + RpcVersionInfo, RpcVoteAccountInfo, RpcVoteAccountStatus, StakeActivationState, }, rpc_sender::RpcSender, }, serde_json::{json, Number, Value}, solana_sdk::{ + clock::{Slot, UnixTimestamp}, epoch_info::EpochInfo, fee_calculator::{FeeCalculator, FeeRateGovernor}, instruction::InstructionError, + message::MessageHeader, signature::Signature, + sysvar::epoch_schedule::EpochSchedule, transaction::{self, Transaction, TransactionError}, }, - solana_transaction_status::{TransactionConfirmationStatus, TransactionStatus}, + solana_transaction_status::{ + EncodedConfirmedBlock, EncodedConfirmedTransaction, EncodedTransaction, + EncodedTransactionWithStatusMeta, Rewards, TransactionConfirmationStatus, + TransactionStatus, UiCompiledInstruction, UiMessage, UiRawMessage, UiTransaction, + UiTransactionEncoding, UiTransactionStatusMeta, + }, solana_version::Version, - std::{collections::HashMap, sync::RwLock}, + std::{collections::HashMap, net::SocketAddr, sync::RwLock}, }; pub const PUBKEY: &str = "7RoSF9fUmdphVCpabEoefH81WwrW7orsWonXWqTXkKV8"; @@ -167,6 +176,47 @@ impl RpcSender for MockSender { value: statuses, })? } + "getTransaction" => serde_json::to_value(EncodedConfirmedTransaction { + slot: 2, + transaction: EncodedTransactionWithStatusMeta { + transaction: EncodedTransaction::Json( + UiTransaction { + signatures: vec!["3AsdoALgZFuq2oUVWrDYhg2pNeaLJKPLf8hU2mQ6U8qJxeJ6hsrPVpMn9ma39DtfYCrDQSvngWRP8NnTpEhezJpE".to_string()], + message: UiMessage::Raw( + UiRawMessage { + header: MessageHeader { + num_required_signatures: 1, + num_readonly_signed_accounts: 0, + num_readonly_unsigned_accounts: 1, + }, + account_keys: vec![ + "C6eBmAXKg6JhJWkajGa5YRGUfG4YKXwbxF5Ufv7PtExZ".to_string(), + "2Gd5eoR5J4BV89uXbtunpbNhjmw3wa1NbRHxTHzDzZLX".to_string(), + "11111111111111111111111111111111".to_string(), + ], + recent_blockhash: "D37n3BSG71oUWcWjbZ37jZP7UfsxG2QMKeuALJ1PYvM6".to_string(), + instructions: vec![UiCompiledInstruction { + program_id_index: 2, + accounts: vec![0, 1], + data: "3Bxs49DitAvXtoDR".to_string(), + }], + }) + }), + meta: Some(UiTransactionStatusMeta { + err: None, + status: Ok(()), + fee: 0, + pre_balances: vec![499999999999999950, 50, 1], + post_balances: vec![499999999999999950, 50, 1], + inner_instructions: None, + log_messages: None, + pre_token_balances: None, + post_token_balances: None, + rewards: None, + }), + }, + block_time: Some(1628633791), + })?, "getTransactionCount" => json![1234], "getSlot" => json![0], "getMaxShredInsertSlot" => json![0], @@ -213,7 +263,7 @@ impl RpcSender for MockSender { } } "getStakeActivation" => json!(RpcStakeActivation { - state: StakeActivationState::Active, + state: StakeActivationState::Activating, active: 123, inactive: 12, }), @@ -240,7 +290,16 @@ impl RpcSender for MockSender { "getVoteAccounts" => { json!(RpcVoteAccountStatus { current: vec![], - delinquent: vec![], + delinquent: vec![RpcVoteAccountInfo { + vote_pubkey: PUBKEY.to_string(), + node_pubkey: PUBKEY.to_string(), + activated_stake: 0, + commission: 0, + epoch_vote_account: false, + epoch_credits: vec![], + last_vote: 0, + root_slot: Slot::default(), + }], }) } "sendTransaction" => { @@ -282,6 +341,54 @@ impl RpcSender for MockSender { context: RpcResponseContext { slot: 1 }, value: json!(Some(0)), })?, + "getClusterNodes" => serde_json::to_value(vec![RpcContactInfo { + pubkey: PUBKEY.to_string(), + gossip: Some(SocketAddr::from(([10, 239, 6, 48], 8899))), + tpu: Some(SocketAddr::from(([10, 239, 6, 48], 8856))), + rpc: Some(SocketAddr::from(([10, 239, 6, 48], 8899))), + version: Some("1.0.0 c375ce1f".to_string()), + feature_set: None, + shred_version: None, + }])?, + "getBlock" => serde_json::to_value(EncodedConfirmedBlock { + previous_blockhash: "mfcyqEXB3DnHXki6KjjmZck6YjmZLvpAByy2fj4nh6B".to_string(), + blockhash: "3Eq21vXNB5s86c62bVuUfTeaMif1N2kUqRPBmGRJhyTA".to_string(), + parent_slot: 429, + transactions: vec![EncodedTransactionWithStatusMeta { + transaction: EncodedTransaction::Binary( + "ju9xZWuDBX4pRxX2oZkTjxU5jB4SSTgEGhX8bQ8PURNzyzqKMPPpNvWihx8zUe\ + FfrbVNoAaEsNKZvGzAnTDy5bhNT9kt6KFCTBixpvrLCzg4M5UdFUQYrn1gdgjX\ + pLHxcaShD81xBNaFDgnA2nkkdHnKtZt4hVSfKAmw3VRZbjrZ7L2fKZBx21CwsG\ + hD6onjM2M3qZW5C8J6d1pj41MxKmZgPBSha3MyKkNLkAGFASK" + .to_string(), + UiTransactionEncoding::Base58, + ), + meta: None, + }], + rewards: Rewards::new(), + block_time: None, + block_height: Some(428), + })?, + "getBlocks" => serde_json::to_value(vec![1, 2, 3])?, + "getBlocksWithLimit" => serde_json::to_value(vec![1, 2, 3])?, + "getSignaturesForAddress" => { + serde_json::to_value(vec![RpcConfirmedTransactionStatusWithSignature { + signature: SIGNATURE.to_string(), + slot: 123, + err: None, + memo: None, + block_time: None, + confirmation_status: Some(TransactionConfirmationStatus::Finalized), + }])? + } + "getBlockTime" => serde_json::to_value(UnixTimestamp::default())?, + "getEpochSchedule" => serde_json::to_value(EpochSchedule::default())?, + "getRecentPerformanceSamples" => serde_json::to_value(vec![RpcPerfSample { + slot: 347873, + num_transactions: 125, + num_slots: 123, + sample_period_secs: 60, + }])?, _ => Value::Null, }; Ok(val) diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 91d349dfd7..5f7146bb5a 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -126,8 +126,8 @@ impl RpcClientConfig { /// # 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 latest_blockhash = Hash::default(); +/// # let tx = system_transaction::transfer(&key, &to, lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// let statuses = rpc_client.get_signature_statuses(&[signature])?.value; /// # Ok::<(), ClientError>(()) @@ -524,23 +524,20 @@ impl RpcClient { /// # use solana_client::{ /// # client_error::ClientError, /// # rpc_client::RpcClient, - /// # rpc_config::RpcSimulateTransactionConfig, /// # }; /// # 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()); /// // Transfer lamports from Alice to Bob and wait for confirmation /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// /// loop { @@ -582,14 +579,12 @@ impl RpcClient { /// # use solana_client::{ /// # client_error::ClientError, /// # rpc_client::RpcClient, - /// # rpc_config::RpcSimulateTransactionConfig, /// # }; /// # use solana_sdk::{ /// # commitment_config::CommitmentConfig, /// # signature::Signer, /// # signature::Signature, /// # signer::keypair::Keypair, - /// # hash::Hash, /// # system_transaction, /// # }; /// # use std::time::Duration; @@ -598,8 +593,8 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// /// loop { @@ -628,6 +623,51 @@ impl RpcClient { }) } + /// Submits a signed transaction to the network. + /// + /// Before a transaction is processed, the receiving node runs a "preflight + /// check" which verifies signatures, checks that the node is healthy, + /// and simulates the transaction. If the preflight check fails then an + /// error is returned immediately. Preflight checks can be disabled by + /// calling [`send_transaction_with_config`] and setting the + /// [`skip_preflight`] field of [`RpcSendTransactionConfig`] to `true`. + /// + /// This method does not wait for the transaction to be processed or + /// confirmed before returning successfully. To wait for the transaction to + /// be processed or confirmed, use the [`send_and_confirm_transaction`] + /// method. + /// + /// [`send_transaction_with_config`]: RpcClient::send_transaction_with_config + /// [`skip_preflight`]: crate::rpc_config::RpcSendTransactionConfig::skip_preflight + /// [`RpcSendTransactionConfig`]: crate::rpc_config::RpcSendTransactionConfig + /// [`send_and_confirm_transaction`]: RpcClient::send_and_confirm_transaction + /// + /// # Errors + /// + /// If the transaction is not signed then an error with kind [`RpcError`] is + /// returned, containing an [`RpcResponseError`] with `code` set to + /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]. + /// + /// If the preflight transaction simulation fails then an error with kind + /// [`RpcError`] is returned, containing an [`RpcResponseError`] with `code` + /// set to [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]. + /// + /// If the receiving node is unhealthy, e.g. it is not fully synced to + /// the cluster, then an error with kind [`RpcError`] is returned, + /// containing an [`RpcResponseError`] with `code` set to + /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. + /// + /// [`RpcResponseError`]: RpcError::RpcResponseError + /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE + /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE + /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY + /// + /// # RPC Reference + /// + /// This method is built on the [`sendTransaction`] RPC method. + /// + /// [`sendTransaction`]: https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction + /// /// # Examples /// /// ``` @@ -647,8 +687,8 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// # Ok::<(), ClientError>(()) /// ``` @@ -672,6 +712,52 @@ impl RpcClient { } } + /// Submits a signed transaction to the network. + /// + /// Before a transaction is processed, the receiving node runs a "preflight + /// check" which verifies signatures, checks that the node is healthy, and + /// simulates the transaction. If the preflight check fails then an error is + /// returned immediately. Preflight checks can be disabled by setting the + /// [`skip_preflight`] field of [`RpcSendTransactionConfig`] to `true`. + /// + /// This method does not wait for the transaction to be processed or + /// confirmed before returning successfully. To wait for the transaction to + /// be processed or confirmed, use the [`send_and_confirm_transaction`] + /// method. + /// + /// [`send_transaction_with_config`]: RpcClient::send_transaction_with_config + /// [`skip_preflight`]: crate::rpc_config::RpcSendTransactionConfig::skip_preflight + /// [`RpcSendTransactionConfig`]: crate::rpc_config::RpcSendTransactionConfig + /// [`send_and_confirm_transaction`]: RpcClient::send_and_confirm_transaction + /// + /// # Errors + /// + /// If preflight checks are enabled, if the transaction is not signed + /// then an error with kind [`RpcError`] is returned, containing an + /// [`RpcResponseError`] with `code` set to + /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]. + /// + /// If preflight checks are enabled, if the preflight transaction simulation + /// fails then an error with kind [`RpcError`] is returned, containing an + /// [`RpcResponseError`] with `code` set to + /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]. + /// + /// If the receiving node is unhealthy, e.g. it is not fully synced to + /// the cluster, then an error with kind [`RpcError`] is returned, + /// containing an [`RpcResponseError`] with `code` set to + /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]. + /// + /// [`RpcResponseError`]: RpcError::RpcResponseError + /// [`JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_TRANSACTION_SIGNATURE_VERIFICATION_FAILURE + /// [`JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE + /// [`JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY`]: crate::rpc_custom_error::JSON_RPC_SERVER_ERROR_NODE_UNHEALTHY + /// + /// # RPC Reference + /// + /// This method is built on the [`sendTransaction`] RPC method. + /// + /// [`sendTransaction`]: https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction + /// /// # Examples /// /// ``` @@ -692,8 +778,8 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let config = RpcSendTransactionConfig { /// skip_preflight: true, /// .. RpcSendTransactionConfig::default() @@ -771,6 +857,34 @@ impl RpcClient { } } + /// Simulates sending a transaction. + /// + /// If the transaction fails, then the [`err`] field of the returned + /// [`RpcSimulateTransactionResult`] will be `Some`. Any logs emitted from + /// the transaction are returned in the [`logs`] field. + /// + /// [`err`]: crate::rpc_response::RpcSimulateTransactionResult::err + /// [`logs`]: crate::rpc_response::RpcSimulateTransactionResult::logs + /// + /// Simulating a transaction is similar to the ["preflight check"] that is + /// run by default when sending a transaction. + /// + /// ["preflight check"]: https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction + /// + /// By default, signatures are not verified during simulation. To verify + /// signatures, call the [`simulate_transaction_with_config`] method, with + /// the [`sig_verify`] field of [`RpcSimulateTransactionConfig`] set to + /// `true`. + /// + /// [`simulate_transaction_with_config`]: RpcClient::simulate_transaction_with_config + /// [`sig_verify`]: crate::rpc_config::RpcSimulateTransactionConfig::sig_verify + /// + /// # RPC Reference + /// + /// This method is built on the [`simulateTransaction`] RPC method. + /// + /// [`simulateTransaction`]: https://docs.solana.com/developing/clients/jsonrpc-api#simulatetransaction + /// /// # Examples /// /// ``` @@ -791,8 +905,8 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let result = rpc_client.simulate_transaction(&tx)?; /// assert!(result.value.err.is_none()); /// # Ok::<(), ClientError>(()) @@ -810,6 +924,43 @@ impl RpcClient { ) } + /// Simulates sending a transaction. + /// + /// If the transaction fails, then the [`err`] field of the returned + /// [`RpcSimulateTransactionResult`] will be `Some`. Any logs emitted from + /// the transaction are returned in the [`logs`] field. + /// + /// [`err`]: crate::rpc_response::RpcSimulateTransactionResult::err + /// [`logs`]: crate::rpc_response::RpcSimulateTransactionResult::logs + /// + /// Simulating a transaction is similar to the ["preflight check"] that is + /// run by default when sending a transaction. + /// + /// ["preflight check"]: https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction + /// + /// By default, signatures are not verified during simulation. To verify + /// signatures, call the [`simulate_transaction_with_config`] method, with + /// the [`sig_verify`] field of [`RpcSimulateTransactionConfig`] set to + /// `true`. + /// + /// [`simulate_transaction_with_config`]: RpcClient::simulate_transaction_with_config + /// [`sig_verify`]: crate::rpc_config::RpcSimulateTransactionConfig::sig_verify + /// + /// This method can additionally query information about accounts by + /// including them in the [`accounts`] field of the + /// [`RpcSimulateTransactionConfig`] argument, in which case those results + /// are reported in the [`accounts`][accounts2] field of the returned + /// [`RpcSimulateTransactionResult`]. + /// + /// [`accounts`]: crate::rpc_config::RpcSimulateTransactionConfig::accounts + /// [accounts2]: crate::rpc_response::RpcSimulateTransactionResult::accounts + /// + /// # RPC Reference + /// + /// This method is built on the [`simulateTransaction`] RPC method. + /// + /// [`simulateTransaction`]: https://docs.solana.com/developing/clients/jsonrpc-api#simulatetransaction + /// /// # Examples /// /// ``` @@ -830,10 +981,10 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let config = RpcSimulateTransactionConfig { - /// sig_verify: false, + /// sig_verify: true, /// .. RpcSimulateTransactionConfig::default() /// }; /// let result = rpc_client.simulate_transaction_with_config( @@ -867,6 +1018,14 @@ impl RpcClient { ) } + /// Returns the highest slot that the node has a snapshot for. + /// + /// # RPC Reference + /// + /// This method corresponds directly to the [`getSnapshotSlot`] RPC method. + /// + /// [`getSnapshotSlot`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsnapshotslot + /// /// # Examples /// /// ``` @@ -882,6 +1041,34 @@ impl RpcClient { self.send(RpcRequest::GetSnapshotSlot, Value::Null) } + /// Check if a transaction has been processed with the default commitment level. + /// + /// If the transaction has been processed with the default commitment level, + /// then this method returns `Ok` of `Some`. If the transaction has not yet + /// been processed with the default commitment level, it returns `Ok` of + /// `None`. + /// + /// If the transaction has been processed with the default commitment level, + /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`. + /// If the transaction has peen processed with the default commitment level, + /// and the transaction failed, this method returns `Ok(Some(Err(_)))`, + /// where the interior error is type [`TransactionError`]. + /// + /// [`TransactionError`]: solana_sdk::transaction::TransactionError + /// + /// 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_statuse_with_commitment_and_history`][RpcClient::get_signature_status_with_commitment_and_history] + /// method. + /// + /// # RPC Reference + /// + /// This method is built on the [`getSignatureStatuses`] RPC method. + /// + /// [`getSignatureStatuses`]: https://docs.solana.com/developing/clients/jsonrpc-api#gitsignaturestatuses + /// /// # Examples /// /// ``` @@ -900,8 +1087,8 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// let status = rpc_client.get_signature_status(&signature)?; /// # Ok::<(), ClientError>(()) @@ -969,8 +1156,8 @@ impl RpcClient { /// // 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// /// let status = loop { @@ -1046,7 +1233,7 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; /// let statuses = rpc_client.get_signature_statuses_with_history(&[signature])?.value; /// if statuses[0].is_none() { /// println!("old transaction does not exist"); @@ -1066,6 +1253,34 @@ impl RpcClient { ) } + /// Check if a transaction has been processed with the given commitment level. + /// + /// If the transaction has been processed with the given commitment level, + /// then this method returns `Ok` of `Some`. If the transaction has not yet + /// been processed with the given commitment level, it returns `Ok` of + /// `None`. + /// + /// If the transaction has been processed with the given commitment level, + /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`. + /// If the transaction has peen processed with the given commitment level, + /// and the transaction failed, this method returns `Ok(Some(Err(_)))`, + /// where the interior error is type [`TransactionError`]. + /// + /// [`TransactionError`]: solana_sdk::transaction::TransactionError + /// + /// 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_statuse_with_commitment_and_history`][RpcClient::get_signature_status_with_commitment_and_history] + /// method. + /// + /// # RPC Reference + /// + /// This method is built on the [`getSignatureStatuses`] RPC method. + /// + /// [`getSignatureStatuses`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturestatuses + /// /// # Examples /// /// ``` @@ -1078,16 +1293,16 @@ impl RpcClient { /// # 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(); /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); + /// let signature = rpc_client.send_and_confirm_transaction(&tx)?; /// let commitment_config = CommitmentConfig::processed(); /// let status = rpc_client.get_signature_status_with_commitment( /// &signature, @@ -1110,6 +1325,30 @@ impl RpcClient { .map(|status_meta| status_meta.status)) } + /// Check if a transaction has been processed with the given commitment level. + /// + /// If the transaction has been processed with the given commitment level, + /// then this method returns `Ok` of `Some`. If the transaction has not yet + /// been processed with the given commitment level, it returns `Ok` of + /// `None`. + /// + /// If the transaction has been processed with the given commitment level, + /// and the transaction succeeded, this method returns `Ok(Some(Ok(())))`. + /// If the transaction has peen processed with the given commitment level, + /// and the transaction failed, this method returns `Ok(Some(Err(_)))`, + /// where the interior error is type [`TransactionError`]. + /// + /// [`TransactionError`]: solana_sdk::transaction::TransactionError + /// + /// This method optionally searches a node's full ledger history and (if + /// implemented) long-term storage. + /// + /// # RPC Reference + /// + /// This method is built on the [`getSignatureStatuses`] RPC method. + /// + /// [`getSignatureStatuses`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturestatuses + /// /// # Examples /// /// ``` @@ -1122,15 +1361,14 @@ impl RpcClient { /// # 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 latest_blockhash = rpc_client.get_latest_blockhash()?; + /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); /// let signature = rpc_client.send_transaction(&tx)?; /// let commitment_config = CommitmentConfig::processed(); /// let search_transaction_history = true; @@ -1159,6 +1397,12 @@ impl RpcClient { .map(|status_meta| status_meta.status)) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getSlot`] RPC method. + /// + /// [`getSlot`]: https://docs.solana.com/developing/clients/jsonrpc-api#getslot + /// /// # Examples /// /// ``` @@ -1174,6 +1418,12 @@ impl RpcClient { self.get_slot_with_commitment(self.commitment()) } + /// # RPC Reference + /// + /// This method is built on the [`getSlot`] RPC method. + /// + /// [`getSlot`]: https://docs.solana.com/developing/clients/jsonrpc-api#getslot + /// /// # Examples /// /// ``` @@ -1197,6 +1447,12 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method is corresponds directly to the [`getBlockHeight`] RPC method. + /// + /// [`getBlockHeight`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblockheight + /// /// # Examples /// /// ``` @@ -1212,6 +1468,12 @@ impl RpcClient { self.get_block_height_with_commitment(self.commitment()) } + /// # RPC Reference + /// + /// This method is built on the [`getBlockHeight`] RPC method. + /// + /// [`getBlockHeight`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblockheight + /// /// # Examples /// /// ``` @@ -1237,6 +1499,12 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getSlotLeaders`] RPC method. + /// + /// [`getSlotLeaders`]: https://docs.solana.com/developing/clients/jsonrpc-api#getslotleaders + /// /// # Examples /// /// ``` @@ -1269,6 +1537,12 @@ impl RpcClient { }) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getBlockProduction`] RPC method. + /// + /// [`getBlockProduction`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblockproduction + /// /// Get block production for the current epoch. /// /// # Examples @@ -1286,6 +1560,12 @@ impl RpcClient { self.send(RpcRequest::GetBlockProduction, Value::Null) } + /// # RPC Reference + /// + /// This method is built on the [`getBlockProduction`] RPC method. + /// + /// [`getBlockProduction`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblockproduction + /// /// # Examples /// /// ``` @@ -1326,25 +1606,69 @@ impl RpcClient { self.send(RpcRequest::GetBlockProduction, json!([config])) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getStakeActivation`] RPC method. + /// + /// [`getStakeActivation`]: https://docs.solana.com/developing/clients/jsonrpc-api#getstakeactivation + /// /// # Examples /// /// ``` /// # use solana_client::{ /// # rpc_client::RpcClient, /// # client_error::ClientError, + /// # rpc_response::StakeActivationState, /// # }; /// # use solana_sdk::{ /// # signer::keypair::Keypair, /// # signature::Signer, + /// # pubkey::Pubkey, + /// # stake, + /// # stake::state::{Authorized, Lockup}, + /// # transaction::Transaction /// # }; + /// # use std::str::FromStr; + /// # let alice = Keypair::new(); /// # 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()?; + /// // Find some vote account to delegate to + /// let vote_accounts = rpc_client.get_vote_accounts()?; + /// let vote_account = vote_accounts.current.get(0).unwrap_or_else(|| &vote_accounts.delinquent[0]); + /// let vote_account_pubkey = &vote_account.vote_pubkey; + /// let vote_account_pubkey = Pubkey::from_str(vote_account_pubkey).expect("pubkey"); + /// + /// // Create a stake account + /// let stake_account = Keypair::new(); + /// let stake_account_pubkey = stake_account.pubkey(); + /// + /// // Build the instructions to create new stake account, + /// // funded by alice, and delegate to a validator's vote account. + /// let instrs = stake::instruction::create_account_and_delegate_stake( + /// &alice.pubkey(), + /// &stake_account_pubkey, + /// &vote_account_pubkey, + /// &Authorized::auto(&stake_account_pubkey), + /// &Lockup::default(), + /// 1_000_000, + /// ); + /// + /// let latest_blockhash = rpc_client.get_latest_blockhash()?; + /// let tx = Transaction::new_signed_with_payer( + /// &instrs, + /// Some(&alice.pubkey()), + /// &[&alice, &stake_account], + /// latest_blockhash, + /// ); + /// + /// rpc_client.send_and_confirm_transaction(&tx)?; + /// + /// let epoch_info = rpc_client.get_epoch_info()?; /// let activation = rpc_client.get_stake_activation( - /// stake_account, - /// Some(epoch.epoch), + /// stake_account_pubkey, + /// Some(epoch_info.epoch), /// )?; + /// + /// assert_eq!(activation.state, StakeActivationState::Activating); /// # Ok::<(), ClientError>(()) /// ``` pub fn get_stake_activation( @@ -1364,6 +1688,12 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getSupply`] RPC method. + /// + /// [`getSupply`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsupply + /// /// # Examples /// /// ``` @@ -1379,6 +1709,12 @@ impl RpcClient { self.supply_with_commitment(self.commitment()) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getSupply`] RPC method. + /// + /// [`getSupply`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsupply + /// /// # Examples /// /// ``` @@ -1404,6 +1740,13 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getLargestAccounts`] RPC + /// method. + /// + /// [`getLargestAccounts`]: https://docs.solana.com/developing/clients/jsonrpc-api#getlargestaccounts + /// /// # Examples /// /// ``` @@ -1438,6 +1781,13 @@ impl RpcClient { self.send(RpcRequest::GetLargestAccounts, json!([config])) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getVoteAccounts`] + /// RPC method. + /// + /// [`getVoteAccounts`]: https://docs.solana.com/developing/clients/jsonrpc-api#getvoteaccounts + /// /// # Examples /// /// ``` @@ -1453,6 +1803,12 @@ impl RpcClient { self.get_vote_accounts_with_commitment(self.commitment()) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getVoteAccounts`] RPC method. + /// + /// [`getVoteAccounts`]: https://docs.solana.com/developing/clients/jsonrpc-api#getvoteaccounts + /// /// # Examples /// /// ``` @@ -1478,6 +1834,16 @@ impl RpcClient { }) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getVoteAccounts`] + /// RPC method with the `Commitment` option set to `processed`, the + /// `votePubkey` option set to new-generated `vote_pubkey`, the + /// `keepUnstakedDelinquents` option set to `true`, the + /// `delinquentSlotDistance` option set to `10` + /// + /// [`getVoteAccounts`]: https://docs.solana.com/developing/clients/jsonrpc-api#getvoteaccounts + /// /// # Examples /// /// ``` @@ -1545,14 +1911,74 @@ impl RpcClient { Ok(()) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getClusterNodes`] + /// RPC method. + /// + /// [`getClusterNodes`]: https://docs.solana.com/developing/clients/jsonrpc-api#getclusternodes + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # rpc_client::RpcClient, + /// # client_error::ClientError, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// let cluster_nodes = rpc_client.get_cluster_nodes()?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_cluster_nodes(&self) -> ClientResult> { self.send(RpcRequest::GetClusterNodes, Value::Null) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getBlock`] RPC + /// method. + /// + /// [`getBlock`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblock + /// + /// # 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()?; + /// let block = rpc_client.get_block(slot)?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_block(&self, slot: Slot) -> ClientResult { self.get_block_with_encoding(slot, UiTransactionEncoding::Json) } + /// # RPC Reference + /// + /// This method is built on the [`getBlock`] RPC method. + /// + /// [`getBlock`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblock + /// + /// # Examples + /// + /// ``` + /// # use solana_transaction_status::UiTransactionEncoding; + /// # use solana_client::{ + /// # rpc_client::RpcClient, + /// # client_error::ClientError, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let slot = rpc_client.get_slot()?; + /// let encoding = UiTransactionEncoding::Base58; + /// let block = rpc_client.get_block_with_encoding( + /// slot, + /// encoding, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_block_with_encoding( &self, slot: Slot, @@ -1564,6 +1990,38 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method is built on the [`getBlock`] RPC method. + /// + /// [`getBlock`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblock + /// + /// # Examples + /// + /// ``` + /// # use solana_transaction_status::{ + /// # TransactionDetails, + /// # UiTransactionEncoding, + /// # }; + /// # use solana_client::{ + /// # rpc_client::RpcClient, + /// # rpc_config::RpcBlockConfig, + /// # client_error::ClientError, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let slot = rpc_client.get_slot()?; + /// let config = RpcBlockConfig { + /// encoding: Some(UiTransactionEncoding::Base58), + /// transaction_details: Some(TransactionDetails::None), + /// rewards: Some(true), + /// commitment: None, + /// }; + /// let block = rpc_client.get_block_with_config( + /// slot, + /// config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_block_with_config( &self, slot: Slot, @@ -1607,6 +2065,26 @@ impl RpcClient { self.send(RpcRequest::GetConfirmedBlock, json!([slot, config])) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getBlocks`] RPC + /// method. + /// + /// [`getBlocks`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblocks + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # rpc_client::RpcClient, + /// # client_error::ClientError, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let start_slot = 0; + /// # let end_slot = 3; + /// let blocks = rpc_client.get_blocks(start_slot, Some(end_slot))?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_blocks(&self, start_slot: Slot, end_slot: Option) -> ClientResult> { self.send( self.maybe_map_request(RpcRequest::GetBlocks)?, @@ -1614,6 +2092,32 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method is built on the [`getBlocks`] RPC method. + /// + /// [`getBlocks`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblocks + /// + /// # 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 start_slot = 2; + /// # let end_slot = 4; + /// // Method does not support commitment below `confirmed` + /// let commitment_config = CommitmentConfig::confirmed(); + /// let blocks = rpc_client.get_blocks_with_commitment( + /// start_slot, + /// Some(end_slot), + /// commitment_config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_blocks_with_commitment( &self, start_slot: Slot, @@ -1632,6 +2136,26 @@ impl RpcClient { self.send(self.maybe_map_request(RpcRequest::GetBlocks)?, json) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getBlocksWithLimit`] + /// RPC method. + /// + /// [`getBlocksWithLimit`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblockswithlimit + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # rpc_client::RpcClient, + /// # client_error::ClientError, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let start_slot = 2; + /// let limit = 3; + /// let blocks = rpc_client.get_blocks_with_limit(start_slot, limit)?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_blocks_with_limit(&self, start_slot: Slot, limit: usize) -> ClientResult> { self.send( self.maybe_map_request(RpcRequest::GetBlocksWithLimit)?, @@ -1639,6 +2163,31 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method is built on the [`getBlocksWithLimit`] RPC method. + /// + /// [`getBlocksWithLimit`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblockswithlimit + /// + /// # 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 start_slot = 2; + /// let limit = 3; + /// let commitment_config = CommitmentConfig::confirmed(); + /// let blocks = rpc_client.get_blocks_with_limit_and_commitment( + /// start_slot, + /// limit, + /// commitment_config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_blocks_with_limit_and_commitment( &self, start_slot: Slot, @@ -1728,6 +2277,32 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method corresponds directly to the + /// [`getSignaturesForAddress`] RPC method. + /// + /// [`getSignaturesForAddress`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturesforaddress + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # use solana_sdk::{ + /// # signature::Signer, + /// # signer::keypair::Keypair, + /// # system_transaction, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let alice = Keypair::new(); + /// let signatures = rpc_client.get_signatures_for_address( + /// &alice.pubkey(), + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_signatures_for_address( &self, address: &Pubkey, @@ -1738,6 +2313,46 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method is built on the [`getSignaturesForAddress`] RPC + /// method. + /// + /// [`getSignaturesForAddress`]: https://docs.solana.com/developing/clients/jsonrpc-api#getsignaturesforaddress + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # rpc_client::GetConfirmedSignaturesForAddress2Config, + /// # }; + /// # use solana_sdk::{ + /// # signature::Signer, + /// # signer::keypair::Keypair, + /// # system_transaction, + /// # commitment_config::CommitmentConfig, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let alice = Keypair::new(); + /// # let bob = Keypair::new(); + /// # let lamports = 50; + /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; + /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); + /// # let signature = rpc_client.send_and_confirm_transaction(&tx)?; + /// let config = GetConfirmedSignaturesForAddress2Config { + /// before: None, + /// until: None, + /// limit: Some(3), + /// commitment: Some(CommitmentConfig::confirmed()), + /// }; + /// let signatures = rpc_client.get_signatures_for_address_with_config( + /// &alice.pubkey(), + /// config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_signatures_for_address_with_config( &self, address: &Pubkey, @@ -1798,6 +2413,41 @@ impl RpcClient { Ok(result) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getTransaction`] RPC + /// method. + /// + /// [`getTransaction`]: https://docs.solana.com/developing/clients/jsonrpc-api#gettransaction + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # use solana_sdk::{ + /// # signature::Signer, + /// # signature::Signature, + /// # signer::keypair::Keypair, + /// # system_transaction, + /// # }; + /// # use solana_transaction_status::UiTransactionEncoding; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let alice = Keypair::new(); + /// # let bob = Keypair::new(); + /// # let lamports = 50; + /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; + /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); + /// let signature = rpc_client.send_and_confirm_transaction(&tx)?; + /// + /// let transaction = rpc_client.get_transaction( + /// &signature, + /// UiTransactionEncoding::Json, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_transaction( &self, signature: &Signature, @@ -1809,6 +2459,46 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method is built on the [`getTransaction`] RPC method. + /// + /// [`getTransaction`]: https://docs.solana.com/developing/clients/jsonrpc-api#gettransaction + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # rpc_config::RpcTransactionConfig, + /// # }; + /// # use solana_sdk::{ + /// # signature::Signer, + /// # signature::Signature, + /// # signer::keypair::Keypair, + /// # system_transaction, + /// # commitment_config::CommitmentConfig, + /// # }; + /// # use solana_transaction_status::UiTransactionEncoding; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let alice = Keypair::new(); + /// # let bob = Keypair::new(); + /// # let lamports = 50; + /// # let latest_blockhash = rpc_client.get_latest_blockhash()?; + /// # let tx = system_transaction::transfer(&alice, &bob.pubkey(), lamports, latest_blockhash); + /// let signature = rpc_client.send_and_confirm_transaction(&tx)?; + /// let config = RpcTransactionConfig { + /// encoding: Some(UiTransactionEncoding::Json), + /// commitment: Some(CommitmentConfig::confirmed()), + /// }; + /// + /// let transaction = rpc_client.get_transaction_with_config( + /// &signature, + /// config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_transaction_with_config( &self, signature: &Signature, @@ -1852,6 +2542,25 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getBlockTime`] RPC + /// method. + /// + /// [`getBlockTime`]: https://docs.solana.com/developing/clients/jsonrpc-api#getblocktime + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let slot = rpc_client.get_slot()?; + /// let block_time = rpc_client.get_block_time(slot)?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_block_time(&self, slot: Slot) -> ClientResult { let request = RpcRequest::GetBlockTime; let response = self.sender.send(request, json!([slot])); @@ -1869,10 +2578,48 @@ impl RpcClient { .map_err(|err| err.into_with_request(request))? } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getEpochInfo`] RPC method. + /// + /// [`getEpochInfo`]: https://docs.solana.com/developing/clients/jsonrpc-api#getepochinfo + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// let epoch_info = rpc_client.get_epoch_info()?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_epoch_info(&self) -> ClientResult { self.get_epoch_info_with_commitment(self.commitment()) } + /// # RPC Reference + /// + /// This method is built on the [`getEpochInfo`] RPC method. + /// + /// [`getEpochInfo`]: https://docs.solana.com/developing/clients/jsonrpc-api#getepochinfo + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # use solana_sdk::commitment_config::CommitmentConfig; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// let commitment_config = CommitmentConfig::confirmed(); + /// let epoch_info = rpc_client.get_epoch_info_with_commitment( + /// commitment_config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_epoch_info_with_commitment( &self, commitment_config: CommitmentConfig, @@ -1883,6 +2630,27 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getLeaderSchedule`] RPC method. + /// + /// [`getLeaderSchedule`]: https://docs.solana.com/developing/clients/jsonrpc-api#getleaderschedule + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # use solana_sdk::commitment_config::CommitmentConfig; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let slot = rpc_client.get_slot()?; + /// let leader_schedule = rpc_client.get_leader_schedule( + /// Some(slot), + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_leader_schedule( &self, slot: Option, @@ -1890,6 +2658,29 @@ impl RpcClient { self.get_leader_schedule_with_commitment(slot, self.commitment()) } + /// # RPC Reference + /// + /// This method is built on the [`getLeaderSchedule`] RPC method. + /// + /// [`getLeaderSchedule`]: https://docs.solana.com/developing/clients/jsonrpc-api#getleaderschedule + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # use solana_sdk::commitment_config::CommitmentConfig; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let slot = rpc_client.get_slot()?; + /// let commitment_config = CommitmentConfig::processed(); + /// let leader_schedule = rpc_client.get_leader_schedule_with_commitment( + /// Some(slot), + /// commitment_config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_leader_schedule_with_commitment( &self, slot: Option, @@ -1904,6 +2695,34 @@ impl RpcClient { ) } + /// # RPC Reference + /// + /// This method is built on the [`getLeaderSchedule`] RPC method. + /// + /// [`getLeaderSchedule`]: https://docs.solana.com/developing/clients/jsonrpc-api#getleaderschedule + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # use solana_client::rpc_config::RpcLeaderScheduleConfig; + /// # use solana_sdk::commitment_config::CommitmentConfig; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// # let slot = rpc_client.get_slot()?; + /// # let validator_pubkey_str = "7AYmEYBBetok8h5L3Eo3vi3bDWnjNnaFbSXfSNYV5ewB".to_string(); + /// let config = RpcLeaderScheduleConfig { + /// identity: Some(validator_pubkey_str), + /// commitment: Some(CommitmentConfig::processed()), + /// }; + /// let leader_schedule = rpc_client.get_leader_schedule_with_config( + /// Some(slot), + /// config, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_leader_schedule_with_config( &self, slot: Option, @@ -1912,10 +2731,48 @@ impl RpcClient { self.send(RpcRequest::GetLeaderSchedule, json!([slot, config])) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getEpochSchedule`] + /// RPC method. + /// + /// [`getEpochSchedule`]: https://docs.solana.com/developing/clients/jsonrpc-api#getepochschedule + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// let epoch_schedule = rpc_client.get_epoch_schedule()?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_epoch_schedule(&self) -> ClientResult { self.send(RpcRequest::GetEpochSchedule, Value::Null) } + /// # RPC Reference + /// + /// This method corresponds directly to the [`getRecentPerformanceSamples`] RPC method. + /// + /// [`getRecentPerformanceSamples`]: https://docs.solana.com/developing/clients/jsonrpc-api#getrecentperformancesamples + /// + /// # Examples + /// + /// ``` + /// # use solana_client::{ + /// # client_error::ClientError, + /// # rpc_client::RpcClient, + /// # }; + /// # let rpc_client = RpcClient::new_mock("succeeds".to_string()); + /// let limit = Some(10); + /// let performance_samples = rpc_client.get_recent_performance_samples( + /// limit, + /// )?; + /// # Ok::<(), ClientError>(()) + /// ``` pub fn get_recent_performance_samples( &self, limit: Option,