RpcClient::send<T> now supports client-defined RPC methods via RpcRequest::Custom

This commit is contained in:
Michael Vines 2021-07-23 14:39:38 -07:00
parent 1ee64afb12
commit f264511585
3 changed files with 38 additions and 16 deletions

View File

@ -78,23 +78,26 @@ impl RpcSender for MockSender {
if self.url == "fails" { if self.url == "fails" {
return Ok(Value::Null); return Ok(Value::Null);
} }
let val = match request {
RpcRequest::GetAccountInfo => serde_json::to_value(Response { let method = &request.build_request_json(42, params.clone())["method"];
let val = match method.as_str().unwrap() {
"getAccountInfo" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: Value::Null, value: Value::Null,
})?, })?,
RpcRequest::GetBalance => serde_json::to_value(Response { "getBalance" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: Value::Number(Number::from(50)), value: Value::Number(Number::from(50)),
})?, })?,
RpcRequest::GetRecentBlockhash => serde_json::to_value(Response { "getRecentBlockhash" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: ( value: (
Value::String(PUBKEY.to_string()), Value::String(PUBKEY.to_string()),
serde_json::to_value(FeeCalculator::default()).unwrap(), serde_json::to_value(FeeCalculator::default()).unwrap(),
), ),
})?, })?,
RpcRequest::GetEpochInfo => serde_json::to_value(EpochInfo { "getEpochInfo" => serde_json::to_value(EpochInfo {
epoch: 1, epoch: 1,
slot_index: 2, slot_index: 2,
slots_in_epoch: 32, slots_in_epoch: 32,
@ -102,7 +105,7 @@ impl RpcSender for MockSender {
block_height: 34, block_height: 34,
transaction_count: Some(123), transaction_count: Some(123),
})?, })?,
RpcRequest::GetFeeCalculatorForBlockhash => { "getFeeCalculatorForBlockhash" => {
let value = if self.url == "blockhash_expired" { let value = if self.url == "blockhash_expired" {
Value::Null Value::Null
} else { } else {
@ -113,11 +116,11 @@ impl RpcSender for MockSender {
value, value,
})? })?
} }
RpcRequest::GetFeeRateGovernor => serde_json::to_value(Response { "getFeeRateGovernor" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: serde_json::to_value(FeeRateGovernor::default()).unwrap(), value: serde_json::to_value(FeeRateGovernor::default()).unwrap(),
})?, })?,
RpcRequest::GetSignatureStatuses => { "getSignatureStatuses" => {
let status: transaction::Result<()> = if self.url == "account_in_use" { let status: transaction::Result<()> = if self.url == "account_in_use" {
Err(TransactionError::AccountInUse) Err(TransactionError::AccountInUse)
} else if self.url == "instruction_error" { } else if self.url == "instruction_error" {
@ -151,11 +154,11 @@ impl RpcSender for MockSender {
value: statuses, value: statuses,
})? })?
} }
RpcRequest::GetTransactionCount => Value::Number(Number::from(1234)), "getTransactionCount" => json![1234],
RpcRequest::GetSlot => Value::Number(Number::from(0)), "getSlot" => json![0],
RpcRequest::GetMaxShredInsertSlot => Value::Number(Number::from(0)), "getMaxShredInsertSlot" => json![0],
RpcRequest::RequestAirdrop => Value::String(Signature::new(&[8; 64]).to_string()), "requestAirdrop" => Value::String(Signature::new(&[8; 64]).to_string()),
RpcRequest::SendTransaction => { "sendTransaction" => {
let signature = if self.url == "malicious" { let signature = if self.url == "malicious" {
Signature::new(&[8; 64]).to_string() Signature::new(&[8; 64]).to_string()
} else { } else {
@ -166,7 +169,7 @@ impl RpcSender for MockSender {
}; };
Value::String(signature) Value::String(signature)
} }
RpcRequest::SimulateTransaction => serde_json::to_value(Response { "simulateTransaction" => serde_json::to_value(Response {
context: RpcResponseContext { slot: 1 }, context: RpcResponseContext { slot: 1 },
value: RpcSimulateTransactionResult { value: RpcSimulateTransactionResult {
err: None, err: None,
@ -175,8 +178,8 @@ impl RpcSender for MockSender {
units_consumed: None, units_consumed: None,
}, },
})?, })?,
RpcRequest::GetMinimumBalanceForRentExemption => Value::Number(Number::from(20)), "getMinimumBalanceForRentExemption" => json![20],
RpcRequest::GetVersion => { "getVersion" => {
let version = Version::default(); let version = Version::default();
json!(RpcVersionInfo { json!(RpcVersionInfo {
solana_core: version.to_string(), solana_core: version.to_string(),

View File

@ -2575,6 +2575,7 @@ mod tests {
let signature = rpc_client.send_transaction(&tx); let signature = rpc_client.send_transaction(&tx);
assert!(signature.is_err()); assert!(signature.is_err());
} }
#[test] #[test]
fn test_get_recent_blockhash() { fn test_get_recent_blockhash() {
let rpc_client = RpcClient::new_mock("succeeds".to_string()); let rpc_client = RpcClient::new_mock("succeeds".to_string());
@ -2589,6 +2590,20 @@ mod tests {
assert!(rpc_client.get_recent_blockhash().is_err()); assert!(rpc_client.get_recent_blockhash().is_err());
} }
#[test]
fn test_custom_request() {
let rpc_client = RpcClient::new_mock("succeeds".to_string());
let slot = rpc_client.get_slot().unwrap();
assert_eq!(slot, 0);
let custom_slot = rpc_client
.send::<Slot>(RpcRequest::Custom { method: "getSlot" }, Value::Null)
.unwrap();
assert_eq!(slot, custom_slot);
}
#[test] #[test]
fn test_get_signature_status() { fn test_get_signature_status() {
let signature = Signature::default(); let signature = Signature::default();

View File

@ -86,6 +86,9 @@ pub enum RpcRequest {
SendTransaction, SendTransaction,
SimulateTransaction, SimulateTransaction,
SignVote, SignVote,
Custom {
method: &'static str,
},
} }
#[allow(deprecated)] #[allow(deprecated)]
@ -154,6 +157,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::SendTransaction => "sendTransaction", RpcRequest::SendTransaction => "sendTransaction",
RpcRequest::SimulateTransaction => "simulateTransaction", RpcRequest::SimulateTransaction => "simulateTransaction",
RpcRequest::SignVote => "signVote", RpcRequest::SignVote => "signVote",
RpcRequest::Custom { method } => method,
}; };
write!(f, "{}", method) write!(f, "{}", method)