2022-01-24 17:01:07 -08:00
|
|
|
//! A nonblocking [`RpcSender`] used for unit testing [`RpcClient`](crate::rpc_client::RpcClient).
|
2021-07-20 11:49:32 -07:00
|
|
|
|
2021-03-26 20:26:06 -07:00
|
|
|
use {
|
2022-08-23 22:34:35 -07:00
|
|
|
crate::rpc_sender::*,
|
|
|
|
async_trait::async_trait,
|
|
|
|
serde_json::{json, Number, Value},
|
|
|
|
solana_account_decoder::{UiAccount, UiAccountEncoding},
|
|
|
|
solana_rpc_client_api::{
|
2021-03-26 20:26:06 -07:00
|
|
|
client_error::Result,
|
2022-08-23 22:34:35 -07:00
|
|
|
config::RpcBlockProductionConfig,
|
|
|
|
request::RpcRequest,
|
|
|
|
response::{
|
2021-08-13 09:08:20 -07:00
|
|
|
Response, RpcAccountBalance, RpcBlockProduction, RpcBlockProductionRange, RpcBlockhash,
|
2021-09-27 13:59:25 -07:00
|
|
|
RpcConfirmedTransactionStatusWithSignature, RpcContactInfo, RpcFees, RpcIdentity,
|
|
|
|
RpcInflationGovernor, RpcInflationRate, RpcInflationReward, RpcKeyedAccount,
|
2023-01-06 22:04:34 -08:00
|
|
|
RpcPerfSample, RpcPrioritizationFee, RpcResponseContext, RpcSimulateTransactionResult,
|
|
|
|
RpcSnapshotSlotInfo, RpcStakeActivation, RpcSupply, RpcVersionInfo, RpcVoteAccountInfo,
|
2021-09-02 13:25:42 -07:00
|
|
|
RpcVoteAccountStatus, StakeActivationState,
|
2021-07-20 11:49:32 -07:00
|
|
|
},
|
2021-03-26 20:26:06 -07:00
|
|
|
},
|
|
|
|
solana_sdk::{
|
2021-09-27 13:59:25 -07:00
|
|
|
account::Account,
|
2021-08-23 17:49:37 -07:00
|
|
|
clock::{Slot, UnixTimestamp},
|
2021-03-26 20:26:06 -07:00
|
|
|
epoch_info::EpochInfo,
|
|
|
|
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
|
|
|
instruction::InstructionError,
|
2021-08-23 17:49:37 -07:00
|
|
|
message::MessageHeader,
|
2021-09-27 13:59:25 -07:00
|
|
|
pubkey::Pubkey,
|
2021-03-26 20:26:06 -07:00
|
|
|
signature::Signature,
|
2021-08-23 17:49:37 -07:00
|
|
|
sysvar::epoch_schedule::EpochSchedule,
|
2022-03-07 23:20:34 -08:00
|
|
|
transaction::{self, Transaction, TransactionError, TransactionVersion},
|
2021-03-26 20:26:06 -07:00
|
|
|
},
|
2021-08-23 17:49:37 -07:00
|
|
|
solana_transaction_status::{
|
2022-09-14 15:58:50 -07:00
|
|
|
option_serializer::OptionSerializer, EncodedConfirmedBlock,
|
|
|
|
EncodedConfirmedTransactionWithStatusMeta, EncodedTransaction,
|
2022-03-09 00:09:08 -08:00
|
|
|
EncodedTransactionWithStatusMeta, Rewards, TransactionBinaryEncoding,
|
|
|
|
TransactionConfirmationStatus, TransactionStatus, UiCompiledInstruction, UiMessage,
|
|
|
|
UiRawMessage, UiTransaction, UiTransactionStatusMeta,
|
2021-08-23 17:49:37 -07:00
|
|
|
},
|
2021-03-26 20:26:06 -07:00
|
|
|
solana_version::Version,
|
2021-09-27 13:59:25 -07:00
|
|
|
std::{collections::HashMap, net::SocketAddr, str::FromStr, sync::RwLock},
|
2019-11-06 13:15:00 -08:00
|
|
|
};
|
2019-03-12 17:26:07 -07:00
|
|
|
|
|
|
|
pub const PUBKEY: &str = "7RoSF9fUmdphVCpabEoefH81WwrW7orsWonXWqTXkKV8";
|
|
|
|
|
2019-12-27 12:35:49 -08:00
|
|
|
pub type Mocks = HashMap<RpcRequest, Value>;
|
2020-05-20 18:40:45 -07:00
|
|
|
pub struct MockSender {
|
2019-12-27 12:35:49 -08:00
|
|
|
mocks: RwLock<Mocks>,
|
2019-03-16 21:51:41 -07:00
|
|
|
url: String,
|
2019-03-12 17:26:07 -07:00
|
|
|
}
|
|
|
|
|
2021-07-20 11:49:32 -07:00
|
|
|
/// An [`RpcSender`] used for unit testing [`RpcClient`](crate::rpc_client::RpcClient).
|
|
|
|
///
|
|
|
|
/// This is primarily for internal use.
|
|
|
|
///
|
|
|
|
/// Unless directed otherwise, it will generally return a reasonable default
|
|
|
|
/// response, at least for [`RpcRequest`] values for which responses have been
|
|
|
|
/// implemented.
|
|
|
|
///
|
|
|
|
/// The behavior can be customized in two ways:
|
|
|
|
///
|
|
|
|
/// 1) The `url` constructor argument is not actually a URL, but a simple string
|
|
|
|
/// directive that changes `MockSender`s behavior in specific scenarios.
|
|
|
|
///
|
|
|
|
/// If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`.
|
|
|
|
///
|
|
|
|
/// It is customary to set the `url` to "succeeds" for mocks that should
|
|
|
|
/// return sucessfully, though this value is not actually interpreted.
|
|
|
|
///
|
|
|
|
/// Other possible values of `url` are specific to different `RpcRequest`
|
|
|
|
/// values. Read the implementation for specifics.
|
|
|
|
///
|
|
|
|
/// 2) Custom responses can be configured by providing [`Mocks`] to the
|
|
|
|
/// [`MockSender::new_with_mocks`] constructor. This type is a [`HashMap`]
|
|
|
|
/// from [`RpcRequest`] to a JSON [`Value`] response, Any entries in this map
|
|
|
|
/// override the default behavior for the given request.
|
2020-05-20 18:40:45 -07:00
|
|
|
impl MockSender {
|
2022-02-14 22:40:08 -08:00
|
|
|
pub fn new<U: ToString>(url: U) -> Self {
|
2019-12-27 12:35:49 -08:00
|
|
|
Self::new_with_mocks(url, Mocks::default())
|
|
|
|
}
|
|
|
|
|
2022-02-14 22:40:08 -08:00
|
|
|
pub fn new_with_mocks<U: ToString>(url: U, mocks: Mocks) -> Self {
|
2019-12-27 12:35:49 -08:00
|
|
|
Self {
|
2022-02-14 22:40:08 -08:00
|
|
|
url: url.to_string(),
|
2019-12-27 12:35:49 -08:00
|
|
|
mocks: RwLock::new(mocks),
|
|
|
|
}
|
2019-03-12 17:26:07 -07:00
|
|
|
}
|
2019-03-16 21:51:41 -07:00
|
|
|
}
|
2019-03-12 17:26:07 -07:00
|
|
|
|
2022-01-24 17:01:07 -08:00
|
|
|
#[async_trait]
|
2020-05-20 18:40:45 -07:00
|
|
|
impl RpcSender for MockSender {
|
2021-09-08 16:44:35 -07:00
|
|
|
fn get_transport_stats(&self) -> RpcTransportStats {
|
|
|
|
RpcTransportStats::default()
|
|
|
|
}
|
|
|
|
|
2022-01-24 17:01:07 -08:00
|
|
|
async fn send(
|
|
|
|
&self,
|
|
|
|
request: RpcRequest,
|
|
|
|
params: serde_json::Value,
|
|
|
|
) -> Result<serde_json::Value> {
|
2020-05-10 08:51:53 -07:00
|
|
|
if let Some(value) = self.mocks.write().unwrap().remove(&request) {
|
2019-12-27 12:35:49 -08:00
|
|
|
return Ok(value);
|
|
|
|
}
|
2019-03-15 22:42:36 -07:00
|
|
|
if self.url == "fails" {
|
2019-03-12 17:26:07 -07:00
|
|
|
return Ok(Value::Null);
|
|
|
|
}
|
2021-07-23 14:39:38 -07:00
|
|
|
|
|
|
|
let method = &request.build_request_json(42, params.clone())["method"];
|
|
|
|
|
|
|
|
let val = match method.as_str().unwrap() {
|
|
|
|
"getAccountInfo" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2020-12-21 13:02:53 -08:00
|
|
|
value: Value::Null,
|
|
|
|
})?,
|
2021-07-23 14:39:38 -07:00
|
|
|
"getBalance" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2020-02-11 21:48:04 -08:00
|
|
|
value: Value::Number(Number::from(50)),
|
|
|
|
})?,
|
2021-07-23 14:39:38 -07:00
|
|
|
"getRecentBlockhash" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2019-11-12 11:49:41 -08:00
|
|
|
value: (
|
|
|
|
Value::String(PUBKEY.to_string()),
|
|
|
|
serde_json::to_value(FeeCalculator::default()).unwrap(),
|
|
|
|
),
|
|
|
|
})?,
|
2021-07-23 14:39:38 -07:00
|
|
|
"getEpochInfo" => serde_json::to_value(EpochInfo {
|
2020-10-23 09:03:29 -07:00
|
|
|
epoch: 1,
|
|
|
|
slot_index: 2,
|
|
|
|
slots_in_epoch: 32,
|
|
|
|
absolute_slot: 34,
|
|
|
|
block_height: 34,
|
2020-12-17 10:04:53 -08:00
|
|
|
transaction_count: Some(123),
|
2020-10-23 09:03:29 -07:00
|
|
|
})?,
|
2021-07-23 14:39:38 -07:00
|
|
|
"getFeeCalculatorForBlockhash" => {
|
2020-03-06 16:01:31 -08:00
|
|
|
let value = if self.url == "blockhash_expired" {
|
|
|
|
Value::Null
|
|
|
|
} else {
|
|
|
|
serde_json::to_value(Some(FeeCalculator::default())).unwrap()
|
|
|
|
};
|
|
|
|
serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2020-03-06 16:01:31 -08:00
|
|
|
value,
|
|
|
|
})?
|
|
|
|
}
|
2021-07-23 14:39:38 -07:00
|
|
|
"getFeeRateGovernor" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2020-02-28 12:27:01 -08:00
|
|
|
value: serde_json::to_value(FeeRateGovernor::default()).unwrap(),
|
|
|
|
})?,
|
2021-08-11 00:04:00 -07:00
|
|
|
"getFees" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-08-11 00:04:00 -07:00
|
|
|
value: serde_json::to_value(RpcFees {
|
|
|
|
blockhash: PUBKEY.to_string(),
|
|
|
|
fee_calculator: FeeCalculator::default(),
|
|
|
|
last_valid_slot: 42,
|
|
|
|
last_valid_block_height: 42,
|
|
|
|
})
|
|
|
|
.unwrap(),
|
|
|
|
})?,
|
2021-07-23 14:39:38 -07:00
|
|
|
"getSignatureStatuses" => {
|
2020-03-23 10:25:39 -07:00
|
|
|
let status: transaction::Result<()> = if self.url == "account_in_use" {
|
|
|
|
Err(TransactionError::AccountInUse)
|
2019-12-09 19:35:34 -08:00
|
|
|
} else if self.url == "instruction_error" {
|
2020-03-23 10:25:39 -07:00
|
|
|
Err(TransactionError::InstructionError(
|
2019-12-09 19:35:34 -08:00
|
|
|
0,
|
|
|
|
InstructionError::UninitializedAccount,
|
2020-03-23 10:25:39 -07:00
|
|
|
))
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
};
|
|
|
|
let status = if self.url == "sig_not_found" {
|
2019-04-05 19:56:17 -07:00
|
|
|
None
|
2019-03-12 17:26:07 -07:00
|
|
|
} else {
|
2020-04-04 16:13:26 -07:00
|
|
|
let err = status.clone().err();
|
2020-03-26 18:21:01 -07:00
|
|
|
Some(TransactionStatus {
|
|
|
|
status,
|
|
|
|
slot: 1,
|
2020-04-06 03:04:54 -07:00
|
|
|
confirmations: None,
|
2020-04-04 16:13:26 -07:00
|
|
|
err,
|
2021-01-15 08:05:05 -08:00
|
|
|
confirmation_status: Some(TransactionConfirmationStatus::Finalized),
|
2020-03-26 18:21:01 -07:00
|
|
|
})
|
2019-03-12 17:26:07 -07:00
|
|
|
};
|
2020-10-02 12:35:39 -07:00
|
|
|
let statuses: Vec<Option<TransactionStatus>> = params.as_array().unwrap()[0]
|
|
|
|
.as_array()
|
|
|
|
.unwrap()
|
|
|
|
.iter()
|
|
|
|
.map(|_| status.clone())
|
|
|
|
.collect();
|
2020-03-26 18:21:01 -07:00
|
|
|
serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2020-10-02 12:35:39 -07:00
|
|
|
value: statuses,
|
2020-03-26 18:21:01 -07:00
|
|
|
})?
|
2019-03-12 17:26:07 -07:00
|
|
|
}
|
2022-01-03 07:45:18 -08:00
|
|
|
"getTransaction" => serde_json::to_value(EncodedConfirmedTransactionWithStatusMeta {
|
2021-08-23 17:49:37 -07:00
|
|
|
slot: 2,
|
|
|
|
transaction: EncodedTransactionWithStatusMeta {
|
2022-03-07 23:20:34 -08:00
|
|
|
version: Some(TransactionVersion::LEGACY),
|
2021-08-23 17:49:37 -07:00
|
|
|
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(),
|
2022-10-25 19:37:44 -07:00
|
|
|
stack_height: None,
|
2021-08-23 17:49:37 -07:00
|
|
|
}],
|
2022-03-07 23:20:34 -08:00
|
|
|
address_table_lookups: None,
|
2021-08-23 17:49:37 -07:00
|
|
|
})
|
|
|
|
}),
|
|
|
|
meta: Some(UiTransactionStatusMeta {
|
|
|
|
err: None,
|
|
|
|
status: Ok(()),
|
|
|
|
fee: 0,
|
|
|
|
pre_balances: vec![499999999999999950, 50, 1],
|
|
|
|
post_balances: vec![499999999999999950, 50, 1],
|
2022-09-14 15:58:50 -07:00
|
|
|
inner_instructions: OptionSerializer::None,
|
|
|
|
log_messages: OptionSerializer::None,
|
|
|
|
pre_token_balances: OptionSerializer::None,
|
|
|
|
post_token_balances: OptionSerializer::None,
|
|
|
|
rewards: OptionSerializer::None,
|
|
|
|
loaded_addresses: OptionSerializer::Skip,
|
|
|
|
return_data: OptionSerializer::Skip,
|
|
|
|
compute_units_consumed: OptionSerializer::Skip,
|
2021-08-23 17:49:37 -07:00
|
|
|
}),
|
|
|
|
},
|
|
|
|
block_time: Some(1628633791),
|
|
|
|
})?,
|
2021-07-23 14:39:38 -07:00
|
|
|
"getTransactionCount" => json![1234],
|
|
|
|
"getSlot" => json![0],
|
|
|
|
"getMaxShredInsertSlot" => json![0],
|
|
|
|
"requestAirdrop" => Value::String(Signature::new(&[8; 64]).to_string()),
|
2021-08-05 14:03:33 -07:00
|
|
|
"getSnapshotSlot" => Value::Number(Number::from(0)),
|
2021-09-02 13:25:42 -07:00
|
|
|
"getHighestSnapshotSlot" => json!(RpcSnapshotSlotInfo {
|
|
|
|
full: 100,
|
|
|
|
incremental: Some(110),
|
|
|
|
}),
|
2021-08-05 14:03:33 -07:00
|
|
|
"getBlockHeight" => Value::Number(Number::from(1234)),
|
|
|
|
"getSlotLeaders" => json!([PUBKEY]),
|
|
|
|
"getBlockProduction" => {
|
|
|
|
if params.is_null() {
|
|
|
|
json!(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-08-05 14:03:33 -07:00
|
|
|
value: RpcBlockProduction {
|
|
|
|
by_identity: HashMap::new(),
|
|
|
|
range: RpcBlockProductionRange {
|
|
|
|
first_slot: 1,
|
|
|
|
last_slot: 2,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
let config: Vec<RpcBlockProductionConfig> =
|
|
|
|
serde_json::from_value(params).unwrap();
|
|
|
|
let config = config[0].clone();
|
|
|
|
let mut by_identity = HashMap::new();
|
|
|
|
by_identity.insert(config.identity.unwrap(), (1, 123));
|
|
|
|
let config_range = config.range.unwrap_or_default();
|
|
|
|
|
|
|
|
json!(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-08-05 14:03:33 -07:00
|
|
|
value: RpcBlockProduction {
|
|
|
|
by_identity,
|
|
|
|
range: RpcBlockProductionRange {
|
|
|
|
first_slot: config_range.first_slot,
|
|
|
|
last_slot: {
|
|
|
|
if let Some(last_slot) = config_range.last_slot {
|
|
|
|
last_slot
|
|
|
|
} else {
|
|
|
|
2
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"getStakeActivation" => json!(RpcStakeActivation {
|
2021-08-23 17:49:37 -07:00
|
|
|
state: StakeActivationState::Activating,
|
2021-08-05 14:03:33 -07:00
|
|
|
active: 123,
|
|
|
|
inactive: 12,
|
|
|
|
}),
|
2022-07-17 11:39:39 -07:00
|
|
|
"getStakeMinimumDelegation" => json!(Response {
|
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
|
|
|
value: 123_456_789,
|
|
|
|
}),
|
2021-08-05 14:03:33 -07:00
|
|
|
"getSupply" => json!(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-08-05 14:03:33 -07:00
|
|
|
value: RpcSupply {
|
|
|
|
total: 100000000,
|
|
|
|
circulating: 50000,
|
|
|
|
non_circulating: 20000,
|
|
|
|
non_circulating_accounts: vec![PUBKEY.to_string()],
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
"getLargestAccounts" => {
|
|
|
|
let rpc_account_balance = RpcAccountBalance {
|
|
|
|
address: PUBKEY.to_string(),
|
|
|
|
lamports: 10000,
|
|
|
|
};
|
|
|
|
|
|
|
|
json!(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-08-05 14:03:33 -07:00
|
|
|
value: vec![rpc_account_balance],
|
|
|
|
})
|
|
|
|
}
|
|
|
|
"getVoteAccounts" => {
|
|
|
|
json!(RpcVoteAccountStatus {
|
|
|
|
current: vec![],
|
2021-08-23 17:49:37 -07:00
|
|
|
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(),
|
|
|
|
}],
|
2021-08-05 14:03:33 -07:00
|
|
|
})
|
|
|
|
}
|
2021-07-23 14:39:38 -07:00
|
|
|
"sendTransaction" => {
|
2020-04-06 18:27:37 -07:00
|
|
|
let signature = if self.url == "malicious" {
|
|
|
|
Signature::new(&[8; 64]).to_string()
|
|
|
|
} else {
|
|
|
|
let tx_str = params.as_array().unwrap()[0].as_str().unwrap().to_string();
|
2020-10-12 09:14:12 -07:00
|
|
|
let data = base64::decode(tx_str).unwrap();
|
2020-04-06 18:27:37 -07:00
|
|
|
let tx: Transaction = bincode::deserialize(&data).unwrap();
|
|
|
|
tx.signatures[0].to_string()
|
|
|
|
};
|
|
|
|
Value::String(signature)
|
|
|
|
}
|
2021-07-23 14:39:38 -07:00
|
|
|
"simulateTransaction" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-07-20 11:49:32 -07:00
|
|
|
value: RpcSimulateTransactionResult {
|
|
|
|
err: None,
|
|
|
|
logs: None,
|
|
|
|
accounts: None,
|
2021-07-20 12:02:10 -07:00
|
|
|
units_consumed: None,
|
2022-03-22 15:17:05 -07:00
|
|
|
return_data: None,
|
2021-07-20 11:49:32 -07:00
|
|
|
},
|
|
|
|
})?,
|
2021-07-23 14:39:38 -07:00
|
|
|
"getMinimumBalanceForRentExemption" => json![20],
|
|
|
|
"getVersion" => {
|
2020-10-20 19:50:24 -07:00
|
|
|
let version = Version::default();
|
|
|
|
json!(RpcVersionInfo {
|
|
|
|
solana_core: version.to_string(),
|
|
|
|
feature_set: Some(version.feature_set),
|
|
|
|
})
|
|
|
|
}
|
2021-08-13 09:08:20 -07:00
|
|
|
"getLatestBlockhash" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-08-13 09:08:20 -07:00
|
|
|
value: RpcBlockhash {
|
|
|
|
blockhash: PUBKEY.to_string(),
|
2021-10-26 13:54:26 -07:00
|
|
|
last_valid_block_height: 1234,
|
2021-08-13 09:08:20 -07:00
|
|
|
},
|
|
|
|
})?,
|
|
|
|
"getFeeForMessage" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-08-13 09:08:20 -07:00
|
|
|
value: json!(Some(0)),
|
|
|
|
})?,
|
2021-08-23 17:49:37 -07:00
|
|
|
"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(),
|
2022-03-09 00:09:08 -08:00
|
|
|
TransactionBinaryEncoding::Base58,
|
2021-08-23 17:49:37 -07:00
|
|
|
),
|
|
|
|
meta: None,
|
2022-03-07 23:20:34 -08:00
|
|
|
version: Some(TransactionVersion::LEGACY),
|
2021-08-23 17:49:37 -07:00
|
|
|
}],
|
|
|
|
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 {
|
2022-01-24 17:01:07 -08:00
|
|
|
signature: crate::mock_sender_for_cli::SIGNATURE.to_string(),
|
2021-08-23 17:49:37 -07:00
|
|
|
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,
|
|
|
|
}])?,
|
2023-01-06 22:04:34 -08:00
|
|
|
"getRecentPrioritizationFees" => serde_json::to_value(vec![RpcPrioritizationFee {
|
|
|
|
slot: 123_456_789,
|
|
|
|
prioritization_fee: 10_000,
|
|
|
|
}])?,
|
2021-09-27 13:59:25 -07:00
|
|
|
"getIdentity" => serde_json::to_value(RpcIdentity {
|
|
|
|
identity: PUBKEY.to_string(),
|
|
|
|
})?,
|
|
|
|
"getInflationGovernor" => serde_json::to_value(
|
|
|
|
RpcInflationGovernor {
|
|
|
|
initial: 0.08,
|
|
|
|
terminal: 0.015,
|
|
|
|
taper: 0.15,
|
|
|
|
foundation: 0.05,
|
|
|
|
foundation_term: 7.0,
|
|
|
|
})?,
|
|
|
|
"getInflationRate" => serde_json::to_value(
|
|
|
|
RpcInflationRate {
|
|
|
|
total: 0.08,
|
|
|
|
validator: 0.076,
|
|
|
|
foundation: 0.004,
|
|
|
|
epoch: 0,
|
|
|
|
})?,
|
|
|
|
"getInflationReward" => serde_json::to_value(vec![
|
|
|
|
Some(RpcInflationReward {
|
|
|
|
epoch: 2,
|
|
|
|
effective_slot: 224,
|
|
|
|
amount: 2500,
|
|
|
|
post_balance: 499999442500,
|
|
|
|
commission: None,
|
|
|
|
})])?,
|
|
|
|
"minimumLedgerSlot" => json![123],
|
|
|
|
"getMaxRetransmitSlot" => json![123],
|
|
|
|
"getMultipleAccounts" => serde_json::to_value(Response {
|
2022-05-11 21:17:21 -07:00
|
|
|
context: RpcResponseContext { slot: 1, api_version: None },
|
2021-09-27 13:59:25 -07:00
|
|
|
value: vec![Value::Null, Value::Null]
|
|
|
|
})?,
|
|
|
|
"getProgramAccounts" => {
|
2022-01-21 16:01:22 -08:00
|
|
|
let pubkey = Pubkey::from_str(PUBKEY).unwrap();
|
2021-09-27 13:59:25 -07:00
|
|
|
let account = Account {
|
|
|
|
lamports: 1_000_000,
|
|
|
|
data: vec![],
|
|
|
|
owner: pubkey,
|
|
|
|
executable: false,
|
|
|
|
rent_epoch: 0,
|
|
|
|
};
|
|
|
|
serde_json::to_value(vec![
|
|
|
|
RpcKeyedAccount {
|
|
|
|
pubkey: PUBKEY.to_string(),
|
|
|
|
account: UiAccount::encode(
|
|
|
|
&pubkey,
|
|
|
|
&account,
|
|
|
|
UiAccountEncoding::Base64,
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
])?
|
|
|
|
},
|
2019-03-12 17:26:07 -07:00
|
|
|
_ => Value::Null,
|
|
|
|
};
|
|
|
|
Ok(val)
|
|
|
|
}
|
2022-04-12 08:43:29 -07:00
|
|
|
|
|
|
|
fn url(&self) -> String {
|
|
|
|
format!("MockSender: {}", self.url)
|
|
|
|
}
|
2019-03-12 17:26:07 -07:00
|
|
|
}
|