0.1.0
This commit is contained in:
@@ -0,0 +1,548 @@
|
||||
// file: kb_rpc/src/standard_http_blocks.rs
|
||||
// version: 1
|
||||
|
||||
//! Configurable standard block and ledger Solana HTTP JSON-RPC requests.
|
||||
|
||||
/// Options accepted by `getBlock`.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcBlockConfig {
|
||||
/// Optional transaction encoding.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub encoding: std::option::Option<crate::RpcTransactionEncoding>,
|
||||
/// Optional transaction detail level.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub transaction_details: std::option::Option<crate::RpcTransactionDetails>,
|
||||
/// Whether rewards must be included.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub rewards: std::option::Option<bool>,
|
||||
/// Optional confirmed or finalized commitment.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub commitment: std::option::Option<crate::RpcCommitmentLevel>,
|
||||
/// Highest transaction version the caller can decode.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub max_supported_transaction_version: std::option::Option<u8>,
|
||||
}
|
||||
|
||||
impl crate::RpcBlockConfig {
|
||||
/// Rejects the processed commitment unsupported by block-history methods.
|
||||
pub fn validate(&self) -> kb_core::Result<()> {
|
||||
if self.commitment == std::option::Option::Some(crate::RpcCommitmentLevel::Processed) {
|
||||
return std::result::Result::Err(kb_core::Error::config(
|
||||
"getBlock does not support processed commitment",
|
||||
));
|
||||
}
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
/// Inclusive slot range accepted by `getBlockProduction`.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcBlockProductionConfigRange {
|
||||
/// First slot included in the range.
|
||||
pub first_slot: u64,
|
||||
/// Optional final slot included in the range.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub last_slot: std::option::Option<u64>,
|
||||
}
|
||||
|
||||
/// Options accepted by `getBlockProduction`.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcBlockProductionConfig {
|
||||
/// Optional validator identity filter.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub identity: std::option::Option<std::string::String>,
|
||||
/// Optional inclusive slot range.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub range: std::option::Option<crate::RpcBlockProductionConfigRange>,
|
||||
/// Optional commitment level.
|
||||
#[serde(skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub commitment: std::option::Option<crate::RpcCommitmentLevel>,
|
||||
}
|
||||
|
||||
impl crate::RpcBlockProductionConfig {
|
||||
/// Validates identity and range ordering.
|
||||
pub fn validate(&self) -> kb_core::Result<()> {
|
||||
if let std::option::Option::Some(identity) = &self.identity {
|
||||
let identity_result =
|
||||
crate::validate_solana_pubkey_text(identity, "getBlockProduction identity");
|
||||
if let std::result::Result::Err(error) = identity_result {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
}
|
||||
if let std::option::Option::Some(range) = self.range {
|
||||
if let std::option::Option::Some(last_slot) = range.last_slot {
|
||||
if last_slot < range.first_slot {
|
||||
return std::result::Result::Err(kb_core::Error::config(
|
||||
"getBlockProduction last slot must not precede first slot",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
/// Reward category attached to a block reward entry.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum RpcRewardType {
|
||||
/// Transaction fee reward.
|
||||
Fee,
|
||||
/// Rent reward.
|
||||
Rent,
|
||||
/// Staking reward.
|
||||
Staking,
|
||||
/// Vote reward.
|
||||
Voting,
|
||||
}
|
||||
|
||||
/// One reward entry returned with a block.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcReward {
|
||||
/// Recipient public key.
|
||||
pub pubkey: std::string::String,
|
||||
/// Signed lamport balance change.
|
||||
pub lamports: i64,
|
||||
/// Recipient balance after the reward.
|
||||
pub post_balance: u64,
|
||||
/// Optional reward category.
|
||||
pub reward_type: std::option::Option<crate::RpcRewardType>,
|
||||
/// Optional validator commission percentage.
|
||||
pub commission: std::option::Option<u8>,
|
||||
/// Optional validator commission in basis points.
|
||||
#[serde(default, skip_serializing_if = "std::option::Option::is_none")]
|
||||
pub commission_bps: std::option::Option<u16>,
|
||||
}
|
||||
|
||||
/// Encoding-dependent confirmed block returned by `getBlock`.
|
||||
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcConfirmedBlock {
|
||||
/// Block hash.
|
||||
pub blockhash: std::string::String,
|
||||
/// Previous block hash.
|
||||
pub previous_blockhash: std::string::String,
|
||||
/// Parent slot.
|
||||
pub parent_slot: u64,
|
||||
/// Encoding-dependent transaction entries when requested.
|
||||
#[serde(default)]
|
||||
pub transactions: std::option::Option<std::vec::Vec<serde_json::Value>>,
|
||||
/// Signature list when signature-only details are requested.
|
||||
#[serde(default)]
|
||||
pub signatures: std::option::Option<std::vec::Vec<std::string::String>>,
|
||||
/// Rewards when requested.
|
||||
#[serde(default)]
|
||||
pub rewards: std::option::Option<std::vec::Vec<crate::RpcReward>>,
|
||||
/// Unix block time when available.
|
||||
#[serde(default)]
|
||||
pub block_time: std::option::Option<i64>,
|
||||
/// Block height when available.
|
||||
#[serde(default)]
|
||||
pub block_height: std::option::Option<u64>,
|
||||
/// Number of reward partitions when available.
|
||||
#[serde(default)]
|
||||
pub num_reward_partitions: std::option::Option<u64>,
|
||||
}
|
||||
|
||||
/// Stake commitment information returned for one block.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcBlockCommitment {
|
||||
/// Commitment stake by lockout depth, or `None` when unavailable.
|
||||
pub commitment: std::option::Option<std::vec::Vec<u64>>,
|
||||
/// Total active stake used for the commitment calculation.
|
||||
pub total_stake: u64,
|
||||
}
|
||||
|
||||
/// Actual slot range represented by a block-production response.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcBlockProductionRange {
|
||||
/// First represented slot.
|
||||
pub first_slot: u64,
|
||||
/// Last represented slot.
|
||||
pub last_slot: u64,
|
||||
}
|
||||
|
||||
/// Block-production counts grouped by validator identity.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcBlockProduction {
|
||||
/// Validator identity to `(leader slots, blocks produced)` map.
|
||||
pub by_identity: std::collections::BTreeMap<std::string::String, (usize, usize)>,
|
||||
/// Actual represented slot range.
|
||||
pub range: crate::RpcBlockProductionRange,
|
||||
}
|
||||
|
||||
/// Recent cluster performance sample.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcPerformanceSample {
|
||||
/// Slot at the end of the sample window.
|
||||
pub slot: u64,
|
||||
/// Total transactions processed during the sample.
|
||||
pub num_transactions: u64,
|
||||
/// Optional count excluding vote transactions.
|
||||
#[serde(default)]
|
||||
pub num_non_vote_transactions: std::option::Option<u64>,
|
||||
/// Slots processed during the sample.
|
||||
pub num_slots: u64,
|
||||
/// Sample period in seconds.
|
||||
pub sample_period_secs: u16,
|
||||
}
|
||||
|
||||
/// Typed `getBlock` request.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct GetBlockRequest {
|
||||
/// Block slot.
|
||||
pub slot: u64,
|
||||
/// Optional encoding, details, rewards, commitment and version options.
|
||||
pub config: std::option::Option<crate::RpcBlockConfig>,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetBlockRequest {
|
||||
type Response = std::option::Option<crate::RpcConfirmedBlock>;
|
||||
|
||||
const METHOD: &'static str = "getBlock";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
let mut params = std::vec![serde_json::Value::from(self.slot)];
|
||||
if let std::option::Option::Some(config) = &self.config {
|
||||
let config_result = config.validate();
|
||||
if let std::result::Result::Err(error) = config_result {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let value = match crate::standard_http::serialize_parameter(Self::METHOD, config) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
params.push(value);
|
||||
}
|
||||
return std::result::Result::Ok(params);
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `getBlockCommitment` request.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct GetBlockCommitmentRequest {
|
||||
/// Block slot.
|
||||
pub slot: u64,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetBlockCommitmentRequest {
|
||||
type Response = crate::RpcBlockCommitment;
|
||||
|
||||
const METHOD: &'static str = "getBlockCommitment";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
return std::result::Result::Ok(std::vec![serde_json::Value::from(self.slot)]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `getBlockProduction` request.
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
||||
pub struct GetBlockProductionRequest {
|
||||
/// Optional identity, range and commitment options.
|
||||
pub config: std::option::Option<crate::RpcBlockProductionConfig>,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetBlockProductionRequest {
|
||||
type Response = crate::RpcResponse<crate::RpcBlockProduction>;
|
||||
|
||||
const METHOD: &'static str = "getBlockProduction";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
if let std::option::Option::Some(config) = &self.config {
|
||||
let validation_result = config.validate();
|
||||
if let std::result::Result::Err(error) = validation_result {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let value = match crate::standard_http::serialize_parameter(Self::METHOD, config) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return std::result::Result::Ok(std::vec![value]);
|
||||
}
|
||||
return std::result::Result::Ok(std::vec::Vec::new());
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `getBlocks` request.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct GetBlocksRequest {
|
||||
/// First slot included in the scan.
|
||||
pub start_slot: u64,
|
||||
/// Optional final slot included in the scan.
|
||||
pub end_slot: std::option::Option<u64>,
|
||||
/// Optional confirmed or finalized context options.
|
||||
pub config: std::option::Option<crate::RpcContextConfig>,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetBlocksRequest {
|
||||
type Response = std::vec::Vec<u64>;
|
||||
|
||||
const METHOD: &'static str = "getBlocks";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
if let std::option::Option::Some(end_slot) = self.end_slot {
|
||||
if end_slot >= self.start_slot
|
||||
&& end_slot.saturating_sub(self.start_slot) > crate::constants::MAX_BLOCK_RANGE
|
||||
{
|
||||
return std::result::Result::Err(kb_core::Error::config(format!(
|
||||
"getBlocks range must not exceed {} slots",
|
||||
crate::constants::MAX_BLOCK_RANGE
|
||||
)));
|
||||
}
|
||||
}
|
||||
if let std::option::Option::Some(config) = &self.config {
|
||||
if config.commitment == std::option::Option::Some(crate::RpcCommitmentLevel::Processed)
|
||||
{
|
||||
return std::result::Result::Err(kb_core::Error::config(
|
||||
"getBlocks does not support processed commitment",
|
||||
));
|
||||
}
|
||||
}
|
||||
let mut params = std::vec![serde_json::Value::from(self.start_slot)];
|
||||
if let std::option::Option::Some(end_slot) = self.end_slot {
|
||||
params.push(serde_json::Value::from(end_slot));
|
||||
}
|
||||
if let std::option::Option::Some(config) = &self.config {
|
||||
let value = match crate::standard_http::serialize_parameter(Self::METHOD, config) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
params.push(value);
|
||||
}
|
||||
return std::result::Result::Ok(params);
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `getBlocksWithLimit` request.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct GetBlocksWithLimitRequest {
|
||||
/// First slot considered by the scan.
|
||||
pub start_slot: u64,
|
||||
/// Maximum number of block slots returned.
|
||||
pub limit: u64,
|
||||
/// Optional confirmed or finalized context options.
|
||||
pub config: std::option::Option<crate::RpcContextConfig>,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetBlocksWithLimitRequest {
|
||||
type Response = std::vec::Vec<u64>;
|
||||
|
||||
const METHOD: &'static str = "getBlocksWithLimit";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
if self.limit > crate::constants::MAX_BLOCK_RANGE {
|
||||
return std::result::Result::Err(kb_core::Error::config(format!(
|
||||
"getBlocksWithLimit limit must not exceed {}",
|
||||
crate::constants::MAX_BLOCK_RANGE
|
||||
)));
|
||||
}
|
||||
if let std::option::Option::Some(config) = &self.config {
|
||||
if config.commitment == std::option::Option::Some(crate::RpcCommitmentLevel::Processed)
|
||||
{
|
||||
return std::result::Result::Err(kb_core::Error::config(
|
||||
"getBlocksWithLimit does not support processed commitment",
|
||||
));
|
||||
}
|
||||
}
|
||||
let mut params = std::vec![
|
||||
serde_json::Value::from(self.start_slot),
|
||||
serde_json::Value::from(self.limit),
|
||||
];
|
||||
if let std::option::Option::Some(config) = &self.config {
|
||||
let value = match crate::standard_http::serialize_parameter(Self::METHOD, config) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
params.push(value);
|
||||
}
|
||||
return std::result::Result::Ok(params);
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `getBlockTime` request.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct GetBlockTimeRequest {
|
||||
/// Block slot.
|
||||
pub slot: u64,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetBlockTimeRequest {
|
||||
type Response = std::option::Option<i64>;
|
||||
|
||||
const METHOD: &'static str = "getBlockTime";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
return std::result::Result::Ok(std::vec![serde_json::Value::from(self.slot)]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `getFirstAvailableBlock` request.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
pub struct GetFirstAvailableBlockRequest;
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetFirstAvailableBlockRequest {
|
||||
type Response = u64;
|
||||
|
||||
const METHOD: &'static str = "getFirstAvailableBlock";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
return std::result::Result::Ok(std::vec::Vec::new());
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `getRecentPerformanceSamples` request.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
pub struct GetRecentPerformanceSamplesRequest {
|
||||
/// Optional sample count. Absence delegates the default to the endpoint.
|
||||
pub limit: std::option::Option<usize>,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpRequest for crate::GetRecentPerformanceSamplesRequest {
|
||||
type Response = std::vec::Vec<crate::RpcPerformanceSample>;
|
||||
|
||||
const METHOD: &'static str = "getRecentPerformanceSamples";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
if let std::option::Option::Some(limit) = self.limit {
|
||||
if limit > crate::constants::MAX_PERFORMANCE_SAMPLE_COUNT {
|
||||
return std::result::Result::Err(kb_core::Error::config(format!(
|
||||
"getRecentPerformanceSamples limit must not exceed {}",
|
||||
crate::constants::MAX_PERFORMANCE_SAMPLE_COUNT
|
||||
)));
|
||||
}
|
||||
return std::result::Result::Ok(std::vec![serde_json::Value::from(limit)]);
|
||||
}
|
||||
return std::result::Result::Ok(std::vec::Vec::new());
|
||||
}
|
||||
}
|
||||
|
||||
/// Typed `minimumLedgerSlot` request.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
pub struct MinimumLedgerSlotRequest;
|
||||
|
||||
impl crate::StandardHttpRequest for crate::MinimumLedgerSlotRequest {
|
||||
type Response = u64;
|
||||
|
||||
const METHOD: &'static str = "minimumLedgerSlot";
|
||||
|
||||
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
||||
return std::result::Result::Ok(std::vec::Vec::new());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn block_options_remain_independently_selectable() {
|
||||
let request = crate::GetBlockRequest {
|
||||
slot: 55,
|
||||
config: std::option::Option::Some(crate::RpcBlockConfig {
|
||||
encoding: std::option::Option::Some(crate::RpcTransactionEncoding::JsonParsed),
|
||||
transaction_details: std::option::Option::Some(
|
||||
crate::RpcTransactionDetails::Accounts,
|
||||
),
|
||||
rewards: std::option::Option::Some(false),
|
||||
commitment: std::option::Option::Some(crate::RpcCommitmentLevel::Confirmed),
|
||||
max_supported_transaction_version: std::option::Option::Some(0),
|
||||
}),
|
||||
};
|
||||
let params = match crate::StandardHttpRequest::params(&request) {
|
||||
std::result::Result::Ok(params) => params,
|
||||
std::result::Result::Err(error) => panic!("params failed: {error}"),
|
||||
};
|
||||
assert_eq!(params[1]["encoding"], serde_json::Value::String("jsonParsed".to_string()));
|
||||
assert_eq!(
|
||||
params[1]["transactionDetails"],
|
||||
serde_json::Value::String("accounts".to_string())
|
||||
);
|
||||
assert_eq!(params[1]["rewards"], serde_json::Value::Bool(false));
|
||||
assert_eq!(params[1]["maxSupportedTransactionVersion"], serde_json::Value::from(0_u64));
|
||||
|
||||
let reward = match serde_json::from_value::<crate::RpcReward>(serde_json::json!({
|
||||
"pubkey": "validator",
|
||||
"lamports": 42,
|
||||
"postBalance": 84,
|
||||
"rewardType": "voting",
|
||||
"commission": 5,
|
||||
"commissionBps": 550
|
||||
})) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => panic!("reward parsing failed: {error}"),
|
||||
};
|
||||
assert_eq!(reward.commission, std::option::Option::Some(5));
|
||||
assert_eq!(reward.commission_bps, std::option::Option::Some(550));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn blocks_without_end_slot_places_config_in_second_position() {
|
||||
let request = crate::GetBlocksRequest {
|
||||
start_slot: 10,
|
||||
end_slot: std::option::Option::None,
|
||||
config: std::option::Option::Some(crate::RpcContextConfig {
|
||||
commitment: std::option::Option::Some(crate::RpcCommitmentLevel::Finalized),
|
||||
min_context_slot: std::option::Option::Some(9),
|
||||
}),
|
||||
};
|
||||
let params = match crate::StandardHttpRequest::params(&request) {
|
||||
std::result::Result::Ok(params) => params,
|
||||
std::result::Result::Err(error) => panic!("params failed: {error}"),
|
||||
};
|
||||
assert_eq!(params.len(), 2);
|
||||
assert_eq!(params[1]["commitment"], serde_json::Value::String("finalized".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_ranges_and_performance_samples_are_bounded() {
|
||||
let range = crate::GetBlocksRequest {
|
||||
start_slot: 0,
|
||||
end_slot: std::option::Option::Some(500_001),
|
||||
config: std::option::Option::None,
|
||||
};
|
||||
let samples =
|
||||
crate::GetRecentPerformanceSamplesRequest { limit: std::option::Option::Some(721) };
|
||||
assert!(crate::StandardHttpRequest::params(&range).is_err());
|
||||
assert!(crate::StandardHttpRequest::params(&samples).is_err());
|
||||
|
||||
let reversed_range = crate::GetBlocksRequest {
|
||||
start_slot: 10,
|
||||
end_slot: std::option::Option::Some(9),
|
||||
config: std::option::Option::None,
|
||||
};
|
||||
let zero_blocks = crate::GetBlocksWithLimitRequest {
|
||||
start_slot: 10,
|
||||
limit: 0,
|
||||
config: std::option::Option::None,
|
||||
};
|
||||
let zero_samples =
|
||||
crate::GetRecentPerformanceSamplesRequest { limit: std::option::Option::Some(0) };
|
||||
let reversed_params = match crate::StandardHttpRequest::params(&reversed_range) {
|
||||
std::result::Result::Ok(params) => params,
|
||||
std::result::Result::Err(error) => panic!("reversed range failed: {error}"),
|
||||
};
|
||||
let zero_block_params = match crate::StandardHttpRequest::params(&zero_blocks) {
|
||||
std::result::Result::Ok(params) => params,
|
||||
std::result::Result::Err(error) => panic!("zero block limit failed: {error}"),
|
||||
};
|
||||
let zero_sample_params = match crate::StandardHttpRequest::params(&zero_samples) {
|
||||
std::result::Result::Ok(params) => params,
|
||||
std::result::Result::Err(error) => panic!("zero sample limit failed: {error}"),
|
||||
};
|
||||
assert_eq!(
|
||||
reversed_params,
|
||||
std::vec![serde_json::Value::from(10_u64), serde_json::Value::from(9_u64),]
|
||||
);
|
||||
assert_eq!(
|
||||
zero_block_params,
|
||||
std::vec![serde_json::Value::from(10_u64), serde_json::Value::from(0_u64),]
|
||||
);
|
||||
assert_eq!(zero_sample_params, std::vec![serde_json::Value::from(0_u64)]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user