diff --git a/archiver-lib/src/archiver.rs b/archiver-lib/src/archiver.rs index 2de3986c1..c5b51bd54 100644 --- a/archiver-lib/src/archiver.rs +++ b/archiver-lib/src/archiver.rs @@ -697,16 +697,11 @@ impl Archiver { RpcClient::new_socket(rpc_peers[node_index].rpc) }; Ok(rpc_client - .send( - &RpcRequest::GetSlotsPerSegment, + .send::( + RpcRequest::GetSlotsPerSegment, serde_json::json!([client_commitment]), 0, ) - .map_err(|err| { - warn!("Error while making rpc request {:?}", err); - ArchiverError::ClientError(err) - })? - .as_u64() .unwrap()) } else { Err(ArchiverError::NoRpcPeers) @@ -749,21 +744,14 @@ impl Archiver { let node_index = thread_rng().gen_range(0, rpc_peers.len()); RpcClient::new_socket(rpc_peers[node_index].rpc) }; - let response = rpc_client - .send( - &RpcRequest::GetStorageTurn, - serde_json::value::Value::Null, - 0, - ) - .map_err(|err| { - warn!("Error while making rpc request {:?}", err); - ArchiverError::ClientError(err) - })?; let RpcStorageTurn { blockhash: storage_blockhash, slot: turn_slot, - } = serde_json::from_value::(response) - .map_err(ArchiverError::JsonError)?; + } = rpc_client.send( + RpcRequest::GetStorageTurn, + serde_json::value::Value::Null, + 0, + )?; let turn_blockhash = storage_blockhash.parse().map_err(|err| { io::Error::new( io::ErrorKind::Other, diff --git a/client/src/client_error.rs b/client/src/client_error.rs index ebeaa52a1..7397ec5ea 100644 --- a/client/src/client_error.rs +++ b/client/src/client_error.rs @@ -50,28 +50,29 @@ impl Into for ClientErrorKind { #[derive(Error, Debug)] #[error("{kind}")] pub struct ClientError { - command: Option<&'static str>, + request: Option, + #[source] kind: ClientErrorKind, } impl ClientError { - pub fn new_with_command(kind: ClientErrorKind, command: &'static str) -> Self { + pub fn new_with_request(kind: ClientErrorKind, request: rpc_request::RpcRequest) -> Self { Self { - command: Some(command), + request: Some(request), kind, } } - pub fn into_with_command(self, command: &'static str) -> Self { + pub fn into_with_request(self, request: rpc_request::RpcRequest) -> Self { Self { - command: Some(command), + request: Some(request), ..self } } - pub fn command(&self) -> Option<&'static str> { - self.command + pub fn request(&self) -> Option<&rpc_request::RpcRequest> { + self.request.as_ref() } pub fn kind(&self) -> &ClientErrorKind { @@ -82,7 +83,7 @@ impl ClientError { impl From for ClientError { fn from(kind: ClientErrorKind) -> Self { Self { - command: None, + request: None, kind, } } @@ -91,7 +92,7 @@ impl From for ClientError { impl From for ClientError { fn from(err: TransportError) -> Self { Self { - command: None, + request: None, kind: err.into(), } } @@ -106,7 +107,7 @@ impl Into for ClientError { impl From for ClientError { fn from(err: std::io::Error) -> Self { Self { - command: None, + request: None, kind: err.into(), } } @@ -115,7 +116,7 @@ impl From for ClientError { impl From for ClientError { fn from(err: reqwest::Error) -> Self { Self { - command: None, + request: None, kind: err.into(), } } @@ -124,7 +125,7 @@ impl From for ClientError { impl From for ClientError { fn from(err: rpc_request::RpcError) -> Self { Self { - command: None, + request: None, kind: err.into(), } } @@ -133,7 +134,7 @@ impl From for ClientError { impl From for ClientError { fn from(err: serde_json::error::Error) -> Self { Self { - command: None, + request: None, kind: err.into(), } } @@ -142,7 +143,7 @@ impl From for ClientError { impl From for ClientError { fn from(err: SignerError) -> Self { Self { - command: None, + request: None, kind: err.into(), } } @@ -151,7 +152,7 @@ impl From for ClientError { impl From for ClientError { fn from(err: TransactionError) -> Self { Self { - command: None, + request: None, kind: err.into(), } } diff --git a/client/src/generic_rpc_client_request.rs b/client/src/generic_rpc_client_request.rs index 509c98fd3..18f49c450 100644 --- a/client/src/generic_rpc_client_request.rs +++ b/client/src/generic_rpc_client_request.rs @@ -3,7 +3,7 @@ use crate::{client_error::Result, rpc_request::RpcRequest}; pub(crate) trait GenericRpcClientRequest { fn send( &self, - request: &RpcRequest, + request: RpcRequest, params: serde_json::Value, retries: usize, ) -> Result; diff --git a/client/src/mock_rpc_client_request.rs b/client/src/mock_rpc_client_request.rs index f05233913..6fbd52f12 100644 --- a/client/src/mock_rpc_client_request.rs +++ b/client/src/mock_rpc_client_request.rs @@ -40,11 +40,11 @@ impl MockRpcClientRequest { impl GenericRpcClientRequest for MockRpcClientRequest { fn send( &self, - request: &RpcRequest, + request: RpcRequest, params: serde_json::Value, _retries: usize, ) -> Result { - if let Some(value) = self.mocks.write().unwrap().remove(request) { + if let Some(value) = self.mocks.write().unwrap().remove(&request) { return Ok(value); } if self.url == "fails" { diff --git a/client/src/rpc_client.rs b/client/src/rpc_client.rs index 39079c368..539cfde54 100644 --- a/client/src/rpc_client.rs +++ b/client/src/rpc_client.rs @@ -96,32 +96,25 @@ impl RpcClient { pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult { let serialized_encoded = bs58::encode(serialize(transaction).unwrap()).into_string(); - let response = - self.client - .send(&RpcRequest::SendTransaction, json!([serialized_encoded]), 5)?; - match response.as_str() { - None => { - Err(RpcError::ForUser("Received result of an unexpected type".to_string()).into()) - } - Some(signature_base58_str) => { - let signature = signature_base58_str.parse::().map_err(|err| { - Into::::into(RpcError::ParseError(err.to_string())) - })?; - // A mismatching RPC response signature indicates an issue with the RPC node, and - // should not be passed along to confirmation methods. The transaction may or may - // not have been submitted to the cluster, so callers should verify the success of - // the correct transaction signature independently. - if signature != transaction.signatures[0] { - Err(RpcError::RpcRequestError(format!( - "RPC node returned mismatched signature {:?}, expected {:?}", - signature, transaction.signatures[0] - )) - .into()) - } else { - Ok(transaction.signatures[0]) - } - } + let signature_base58_str: String = + self.send(RpcRequest::SendTransaction, json!([serialized_encoded]), 5)?; + + let signature = signature_base58_str + .parse::() + .map_err(|err| Into::::into(RpcError::ParseError(err.to_string())))?; + // A mismatching RPC response signature indicates an issue with the RPC node, and + // should not be passed along to confirmation methods. The transaction may or may + // not have been submitted to the cluster, so callers should verify the success of + // the correct transaction signature independently. + if signature != transaction.signatures[0] { + Err(RpcError::RpcRequestError(format!( + "RPC node returned mismatched signature {:?}, expected {:?}", + signature, transaction.signatures[0] + )) + .into()) + } else { + Ok(transaction.signatures[0]) } } @@ -137,11 +130,7 @@ impl RpcClient { signatures: &[Signature], ) -> RpcResult>> { let signatures: Vec<_> = signatures.iter().map(|s| s.to_string()).collect(); - let signature_status = - self.client - .send(&RpcRequest::GetSignatureStatuses, json!([signatures]), 5)?; - Ok(serde_json::from_value(signature_status) - .map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?) + self.send(RpcRequest::GetSignatureStatuses, json!([signatures]), 5) } pub fn get_signature_status_with_commitment( @@ -149,14 +138,11 @@ impl RpcClient { signature: &Signature, commitment_config: CommitmentConfig, ) -> ClientResult>> { - let signature_status = self.client.send( - &RpcRequest::GetSignatureStatuses, + let result: Response>> = self.send( + RpcRequest::GetSignatureStatuses, json!([[signature.to_string()]]), 5, )?; - let result: Response>> = - serde_json::from_value(signature_status) - .map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?; Ok(result.value[0] .clone() .filter(|result| result.satisfies_commitment(commitment_config)) @@ -169,16 +155,13 @@ impl RpcClient { commitment_config: CommitmentConfig, search_transaction_history: bool, ) -> ClientResult>> { - let signature_status = self.client.send( - &RpcRequest::GetSignatureStatuses, + let result: Response>> = self.send( + RpcRequest::GetSignatureStatuses, json!([[signature.to_string()], { "searchTransactionHistory": search_transaction_history }]), 5, )?; - let result: Response>> = - serde_json::from_value(signature_status) - .map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?; Ok(result.value[0] .clone() .filter(|result| result.satisfies_commitment(commitment_config)) @@ -193,13 +176,7 @@ impl RpcClient { &self, commitment_config: CommitmentConfig, ) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetSlot, json!([commitment_config]), 0) - .map_err(|err| err.into_with_command("GetSlot"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetSlot")) + self.send(RpcRequest::GetSlot, json!([commitment_config]), 0) } pub fn total_supply(&self) -> ClientResult { @@ -210,13 +187,7 @@ impl RpcClient { &self, commitment_config: CommitmentConfig, ) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetTotalSupply, json!([commitment_config]), 0) - .map_err(|err| err.into_with_command("GetTotalSupply"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetTotalSupply")) + self.send(RpcRequest::GetTotalSupply, json!([commitment_config]), 0) } pub fn get_vote_accounts(&self) -> ClientResult { @@ -227,23 +198,11 @@ impl RpcClient { &self, commitment_config: CommitmentConfig, ) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetVoteAccounts, json!([commitment_config]), 0) - .map_err(|err| err.into_with_command("GetVoteAccounts"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetVoteAccounts")) + self.send(RpcRequest::GetVoteAccounts, json!([commitment_config]), 0) } pub fn get_cluster_nodes(&self) -> ClientResult> { - let response = self - .client - .send(&RpcRequest::GetClusterNodes, Value::Null, 0) - .map_err(|err| err.into_with_command("GetClusterNodes"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetClusterNodes")) + self.send(RpcRequest::GetClusterNodes, Value::Null, 0) } pub fn get_confirmed_block(&self, slot: Slot) -> ClientResult { @@ -255,13 +214,7 @@ impl RpcClient { slot: Slot, encoding: TransactionEncoding, ) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetConfirmedBlock, json!([slot, encoding]), 0) - .map_err(|err| err.into_with_command("GetConfirmedBlock"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetConfirmedBlock")) + self.send(RpcRequest::GetConfirmedBlock, json!([slot, encoding]), 0) } pub fn get_confirmed_blocks( @@ -269,17 +222,11 @@ impl RpcClient { start_slot: Slot, end_slot: Option, ) -> ClientResult> { - let response = self - .client - .send( - &RpcRequest::GetConfirmedBlocks, - json!([start_slot, end_slot]), - 0, - ) - .map_err(|err| err.into_with_command("GetConfirmedBlocks"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetConfirmedBlocks")) + self.send( + RpcRequest::GetConfirmedBlocks, + json!([start_slot, end_slot]), + 0, + ) } pub fn get_confirmed_signatures_for_address( @@ -288,19 +235,11 @@ impl RpcClient { start_slot: Slot, end_slot: Slot, ) -> ClientResult> { - let response = self - .client - .send( - &RpcRequest::GetConfirmedSignaturesForAddress, - json!([address.to_string(), start_slot, end_slot]), - 0, - ) - .map_err(|err| err.into_with_command("GetConfirmedSignaturesForAddress"))?; - - let signatures_base58_str: Vec = - serde_json::from_value(response).map_err(|err| { - ClientError::new_with_command(err.into(), "GetConfirmedSignaturesForAddress") - })?; + let signatures_base58_str: Vec = self.send( + RpcRequest::GetConfirmedSignaturesForAddress, + json!([address.to_string(), start_slot, end_slot]), + 0, + )?; let mut signatures = vec![]; for signature_base58_str in signatures_base58_str { @@ -318,23 +257,16 @@ impl RpcClient { signature: &Signature, encoding: TransactionEncoding, ) -> ClientResult { - let response = self - .client - .send( - &RpcRequest::GetConfirmedTransaction, - json!([signature.to_string(), encoding]), - 0, - ) - .map_err(|err| err.into_with_command("GetConfirmedTransaction"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetConfirmedTransaction")) + self.send( + RpcRequest::GetConfirmedTransaction, + json!([signature.to_string(), encoding]), + 0, + ) } pub fn get_block_time(&self, slot: Slot) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetBlockTime, json!([slot]), 0); + let request = RpcRequest::GetBlockTime; + let response = self.client.send(request, json!([slot]), 0); response .map(|result_json| { @@ -342,11 +274,11 @@ impl RpcClient { return Err(RpcError::ForUser(format!("Block Not Found: slot={}", slot)).into()); } let result = serde_json::from_value(result_json) - .map_err(|err| ClientError::new_with_command(err.into(), "GetBlockTime"))?; + .map_err(|err| ClientError::new_with_request(err.into(), request))?; trace!("Response block timestamp {:?} {:?}", slot, result); Ok(result) }) - .map_err(|err| err.into_with_command("GetBlockTime"))? + .map_err(|err| err.into_with_request(request))? } pub fn get_epoch_info(&self) -> ClientResult { @@ -357,13 +289,7 @@ impl RpcClient { &self, commitment_config: CommitmentConfig, ) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetEpochInfo, json!([commitment_config]), 0) - .map_err(|err| err.into_with_command("GetEpochInfo"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetEpochInfo")) + self.send(RpcRequest::GetEpochInfo, json!([commitment_config]), 0) } pub fn get_leader_schedule( @@ -378,75 +304,38 @@ impl RpcClient { slot: Option, commitment_config: CommitmentConfig, ) -> ClientResult> { - let response = self - .client - .send( - &RpcRequest::GetLeaderSchedule, - json!([slot, commitment_config]), - 0, - ) - .map_err(|err| err.into_with_command("GetLeaderSchedule"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetLeaderSchedule")) + self.send( + RpcRequest::GetLeaderSchedule, + json!([slot, commitment_config]), + 0, + ) } pub fn get_epoch_schedule(&self) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetEpochSchedule, Value::Null, 0) - .map_err(|err| err.into_with_command("GetEpochSchedule"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetEpochSchedule")) + self.send(RpcRequest::GetEpochSchedule, Value::Null, 0) } pub fn get_identity(&self) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetIdentity, Value::Null, 0) - .map_err(|err| err.into_with_command("GetIdentity"))?; + let rpc_identity: RpcIdentity = self.send(RpcRequest::GetIdentity, Value::Null, 0)?; - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetIdentity")) - .and_then(|rpc_identity: RpcIdentity| { - rpc_identity.identity.parse::().map_err(|_| { - ClientError::new_with_command( - RpcError::ParseError("Pubkey".to_string()).into(), - "GetIdentity", - ) - }) - }) + rpc_identity.identity.parse::().map_err(|_| { + ClientError::new_with_request( + RpcError::ParseError("Pubkey".to_string()).into(), + RpcRequest::GetIdentity, + ) + }) } pub fn get_inflation(&self) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetInflation, Value::Null, 0) - .map_err(|err| err.into_with_command("GetInflation"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetInflation")) + self.send(RpcRequest::GetInflation, Value::Null, 0) } pub fn get_version(&self) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetVersion, Value::Null, 0) - .map_err(|err| err.into_with_command("GetVersion"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetVersion")) + self.send(RpcRequest::GetVersion, Value::Null, 0) } pub fn minimum_ledger_slot(&self) -> ClientResult { - let response = self - .client - .send(&RpcRequest::MinimumLedgerSlot, Value::Null, 0) - .map_err(|err| err.into_with_command("MinimumLedgerSlot"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "MinimumLedgerSlot")) + self.send(RpcRequest::MinimumLedgerSlot, Value::Null, 0) } pub fn send_and_confirm_transaction( @@ -600,18 +489,15 @@ impl RpcClient { pubkey: &Pubkey, retries: usize, ) -> Result, Box> { + let request = RpcRequest::GetBalance; let balance_json = self .client - .send( - &RpcRequest::GetBalance, - json!([pubkey.to_string()]), - retries, - ) - .map_err(|err| err.into_with_command("RetryGetBalance"))?; + .send(request, json!([pubkey.to_string()]), retries) + .map_err(|err| err.into_with_request(request))?; Ok(Some( serde_json::from_value::>(balance_json) - .map_err(|err| ClientError::new_with_command(err.into(), "RetryGetBalance"))? + .map_err(|err| ClientError::new_with_request(err.into(), request))? .value, )) } @@ -628,7 +514,7 @@ impl RpcClient { commitment_config: CommitmentConfig, ) -> RpcResult> { let response = self.client.send( - &RpcRequest::GetAccountInfo, + RpcRequest::GetAccountInfo, json!([pubkey.to_string(), commitment_config]), 0, ); @@ -664,18 +550,14 @@ impl RpcClient { } pub fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> ClientResult { + let request = RpcRequest::GetMinimumBalanceForRentExemption; let minimum_balance_json = self .client - .send( - &RpcRequest::GetMinimumBalanceForRentExemption, - json!([data_len]), - 0, - ) - .map_err(|err| err.into_with_command("GetMinimumBalanceForRentExemption"))?; + .send(request, json!([data_len]), 0) + .map_err(|err| err.into_with_request(request))?; - let minimum_balance: u64 = serde_json::from_value(minimum_balance_json).map_err(|err| { - ClientError::new_with_command(err.into(), "GetMinimumBalanceForRentExemption") - })?; + let minimum_balance: u64 = serde_json::from_value(minimum_balance_json) + .map_err(|err| ClientError::new_with_request(err.into(), request))?; trace!( "Response minimum balance {:?} {:?}", data_len, @@ -696,39 +578,25 @@ impl RpcClient { pubkey: &Pubkey, commitment_config: CommitmentConfig, ) -> RpcResult { - let balance_json = self - .client - .send( - &RpcRequest::GetBalance, - json!([pubkey.to_string(), commitment_config]), - 0, - ) - .map_err(|err| err.into_with_command("GetBalance"))?; - - serde_json::from_value::>(balance_json) - .map_err(|err| ClientError::new_with_command(err.into(), "GetBalance")) + self.send( + RpcRequest::GetBalance, + json!([pubkey.to_string(), commitment_config]), + 0, + ) } pub fn get_program_accounts(&self, pubkey: &Pubkey) -> ClientResult> { - let response = self - .client - .send( - &RpcRequest::GetProgramAccounts, - json!([pubkey.to_string()]), - 0, - ) - .map_err(|err| err.into_with_command("GetProgramAccounts"))?; - - let accounts: Vec = - serde_json::from_value::>(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetProgramAccounts"))?; - + let accounts: Vec = self.send( + RpcRequest::GetProgramAccounts, + json!([pubkey.to_string()]), + 0, + )?; let mut pubkey_accounts: Vec<(Pubkey, Account)> = Vec::new(); for RpcKeyedAccount { pubkey, account } in accounts.into_iter() { let pubkey = pubkey.parse().map_err(|_| { - ClientError::new_with_command( + ClientError::new_with_request( RpcError::ParseError("Pubkey".to_string()).into(), - "GetProgramAccounts", + RpcRequest::GetProgramAccounts, ) })?; pubkey_accounts.push((pubkey, account.decode().unwrap())); @@ -745,17 +613,11 @@ impl RpcClient { &self, commitment_config: CommitmentConfig, ) -> ClientResult { - let response = self - .client - .send( - &RpcRequest::GetTransactionCount, - json!([commitment_config]), - 0, - ) - .map_err(|err| err.into_with_command("GetTransactionCount"))?; - - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetTransactionCount")) + self.send( + RpcRequest::GetTransactionCount, + json!([commitment_config]), + 0, + ) } pub fn get_recent_blockhash(&self) -> ClientResult<(Hash, FeeCalculator)> { @@ -768,15 +630,6 @@ impl RpcClient { &self, commitment_config: CommitmentConfig, ) -> RpcResult<(Hash, FeeCalculator)> { - let response = self - .client - .send( - &RpcRequest::GetRecentBlockhash, - json!([commitment_config]), - 0, - ) - .map_err(|err| err.into_with_command("GetRecentBlockhash"))?; - let Response { context, value: @@ -784,12 +637,16 @@ impl RpcClient { blockhash, fee_calculator, }, - } = serde_json::from_value::>(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetRecentBlockhash"))?; + } = self.send::>( + RpcRequest::GetRecentBlockhash, + json!([commitment_config]), + 0, + )?; + let blockhash = blockhash.parse().map_err(|_| { - ClientError::new_with_command( + ClientError::new_with_request( RpcError::ParseError("Hash".to_string()).into(), - "GetRecentBlockhash", + RpcRequest::GetRecentBlockhash, ) })?; Ok(Response { @@ -802,31 +659,25 @@ impl RpcClient { &self, blockhash: &Hash, ) -> ClientResult> { - let response = self - .client - .send( - &RpcRequest::GetFeeCalculatorForBlockhash, - json!([blockhash.to_string()]), - 0, - ) - .map_err(|err| err.into_with_command("GetFeeCalculatorForBlockhash"))?; - let Response { value, .. } = serde_json::from_value::>>( - response, - ) - .map_err(|e| ClientError::new_with_command(e.into(), "GetFeeCalculatorForBlockhash"))?; + let Response { value, .. } = self.send::>>( + RpcRequest::GetFeeCalculatorForBlockhash, + json!([blockhash.to_string()]), + 0, + )?; + Ok(value.map(|rf| rf.fee_calculator)) } pub fn get_fee_rate_governor(&self) -> RpcResult { - let response = self - .client - .send(&RpcRequest::GetFeeRateGovernor, Value::Null, 0) - .map_err(|err| err.into_with_command("GetFeeRateGovernor"))?; let Response { context, value: RpcFeeRateGovernor { fee_rate_governor }, - } = serde_json::from_value::>(response) - .map_err(|e| ClientError::new_with_command(e.into(), "GetFeeRateGovernor"))?; + } = self.send::>( + RpcRequest::GetFeeRateGovernor, + Value::Null, + 0, + )?; + Ok(Response { context, value: fee_rate_governor, @@ -860,18 +711,11 @@ impl RpcClient { } pub fn get_genesis_hash(&self) -> ClientResult { - let response = self - .client - .send(&RpcRequest::GetGenesisHash, Value::Null, 0) - .map_err(|err| err.into_with_command("GetGenesisHash"))?; - - let hash = serde_json::from_value::(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetGenesisHash"))?; - - let hash = hash.parse().map_err(|_| { - ClientError::new_with_command( + let hash_str: String = self.send(RpcRequest::GetGenesisHash, Value::Null, 0)?; + let hash = hash_str.parse().map_err(|_| { + ClientError::new_with_request( RpcError::ParseError("Hash".to_string()).into(), - "GetGenesisHash", + RpcRequest::GetGenesisHash, ) })?; Ok(hash) @@ -927,7 +771,7 @@ impl RpcClient { return balance_result.ok(); } trace!( - "retry_get_balance[{}] {:?} {:?}", + "wait_for_balance_with_commitment [{}] {:?} {:?}", run, balance_result, expected_balance @@ -1060,23 +904,18 @@ impl RpcClient { &self, signature: &Signature, ) -> ClientResult { - let response = self - .client - .send( - &RpcRequest::GetSignatureStatuses, - json!([[signature.to_string()]]), - 5, - ) - .map_err(|err| err.into_with_command("GetSignatureStatuses"))?; - let result: Response>> = serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?; + let result: Response>> = self.send( + RpcRequest::GetSignatureStatuses, + json!([[signature.to_string()]]), + 5, + )?; let confirmations = result.value[0] .clone() .ok_or_else(|| { - ClientError::new_with_command( + ClientError::new_with_request( ClientErrorKind::Custom("signature not found".to_string()), - "GetSignatureStatuses", + RpcRequest::GetSignatureStatuses, ) })? .confirmations @@ -1180,17 +1019,20 @@ impl RpcClient { } pub fn validator_exit(&self) -> ClientResult { - let response = self - .client - .send(&RpcRequest::ValidatorExit, Value::Null, 0) - .map_err(|err| err.into_with_command("ValidatorExit"))?; - serde_json::from_value(response) - .map_err(|err| ClientError::new_with_command(err.into(), "ValidatorExit")) + self.send(RpcRequest::ValidatorExit, Value::Null, 0) } - pub fn send(&self, request: &RpcRequest, params: Value, retries: usize) -> ClientResult { + pub fn send(&self, request: RpcRequest, params: Value, retries: usize) -> ClientResult + where + T: serde::de::DeserializeOwned, + { assert!(params.is_array() || params.is_null()); - self.client.send(request, params, retries) + let response = self + .client + .send(request, params, retries) + .map_err(|err| err.into_with_request(request))?; + serde_json::from_value(response) + .map_err(|err| ClientError::new_with_request(err.into(), request)) } } @@ -1260,21 +1102,23 @@ mod tests { let rpc_addr = receiver.recv().unwrap(); let rpc_client = RpcClient::new_socket(rpc_addr); - let balance = rpc_client.send( - &RpcRequest::GetBalance, - json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"]), - 0, - ); - assert_eq!(balance.unwrap().as_u64().unwrap(), 50); + let balance: u64 = rpc_client + .send( + RpcRequest::GetBalance, + json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"]), + 0, + ) + .unwrap(); + assert_eq!(balance, 50); - let blockhash = rpc_client.send(&RpcRequest::GetRecentBlockhash, Value::Null, 0); - assert_eq!( - blockhash.unwrap().as_str().unwrap(), - "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx" - ); + let blockhash: String = rpc_client + .send(RpcRequest::GetRecentBlockhash, Value::Null, 0) + .unwrap(); + assert_eq!(blockhash, "deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhx"); // Send erroneous parameter - let blockhash = rpc_client.send(&RpcRequest::GetRecentBlockhash, json!(["parameter"]), 0); + let blockhash: ClientResult = + rpc_client.send(RpcRequest::GetRecentBlockhash, json!(["parameter"]), 0); assert_eq!(blockhash.is_err(), true); } @@ -1308,12 +1152,14 @@ mod tests { let rpc_addr = receiver.recv().unwrap(); let rpc_client = RpcClient::new_socket(rpc_addr); - let balance = rpc_client.send( - &RpcRequest::GetBalance, - json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhw"]), - 10, - ); - assert_eq!(balance.unwrap().as_u64().unwrap(), 5); + let balance: u64 = rpc_client + .send( + RpcRequest::GetBalance, + json!(["deadbeefXjn8o3yroDHxUtKsZZgoy4GPkPPXfouKNHhw"]), + 10, + ) + .unwrap(); + assert_eq!(balance, 5); } #[test] diff --git a/client/src/rpc_client_request.rs b/client/src/rpc_client_request.rs index a3f53ffb9..22d6cf452 100644 --- a/client/src/rpc_client_request.rs +++ b/client/src/rpc_client_request.rs @@ -31,7 +31,7 @@ impl RpcClientRequest { impl GenericRpcClientRequest for RpcClientRequest { fn send( &self, - request: &RpcRequest, + request: RpcRequest, params: serde_json::Value, mut retries: usize, ) -> Result { diff --git a/client/src/rpc_request.rs b/client/src/rpc_request.rs index bdac2335a..fd02283fb 100644 --- a/client/src/rpc_request.rs +++ b/client/src/rpc_request.rs @@ -1,7 +1,8 @@ use serde_json::{json, Value}; +use std::fmt; use thiserror::Error; -#[derive(Debug, PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] pub enum RpcRequest { DeregisterNode, ValidatorExit, @@ -42,12 +43,8 @@ pub enum RpcRequest { MinimumLedgerSlot, } -pub const MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS: usize = 256; -pub const MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE: u64 = 10_000; - -impl RpcRequest { - pub(crate) fn build_request_json(&self, id: u64, params: Value) -> Value { - let jsonrpc = "2.0"; +impl fmt::Display for RpcRequest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let method = match self { RpcRequest::DeregisterNode => "deregisterNode", RpcRequest::ValidatorExit => "validatorExit", @@ -87,10 +84,21 @@ impl RpcRequest { RpcRequest::GetMinimumBalanceForRentExemption => "getMinimumBalanceForRentExemption", RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot", }; + + write!(f, "{}", method) + } +} + +pub const MAX_GET_SIGNATURE_STATUSES_QUERY_ITEMS: usize = 256; +pub const MAX_GET_CONFIRMED_SIGNATURES_FOR_ADDRESS_SLOT_RANGE: u64 = 10_000; + +impl RpcRequest { + pub(crate) fn build_request_json(self, id: u64, params: Value) -> Value { + let jsonrpc = "2.0"; json!({ "jsonrpc": jsonrpc, "id": id, - "method": method, + "method": format!("{}", self), "params": params, }) }