156 lines
6.5 KiB
Rust
156 lines
6.5 KiB
Rust
// file: kb_rpc/src/standard_http_transactions.rs
|
|
// version: 2
|
|
|
|
//! Configurable standard transaction-oriented Solana HTTP JSON-RPC requests.
|
|
|
|
/// Prioritization fee observed for one recent slot.
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct RpcPrioritizationFee {
|
|
/// Slot from which the fee sample was retained.
|
|
pub slot: u64,
|
|
/// Minimum compute-unit price in micro-lamports for the requested writable set.
|
|
pub prioritization_fee: u64,
|
|
}
|
|
|
|
/// Typed `getRecentPrioritizationFees` request.
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
|
pub struct GetRecentPrioritizationFeesRequest {
|
|
/// Optional writable account set. `None` omits the parameter; `Some([])` sends an explicit empty set.
|
|
pub locked_writable_accounts: std::option::Option<std::vec::Vec<std::string::String>>,
|
|
}
|
|
|
|
impl crate::StandardHttpRequest for crate::GetRecentPrioritizationFeesRequest {
|
|
type Response = std::vec::Vec<crate::RpcPrioritizationFee>;
|
|
|
|
const METHOD: &'static str = "getRecentPrioritizationFees";
|
|
|
|
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
|
if let std::option::Option::Some(accounts) = &self.locked_writable_accounts {
|
|
let validation_result = crate::standard_http::validate_pubkey_list(
|
|
accounts,
|
|
"getRecentPrioritizationFees writable account",
|
|
crate::constants::MAX_PRIORITIZATION_FEE_ACCOUNT_COUNT,
|
|
);
|
|
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, accounts) {
|
|
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 `getTransactionCount` request.
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
|
pub struct GetTransactionCountRequest {
|
|
/// Optional commitment and minimum-context options.
|
|
pub config: std::option::Option<crate::RpcContextConfig>,
|
|
}
|
|
|
|
impl crate::StandardHttpRequest for crate::GetTransactionCountRequest {
|
|
type Response = u64;
|
|
|
|
const METHOD: &'static str = "getTransactionCount";
|
|
|
|
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
|
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),
|
|
};
|
|
return std::result::Result::Ok(std::vec![value]);
|
|
}
|
|
return std::result::Result::Ok(std::vec::Vec::new());
|
|
}
|
|
}
|
|
|
|
/// Typed `isBlockhashValid` request.
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub struct IsBlockhashValidRequest {
|
|
/// Base58 blockhash being checked.
|
|
pub blockhash: std::string::String,
|
|
/// Optional commitment and minimum-context options.
|
|
pub config: std::option::Option<crate::RpcContextConfig>,
|
|
}
|
|
|
|
impl crate::StandardHttpRequest for crate::IsBlockhashValidRequest {
|
|
type Response = crate::RpcResponse<bool>;
|
|
|
|
const METHOD: &'static str = "isBlockhashValid";
|
|
|
|
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
|
|
let validation_result =
|
|
crate::validate_solana_hash_text(&self.blockhash, "isBlockhashValid blockhash");
|
|
if let std::result::Result::Err(error) = validation_result {
|
|
return std::result::Result::Err(error);
|
|
}
|
|
let mut params = std::vec![serde_json::Value::String(self.blockhash.clone())];
|
|
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);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
fn pubkey(seed: u8) -> std::string::String {
|
|
return bs58::encode([seed; 32]).into_string();
|
|
}
|
|
|
|
#[test]
|
|
fn prioritization_fee_request_distinguishes_omitted_and_explicit_empty_sets() {
|
|
let omitted = crate::GetRecentPrioritizationFeesRequest {
|
|
locked_writable_accounts: std::option::Option::None,
|
|
};
|
|
let explicit = crate::GetRecentPrioritizationFeesRequest {
|
|
locked_writable_accounts: std::option::Option::Some(std::vec::Vec::new()),
|
|
};
|
|
let omitted_params = match crate::StandardHttpRequest::params(&omitted) {
|
|
std::result::Result::Ok(params) => params,
|
|
std::result::Result::Err(error) => panic!("unexpected omitted params error: {error}"),
|
|
};
|
|
let explicit_params = match crate::StandardHttpRequest::params(&explicit) {
|
|
std::result::Result::Ok(params) => params,
|
|
std::result::Result::Err(error) => panic!("unexpected explicit params error: {error}"),
|
|
};
|
|
assert_eq!(omitted_params, std::vec::Vec::<serde_json::Value>::new());
|
|
assert_eq!(explicit_params, std::vec![serde_json::json!([])]);
|
|
}
|
|
|
|
#[test]
|
|
fn prioritization_fee_request_enforces_official_account_bound() {
|
|
let request = crate::GetRecentPrioritizationFeesRequest {
|
|
locked_writable_accounts: std::option::Option::Some(
|
|
(0_u16..129_u16).map(|value| return pubkey(value as u8)).collect(),
|
|
),
|
|
};
|
|
assert!(crate::StandardHttpRequest::params(&request).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn blockhash_validity_preserves_minimum_context_slot() {
|
|
let request = crate::IsBlockhashValidRequest {
|
|
blockhash: pubkey(9),
|
|
config: std::option::Option::Some(crate::RpcContextConfig {
|
|
commitment: std::option::Option::Some(crate::RpcCommitmentLevel::Finalized),
|
|
min_context_slot: std::option::Option::Some(123),
|
|
}),
|
|
};
|
|
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]["minContextSlot"], serde_json::Value::from(123_u64));
|
|
}
|
|
}
|