Remove RpcClient code duplication (#9952)

This commit is contained in:
Michael Vines 2020-05-10 08:51:53 -07:00 committed by GitHub
parent 405e39fb9f
commit af6a8f5fac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 199 additions and 356 deletions

View File

@ -697,16 +697,11 @@ impl Archiver {
RpcClient::new_socket(rpc_peers[node_index].rpc)
};
Ok(rpc_client
.send(
&RpcRequest::GetSlotsPerSegment,
.send::<u64>(
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::<RpcStorageTurn>(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,

View File

@ -50,28 +50,29 @@ impl Into<TransportError> for ClientErrorKind {
#[derive(Error, Debug)]
#[error("{kind}")]
pub struct ClientError {
command: Option<&'static str>,
request: Option<rpc_request::RpcRequest>,
#[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<ClientErrorKind> for ClientError {
fn from(kind: ClientErrorKind) -> Self {
Self {
command: None,
request: None,
kind,
}
}
@ -91,7 +92,7 @@ impl From<ClientErrorKind> for ClientError {
impl From<TransportError> for ClientError {
fn from(err: TransportError) -> Self {
Self {
command: None,
request: None,
kind: err.into(),
}
}
@ -106,7 +107,7 @@ impl Into<TransportError> for ClientError {
impl From<std::io::Error> for ClientError {
fn from(err: std::io::Error) -> Self {
Self {
command: None,
request: None,
kind: err.into(),
}
}
@ -115,7 +116,7 @@ impl From<std::io::Error> for ClientError {
impl From<reqwest::Error> for ClientError {
fn from(err: reqwest::Error) -> Self {
Self {
command: None,
request: None,
kind: err.into(),
}
}
@ -124,7 +125,7 @@ impl From<reqwest::Error> for ClientError {
impl From<rpc_request::RpcError> for ClientError {
fn from(err: rpc_request::RpcError) -> Self {
Self {
command: None,
request: None,
kind: err.into(),
}
}
@ -133,7 +134,7 @@ impl From<rpc_request::RpcError> for ClientError {
impl From<serde_json::error::Error> for ClientError {
fn from(err: serde_json::error::Error) -> Self {
Self {
command: None,
request: None,
kind: err.into(),
}
}
@ -142,7 +143,7 @@ impl From<serde_json::error::Error> for ClientError {
impl From<SignerError> for ClientError {
fn from(err: SignerError) -> Self {
Self {
command: None,
request: None,
kind: err.into(),
}
}
@ -151,7 +152,7 @@ impl From<SignerError> for ClientError {
impl From<TransactionError> for ClientError {
fn from(err: TransactionError) -> Self {
Self {
command: None,
request: None,
kind: err.into(),
}
}

View File

@ -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<serde_json::Value>;

View File

@ -40,11 +40,11 @@ impl MockRpcClientRequest {
impl GenericRpcClientRequest for MockRpcClientRequest {
fn send(
&self,
request: &RpcRequest,
request: RpcRequest,
params: serde_json::Value,
_retries: usize,
) -> Result<serde_json::Value> {
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" {

View File

@ -96,32 +96,25 @@ impl RpcClient {
pub fn send_transaction(&self, transaction: &Transaction) -> ClientResult<Signature> {
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::<Signature>().map_err(|err| {
Into::<ClientError>::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::<Signature>()
.map_err(|err| Into::<ClientError>::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<Vec<Option<TransactionStatus>>> {
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<Option<transaction::Result<()>>> {
let signature_status = self.client.send(
&RpcRequest::GetSignatureStatuses,
let result: Response<Vec<Option<TransactionStatus>>> = self.send(
RpcRequest::GetSignatureStatuses,
json!([[signature.to_string()]]),
5,
)?;
let result: Response<Vec<Option<TransactionStatus>>> =
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<Option<transaction::Result<()>>> {
let signature_status = self.client.send(
&RpcRequest::GetSignatureStatuses,
let result: Response<Vec<Option<TransactionStatus>>> = self.send(
RpcRequest::GetSignatureStatuses,
json!([[signature.to_string()], {
"searchTransactionHistory": search_transaction_history
}]),
5,
)?;
let result: Response<Vec<Option<TransactionStatus>>> =
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<Slot> {
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<u64> {
@ -210,13 +187,7 @@ impl RpcClient {
&self,
commitment_config: CommitmentConfig,
) -> ClientResult<u64> {
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<RpcVoteAccountStatus> {
@ -227,23 +198,11 @@ impl RpcClient {
&self,
commitment_config: CommitmentConfig,
) -> ClientResult<RpcVoteAccountStatus> {
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<Vec<RpcContactInfo>> {
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<ConfirmedBlock> {
@ -255,13 +214,7 @@ impl RpcClient {
slot: Slot,
encoding: TransactionEncoding,
) -> ClientResult<ConfirmedBlock> {
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<Slot>,
) -> ClientResult<Vec<Slot>> {
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<Vec<Signature>> {
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<String> =
serde_json::from_value(response).map_err(|err| {
ClientError::new_with_command(err.into(), "GetConfirmedSignaturesForAddress")
})?;
let signatures_base58_str: Vec<String> = 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<ConfirmedTransaction> {
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<UnixTimestamp> {
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<RpcEpochInfo> {
@ -357,13 +289,7 @@ impl RpcClient {
&self,
commitment_config: CommitmentConfig,
) -> ClientResult<RpcEpochInfo> {
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<Slot>,
commitment_config: CommitmentConfig,
) -> ClientResult<Option<RpcLeaderSchedule>> {
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<EpochSchedule> {
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<Pubkey> {
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::<Pubkey>().map_err(|_| {
ClientError::new_with_command(
RpcError::ParseError("Pubkey".to_string()).into(),
"GetIdentity",
)
})
})
rpc_identity.identity.parse::<Pubkey>().map_err(|_| {
ClientError::new_with_request(
RpcError::ParseError("Pubkey".to_string()).into(),
RpcRequest::GetIdentity,
)
})
}
pub fn get_inflation(&self) -> ClientResult<Inflation> {
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<RpcVersionInfo> {
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<Slot> {
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<Option<u64>, Box<dyn error::Error>> {
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::<Response<u64>>(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<Option<Account>> {
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<u64> {
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<u64> {
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::<Response<u64>>(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<Vec<(Pubkey, Account)>> {
let response = self
.client
.send(
&RpcRequest::GetProgramAccounts,
json!([pubkey.to_string()]),
0,
)
.map_err(|err| err.into_with_command("GetProgramAccounts"))?;
let accounts: Vec<RpcKeyedAccount> =
serde_json::from_value::<Vec<RpcKeyedAccount>>(response)
.map_err(|err| ClientError::new_with_command(err.into(), "GetProgramAccounts"))?;
let accounts: Vec<RpcKeyedAccount> = 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<u64> {
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<RpcBlockhashFeeCalculator>>(response)
.map_err(|err| ClientError::new_with_command(err.into(), "GetRecentBlockhash"))?;
} = self.send::<Response<RpcBlockhashFeeCalculator>>(
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<Option<FeeCalculator>> {
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<Option<RpcFeeCalculator>>>(
response,
)
.map_err(|e| ClientError::new_with_command(e.into(), "GetFeeCalculatorForBlockhash"))?;
let Response { value, .. } = self.send::<Response<Option<RpcFeeCalculator>>>(
RpcRequest::GetFeeCalculatorForBlockhash,
json!([blockhash.to_string()]),
0,
)?;
Ok(value.map(|rf| rf.fee_calculator))
}
pub fn get_fee_rate_governor(&self) -> RpcResult<FeeRateGovernor> {
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<RpcFeeRateGovernor>>(response)
.map_err(|e| ClientError::new_with_command(e.into(), "GetFeeRateGovernor"))?;
} = self.send::<Response<RpcFeeRateGovernor>>(
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<Hash> {
let response = self
.client
.send(&RpcRequest::GetGenesisHash, Value::Null, 0)
.map_err(|err| err.into_with_command("GetGenesisHash"))?;
let hash = serde_json::from_value::<String>(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<usize> {
let response = self
.client
.send(
&RpcRequest::GetSignatureStatuses,
json!([[signature.to_string()]]),
5,
)
.map_err(|err| err.into_with_command("GetSignatureStatuses"))?;
let result: Response<Vec<Option<TransactionStatus>>> = serde_json::from_value(response)
.map_err(|err| ClientError::new_with_command(err.into(), "GetSignatureStatuses"))?;
let result: Response<Vec<Option<TransactionStatus>>> = 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<bool> {
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<Value> {
pub fn send<T>(&self, request: RpcRequest, params: Value, retries: usize) -> ClientResult<T>
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<String> =
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]

View File

@ -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<serde_json::Value> {

View File

@ -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,
})
}