| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- use {
- crate::response::RpcSimulateTransactionResult,
- serde_json::{json, Value},
- solana_clock::Slot,
- solana_pubkey::Pubkey,
- std::fmt,
- thiserror::Error,
- };
- #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
- pub enum RpcRequest {
- Custom { method: &'static str },
- DeregisterNode,
- GetAccountInfo,
- GetBalance,
- GetBlock,
- GetBlockHeight,
- GetBlockProduction,
- GetBlocks,
- GetBlocksWithLimit,
- GetBlockTime,
- GetClusterNodes,
- GetEpochInfo,
- GetEpochSchedule,
- GetFeeForMessage,
- GetFirstAvailableBlock,
- GetGenesisHash,
- GetHealth,
- GetIdentity,
- GetInflationGovernor,
- GetInflationRate,
- GetInflationReward,
- GetLargestAccounts,
- GetLatestBlockhash,
- GetLeaderSchedule,
- GetMaxRetransmitSlot,
- GetMaxShredInsertSlot,
- GetMinimumBalanceForRentExemption,
- GetMultipleAccounts,
- GetProgramAccounts,
- GetRecentPerformanceSamples,
- GetRecentPrioritizationFees,
- GetHighestSnapshotSlot,
- GetSignaturesForAddress,
- GetSignatureStatuses,
- GetSlot,
- GetSlotLeader,
- GetSlotLeaders,
- GetStorageTurn,
- GetStorageTurnRate,
- GetSlotsPerSegment,
- GetStakeMinimumDelegation,
- GetStoragePubkeysForSlot,
- GetSupply,
- GetTokenAccountBalance,
- GetTokenAccountsByDelegate,
- GetTokenAccountsByOwner,
- GetTokenLargestAccounts,
- GetTokenSupply,
- GetTransaction,
- GetTransactionCount,
- GetVersion,
- GetVoteAccounts,
- IsBlockhashValid,
- MinimumLedgerSlot,
- RegisterNode,
- RequestAirdrop,
- SendTransaction,
- SimulateTransaction,
- SignVote,
- }
- #[allow(deprecated)]
- impl fmt::Display for RpcRequest {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let method = match self {
- RpcRequest::Custom { method } => method,
- RpcRequest::DeregisterNode => "deregisterNode",
- RpcRequest::GetAccountInfo => "getAccountInfo",
- RpcRequest::GetBalance => "getBalance",
- RpcRequest::GetBlock => "getBlock",
- RpcRequest::GetBlockHeight => "getBlockHeight",
- RpcRequest::GetBlockProduction => "getBlockProduction",
- RpcRequest::GetBlocks => "getBlocks",
- RpcRequest::GetBlocksWithLimit => "getBlocksWithLimit",
- RpcRequest::GetBlockTime => "getBlockTime",
- RpcRequest::GetClusterNodes => "getClusterNodes",
- RpcRequest::GetEpochInfo => "getEpochInfo",
- RpcRequest::GetEpochSchedule => "getEpochSchedule",
- RpcRequest::GetFeeForMessage => "getFeeForMessage",
- RpcRequest::GetFirstAvailableBlock => "getFirstAvailableBlock",
- RpcRequest::GetGenesisHash => "getGenesisHash",
- RpcRequest::GetHealth => "getHealth",
- RpcRequest::GetIdentity => "getIdentity",
- RpcRequest::GetInflationGovernor => "getInflationGovernor",
- RpcRequest::GetInflationRate => "getInflationRate",
- RpcRequest::GetInflationReward => "getInflationReward",
- RpcRequest::GetLargestAccounts => "getLargestAccounts",
- RpcRequest::GetLatestBlockhash => "getLatestBlockhash",
- RpcRequest::GetLeaderSchedule => "getLeaderSchedule",
- RpcRequest::GetMaxRetransmitSlot => "getMaxRetransmitSlot",
- RpcRequest::GetMaxShredInsertSlot => "getMaxShredInsertSlot",
- RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption",
- RpcRequest::GetMultipleAccounts => "getMultipleAccounts",
- RpcRequest::GetProgramAccounts => "getProgramAccounts",
- RpcRequest::GetRecentPerformanceSamples => "getRecentPerformanceSamples",
- RpcRequest::GetRecentPrioritizationFees => "getRecentPrioritizationFees",
- RpcRequest::GetHighestSnapshotSlot => "getHighestSnapshotSlot",
- RpcRequest::GetSignaturesForAddress => "getSignaturesForAddress",
- RpcRequest::GetSignatureStatuses => "getSignatureStatuses",
- RpcRequest::GetSlot => "getSlot",
- RpcRequest::GetSlotLeader => "getSlotLeader",
- RpcRequest::GetSlotLeaders => "getSlotLeaders",
- RpcRequest::GetStakeMinimumDelegation => "getStakeMinimumDelegation",
- RpcRequest::GetStorageTurn => "getStorageTurn",
- RpcRequest::GetStorageTurnRate => "getStorageTurnRate",
- RpcRequest::GetSlotsPerSegment => "getSlotsPerSegment",
- RpcRequest::GetStoragePubkeysForSlot => "getStoragePubkeysForSlot",
- RpcRequest::GetSupply => "getSupply",
- RpcRequest::GetTokenAccountBalance => "getTokenAccountBalance",
- RpcRequest::GetTokenAccountsByDelegate => "getTokenAccountsByDelegate",
- RpcRequest::GetTokenAccountsByOwner => "getTokenAccountsByOwner",
- RpcRequest::GetTokenSupply => "getTokenSupply",
- RpcRequest::GetTokenLargestAccounts => "getTokenLargestAccounts",
- RpcRequest::GetTransaction => "getTransaction",
- RpcRequest::GetTransactionCount => "getTransactionCount",
- RpcRequest::GetVersion => "getVersion",
- RpcRequest::GetVoteAccounts => "getVoteAccounts",
- RpcRequest::IsBlockhashValid => "isBlockhashValid",
- RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
- RpcRequest::RegisterNode => "registerNode",
- RpcRequest::RequestAirdrop => "requestAirdrop",
- RpcRequest::SendTransaction => "sendTransaction",
- RpcRequest::SimulateTransaction => "simulateTransaction",
- RpcRequest::SignVote => "signVote",
- };
- write!(f, "{method}")
- }
- }
- // Changing any of these? Update the JSON RPC docs!
- pub const MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS: usize = 256;
- pub const MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE: u64 = 10_000;
- pub const MAX_GET_CONFIRMED_BLOCKS_RANGE: u64 = 500_000;
- pub const MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS2_LIMIT: usize = 1_000;
- pub const MAX_MULTIPLE_ACCOUNTS: usize = 100;
- pub const NUM_LARGEST_ACCOUNTS: usize = 20;
- pub const MAX_GET_PROGRAM_ACCOUNT_FILTERS: usize = 4;
- pub const MAX_GET_SLOT_LEADERS: usize = 5000;
- // Limit the length of the `epoch_credits` array for each validator in a `get_vote_accounts`
- // response
- pub const MAX_RPC_VOTE_ACCOUNT_INFO_EPOCH_CREDITS_HISTORY: usize = 5;
- // Validators that are this number of slots behind are considered delinquent
- pub const DELINQUENT_VALIDATOR_SLOT_DISTANCE: u64 = 128;
- impl RpcRequest {
- pub fn build_request_json(self, id: u64, params: Value) -> Value {
- let jsonrpc = "2.0";
- json!({
- "jsonrpc": jsonrpc,
- "id": id,
- "method": format!("{self}"),
- "params": params,
- })
- }
- }
- #[derive(Debug)]
- pub enum RpcResponseErrorData {
- Empty,
- SendTransactionPreflightFailure(RpcSimulateTransactionResult),
- NodeUnhealthy { num_slots_behind: Option<Slot> },
- }
- impl fmt::Display for RpcResponseErrorData {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- RpcResponseErrorData::SendTransactionPreflightFailure(
- RpcSimulateTransactionResult {
- logs: Some(logs), ..
- },
- ) => {
- if logs.is_empty() {
- Ok(())
- } else {
- writeln!(f, "{} log messages:", logs.len())?;
- for log in logs {
- writeln!(f, " {log}")?;
- }
- Ok(())
- }
- }
- _ => Ok(()),
- }
- }
- }
- #[derive(Debug, Error)]
- pub enum RpcError {
- #[error("RPC request error: {0}")]
- RpcRequestError(String),
- #[error("RPC response error {code}: {message}; {data}")]
- RpcResponseError {
- code: i64,
- message: String,
- data: RpcResponseErrorData,
- },
- #[error("parse error: expected {0}")]
- ParseError(String), /* "expected" */
- // Anything in a `ForUser` needs to die. The caller should be
- // deciding what to tell their user
- #[error("{0}")]
- ForUser(String), /* "direct-to-user message" */
- }
- #[derive(Serialize, Deserialize)]
- pub enum TokenAccountsFilter {
- Mint(Pubkey),
- ProgramId(Pubkey),
- }
- #[cfg(test)]
- mod tests {
- use {
- super::*,
- crate::config::RpcTokenAccountsFilter,
- solana_commitment_config::{CommitmentConfig, CommitmentLevel},
- };
- #[test]
- fn test_build_request_json() {
- let test_request = RpcRequest::GetAccountInfo;
- let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
- let request = test_request.build_request_json(1, json!([addr]));
- assert_eq!(request["method"], "getAccountInfo");
- assert_eq!(request["params"], json!([addr]));
- let test_request = RpcRequest::GetBalance;
- let request = test_request.build_request_json(1, json!([addr]));
- assert_eq!(request["method"], "getBalance");
- let test_request = RpcRequest::GetEpochInfo;
- let request = test_request.build_request_json(1, Value::Null);
- assert_eq!(request["method"], "getEpochInfo");
- let test_request = RpcRequest::GetLatestBlockhash;
- let request = test_request.build_request_json(1, Value::Null);
- assert_eq!(request["method"], "getLatestBlockhash");
- let test_request = RpcRequest::GetSlot;
- let request = test_request.build_request_json(1, Value::Null);
- assert_eq!(request["method"], "getSlot");
- let test_request = RpcRequest::GetTransactionCount;
- let request = test_request.build_request_json(1, Value::Null);
- assert_eq!(request["method"], "getTransactionCount");
- let test_request = RpcRequest::RequestAirdrop;
- let request = test_request.build_request_json(1, Value::Null);
- assert_eq!(request["method"], "requestAirdrop");
- let test_request = RpcRequest::SendTransaction;
- let request = test_request.build_request_json(1, Value::Null);
- assert_eq!(request["method"], "sendTransaction");
- let test_request = RpcRequest::GetTokenLargestAccounts;
- let request = test_request.build_request_json(1, Value::Null);
- assert_eq!(request["method"], "getTokenLargestAccounts");
- }
- #[test]
- fn test_build_request_json_config_options() {
- let commitment_config = CommitmentConfig {
- commitment: CommitmentLevel::Finalized,
- };
- let addr = json!("deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx");
- // Test request with CommitmentConfig and no params
- let test_request = RpcRequest::GetLatestBlockhash;
- let request = test_request.build_request_json(1, json!([commitment_config]));
- assert_eq!(request["params"], json!([commitment_config.clone()]));
- // Test request with CommitmentConfig and params
- let test_request = RpcRequest::GetBalance;
- let request = test_request.build_request_json(1, json!([addr, commitment_config]));
- assert_eq!(request["params"], json!([addr, commitment_config]));
- // Test request with CommitmentConfig and params
- let test_request = RpcRequest::GetTokenAccountsByOwner;
- let mint = solana_pubkey::new_rand();
- let token_account_filter = RpcTokenAccountsFilter::Mint(mint.to_string());
- let request = test_request
- .build_request_json(1, json!([addr, token_account_filter, commitment_config]));
- assert_eq!(
- request["params"],
- json!([addr, token_account_filter, commitment_config])
- );
- }
- }
|