// 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>, } impl crate::StandardHttpRequest for crate::GetRecentPrioritizationFeesRequest { type Response = std::vec::Vec; const METHOD: &'static str = "getRecentPrioritizationFees"; fn params(&self) -> kb_core::Result> { 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, } impl crate::StandardHttpRequest for crate::GetTransactionCountRequest { type Response = u64; const METHOD: &'static str = "getTransactionCount"; fn params(&self) -> kb_core::Result> { 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, } impl crate::StandardHttpRequest for crate::IsBlockhashValidRequest { type Response = crate::RpcResponse; const METHOD: &'static str = "isBlockhashValid"; fn params(&self) -> kb_core::Result> { 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::::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)); } }