v0.2.2-pre.002
This commit is contained in:
138
crates/ksp-onchain-transport-lib/src/rpc_tokens.rs
Normal file
138
crates/ksp-onchain-transport-lib/src/rpc_tokens.rs
Normal file
@@ -0,0 +1,138 @@
|
||||
// file: crates/ksp-onchain-transport-lib/src/rpc_tokens.rs
|
||||
// version: 1
|
||||
|
||||
/// Exclusive selector accepted by token-account list RPC methods.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum SolanaTokenAccountSelector {
|
||||
/// Select token accounts for one mint.
|
||||
Mint(ksp_core_lib::Pubkey),
|
||||
/// Select token accounts owned by one token program.
|
||||
ProgramId(ksp_core_lib::Pubkey),
|
||||
}
|
||||
|
||||
impl SolanaTokenAccountSelector {
|
||||
/// Serializes the exclusive selector to the Solana JSON-RPC wire object.
|
||||
#[must_use]
|
||||
pub(crate) fn to_json_value(&self) -> serde_json::Value {
|
||||
return match self {
|
||||
Self::Mint(pubkey) => serde_json::json!({"mint": pubkey.to_string()}),
|
||||
Self::ProgramId(pubkey) => serde_json::json!({"programId": pubkey.to_string()}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Token amount returned by Solana HTTP token RPC methods.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SolanaTokenAmount {
|
||||
amount: std::string::String,
|
||||
decimals: u8,
|
||||
ui_amount: std::option::Option<f64>,
|
||||
ui_amount_string: std::string::String,
|
||||
}
|
||||
|
||||
impl SolanaTokenAmount {
|
||||
/// Returns the integer token amount as an exact decimal string.
|
||||
#[must_use]
|
||||
pub fn amount(&self) -> &str {
|
||||
return self.amount.as_str();
|
||||
}
|
||||
|
||||
/// Returns the mint decimal precision.
|
||||
#[must_use]
|
||||
pub const fn decimals(&self) -> u8 {
|
||||
return self.decimals;
|
||||
}
|
||||
|
||||
/// Returns the nullable floating-point UI amount exactly as provided by RPC.
|
||||
#[must_use]
|
||||
pub const fn ui_amount(&self) -> std::option::Option<f64> {
|
||||
return self.ui_amount;
|
||||
}
|
||||
|
||||
/// Returns the exact UI amount string provided by RPC.
|
||||
#[must_use]
|
||||
pub fn ui_amount_string(&self) -> &str {
|
||||
return self.ui_amount_string.as_str();
|
||||
}
|
||||
|
||||
/// Decodes one token amount from the Solana JSON wire shape.
|
||||
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
|
||||
let decoded = crate::decode_wire_json::<WireTokenAmount>(method, value);
|
||||
return match decoded {
|
||||
std::result::Result::Ok(wire) => std::result::Result::Ok(Self {
|
||||
amount: wire.amount,
|
||||
decimals: wire.decimals,
|
||||
ui_amount: wire.ui_amount,
|
||||
ui_amount_string: wire.ui_amount_string,
|
||||
}),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(error),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Token-account balance entry returned by `getTokenLargestAccounts`.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct SolanaTokenAccountBalance {
|
||||
address: ksp_core_lib::Pubkey,
|
||||
amount: crate::SolanaTokenAmount,
|
||||
}
|
||||
|
||||
impl SolanaTokenAccountBalance {
|
||||
/// Returns the token account address.
|
||||
#[must_use]
|
||||
pub const fn address(&self) -> &ksp_core_lib::Pubkey {
|
||||
return &self.address;
|
||||
}
|
||||
|
||||
/// Returns the token amount fields.
|
||||
#[must_use]
|
||||
pub const fn amount(&self) -> &crate::SolanaTokenAmount {
|
||||
return &self.amount;
|
||||
}
|
||||
|
||||
/// Decodes one token-account balance entry from the Solana JSON wire shape.
|
||||
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
|
||||
let decoded = crate::decode_wire_json::<WireTokenAccountBalance>(method, value);
|
||||
let wire = match decoded {
|
||||
std::result::Result::Ok(wire) => wire,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let address = crate::parse_wire_pubkey(method, "address", wire.address.as_str());
|
||||
let address = match address {
|
||||
std::result::Result::Ok(address) => address,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let amount = crate::SolanaTokenAmount {
|
||||
amount: wire.amount,
|
||||
decimals: wire.decimals,
|
||||
ui_amount: wire.ui_amount,
|
||||
ui_amount_string: wire.ui_amount_string,
|
||||
};
|
||||
return std::result::Result::Ok(Self { address, amount });
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct WireTokenAmount {
|
||||
amount: std::string::String,
|
||||
decimals: u8,
|
||||
#[serde(rename = "uiAmount")]
|
||||
ui_amount: std::option::Option<f64>,
|
||||
#[serde(rename = "uiAmountString")]
|
||||
ui_amount_string: std::string::String,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct WireTokenAccountBalance {
|
||||
address: std::string::String,
|
||||
amount: std::string::String,
|
||||
decimals: u8,
|
||||
#[serde(rename = "uiAmount")]
|
||||
ui_amount: std::option::Option<f64>,
|
||||
#[serde(rename = "uiAmountString")]
|
||||
ui_amount_string: std::string::String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "../unit_tests/rpc_tokens.rs"]
|
||||
mod tests;
|
||||
Reference in New Issue
Block a user