This commit is contained in:
2026-07-23 16:37:12 +02:00
parent 99c345f2f2
commit 0da75c1311
2159 changed files with 230833 additions and 0 deletions

View File

@@ -0,0 +1,241 @@
// 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<crate::RpcCommitmentConfig>,
) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
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<crate::RpcAccountInfoConfig>,
) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
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<crate::RpcCommitmentConfig>,
}
impl crate::StandardHttpRequest for crate::GetTokenAccountBalanceRequest {
type Response = crate::RpcResponse<crate::RpcTokenAmount>;
const METHOD: &'static str = "getTokenAccountBalance";
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
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<crate::RpcAccountInfoConfig>,
}
impl crate::StandardHttpRequest for crate::GetTokenAccountsByDelegateRequest {
type Response = crate::RpcResponse<std::vec::Vec<crate::RpcKeyedAccount>>;
const METHOD: &'static str = "getTokenAccountsByDelegate";
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
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<crate::RpcAccountInfoConfig>,
}
impl crate::StandardHttpRequest for crate::GetTokenAccountsByOwnerRequest {
type Response = crate::RpcResponse<std::vec::Vec<crate::RpcKeyedAccount>>;
const METHOD: &'static str = "getTokenAccountsByOwner";
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
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<crate::RpcCommitmentConfig>,
}
impl crate::StandardHttpRequest for crate::GetTokenLargestAccountsRequest {
type Response = crate::RpcResponse<std::vec::Vec<crate::RpcTokenAccountBalance>>;
const METHOD: &'static str = "getTokenLargestAccounts";
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
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<crate::RpcCommitmentConfig>,
}
impl crate::StandardHttpRequest for crate::GetTokenSupplyRequest {
type Response = crate::RpcResponse<crate::RpcTokenAmount>;
const METHOD: &'static str = "getTokenSupply";
fn params(&self) -> kb_core::Result<std::vec::Vec<serde_json::Value>> {
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());
}
}