// file: kb_rpc/src/standard_http_tokens.rs // version: 1 //! Configurable standard SPL Token-oriented Solana HTTP JSON-RPC requests. fn pubkey_with_optional_commitment_params( method: &str, address: &str, field: &str, config: &std::option::Option, ) -> kb_core::Result> { let validation_result = crate::validate_solana_pubkey_text(address, field); if let std::result::Result::Err(error) = validation_result { return std::result::Result::Err(error); } let mut params = std::vec![serde_json::Value::String(address.to_string())]; if let std::option::Option::Some(config) = config { let config_value = match crate::standard_http::serialize_parameter(method, config) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; params.push(config_value); } return std::result::Result::Ok(params); } fn token_accounts_query_params( method: &str, authority: &str, field: &str, filter: &crate::RpcTokenAccountsFilter, config: &std::option::Option, ) -> kb_core::Result> { let authority_result = crate::validate_solana_pubkey_text(authority, field); if let std::result::Result::Err(error) = authority_result { return std::result::Result::Err(error); } let filter_result = filter.validate(); if let std::result::Result::Err(error) = filter_result { return std::result::Result::Err(error); } if let std::option::Option::Some(config) = config { let config_result = config.validate(); if let std::result::Result::Err(error) = config_result { return std::result::Result::Err(error); } } let filter_value = match crate::standard_http::serialize_parameter(method, filter) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; let mut params = std::vec![serde_json::Value::String(authority.to_string()), filter_value,]; if let std::option::Option::Some(config) = config { let config_value = match crate::standard_http::serialize_parameter(method, config) { std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; params.push(config_value); } return std::result::Result::Ok(params); } /// Typed `getTokenAccountBalance` request. #[derive(Clone, Debug, Eq, PartialEq)] pub struct GetTokenAccountBalanceRequest { /// Token account public key. pub address: std::string::String, /// Optional commitment option. pub config: std::option::Option, } impl crate::StandardHttpRequest for crate::GetTokenAccountBalanceRequest { type Response = crate::RpcResponse; const METHOD: &'static str = "getTokenAccountBalance"; fn params(&self) -> kb_core::Result> { return crate::standard_http_tokens::pubkey_with_optional_commitment_params( Self::METHOD, &self.address, "getTokenAccountBalance address", &self.config, ); } } /// Typed `getTokenAccountsByDelegate` request. #[derive(Clone, Debug, Eq, PartialEq)] pub struct GetTokenAccountsByDelegateRequest { /// Delegate public key. pub delegate: std::string::String, /// Mint or Token Program selector. pub filter: crate::RpcTokenAccountsFilter, /// Optional account representation and context options. pub config: std::option::Option, } impl crate::StandardHttpRequest for crate::GetTokenAccountsByDelegateRequest { type Response = crate::RpcResponse>; const METHOD: &'static str = "getTokenAccountsByDelegate"; fn params(&self) -> kb_core::Result> { return crate::standard_http_tokens::token_accounts_query_params( Self::METHOD, &self.delegate, "getTokenAccountsByDelegate delegate", &self.filter, &self.config, ); } } /// Typed `getTokenAccountsByOwner` request. #[derive(Clone, Debug, Eq, PartialEq)] pub struct GetTokenAccountsByOwnerRequest { /// Owner public key. pub owner: std::string::String, /// Mint or Token Program selector. pub filter: crate::RpcTokenAccountsFilter, /// Optional account representation and context options. pub config: std::option::Option, } impl crate::StandardHttpRequest for crate::GetTokenAccountsByOwnerRequest { type Response = crate::RpcResponse>; const METHOD: &'static str = "getTokenAccountsByOwner"; fn params(&self) -> kb_core::Result> { return crate::standard_http_tokens::token_accounts_query_params( Self::METHOD, &self.owner, "getTokenAccountsByOwner owner", &self.filter, &self.config, ); } } /// Typed `getTokenLargestAccounts` request. #[derive(Clone, Debug, Eq, PartialEq)] pub struct GetTokenLargestAccountsRequest { /// Mint public key. pub mint: std::string::String, /// Optional commitment option. pub config: std::option::Option, } impl crate::StandardHttpRequest for crate::GetTokenLargestAccountsRequest { type Response = crate::RpcResponse>; const METHOD: &'static str = "getTokenLargestAccounts"; fn params(&self) -> kb_core::Result> { return crate::standard_http_tokens::pubkey_with_optional_commitment_params( Self::METHOD, &self.mint, "getTokenLargestAccounts mint", &self.config, ); } } /// Typed `getTokenSupply` request. #[derive(Clone, Debug, Eq, PartialEq)] pub struct GetTokenSupplyRequest { /// Mint public key. pub mint: std::string::String, /// Optional commitment option. pub config: std::option::Option, } impl crate::StandardHttpRequest for crate::GetTokenSupplyRequest { type Response = crate::RpcResponse; const METHOD: &'static str = "getTokenSupply"; fn params(&self) -> kb_core::Result> { return crate::standard_http_tokens::pubkey_with_optional_commitment_params( Self::METHOD, &self.mint, "getTokenSupply mint", &self.config, ); } } #[cfg(test)] mod tests { fn pubkey(seed: u8) -> std::string::String { return bs58::encode([seed; 32]).into_string(); } #[test] fn token_owner_query_preserves_filter_and_independent_account_options() { let request = crate::GetTokenAccountsByOwnerRequest { owner: pubkey(1), filter: crate::RpcTokenAccountsFilter::ProgramId(pubkey(2)), config: std::option::Option::Some(crate::RpcAccountInfoConfig { encoding: std::option::Option::Some(crate::RpcAccountEncoding::Base64Zstd), data_slice: std::option::Option::None, commitment: std::option::Option::Some(crate::RpcCommitmentLevel::Processed), min_context_slot: std::option::Option::Some(42), }), }; 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], serde_json::json!({ "programId": pubkey(2) })); assert_eq!(params[2]["encoding"], serde_json::Value::String("base64+zstd".to_string())); assert_eq!(params[2]["commitment"], serde_json::Value::String("processed".to_string())); } #[test] fn token_balance_omits_unselected_options() { let request = crate::GetTokenAccountBalanceRequest { address: pubkey(3), config: std::option::Option::None, }; 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, std::vec![serde_json::Value::String(pubkey(3))]); let configured = crate::GetTokenSupplyRequest { mint: pubkey(4), config: std::option::Option::Some(crate::RpcCommitmentConfig { commitment: std::option::Option::Some(crate::RpcCommitmentLevel::Finalized), }), }; let configured_params = match crate::StandardHttpRequest::params(&configured) { std::result::Result::Ok(params) => params, std::result::Result::Err(error) => panic!("params failed: {error}"), }; assert_eq!(configured_params[1], serde_json::json!({ "commitment": "finalized" })); assert!(configured_params[1].get("minContextSlot").is_none()); } }