v0.2.4-pre.007

This commit is contained in:
2026-08-18 21:33:21 +02:00
parent 7a889dd466
commit 4252a21140
13 changed files with 898 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/rpc_economics.rs
// version: 2
// version: 3
/// Inflation-governor values returned by `getInflationGovernor`.
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -43,7 +43,6 @@ impl SolanaInflationGovernor {
}
/// Decodes an inflation-governor result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireInflationGovernor>(method, value);
return match decoded {
@@ -94,7 +93,6 @@ impl SolanaInflationRate {
}
/// Decodes an inflation-rate result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireInflationRate>(method, value);
return match decoded {
@@ -260,14 +258,12 @@ impl SolanaSupplyConfig {
}
/// Returns whether this config would serialize to an empty object.
#[cfg(test)]
pub(crate) const fn is_empty(&self) -> bool {
return self.commitment.is_none() && self.exclude_non_circulating_accounts_list.is_none();
}
/// Serializes this config to the exact Solana JSON-RPC object.
#[must_use]
#[cfg(test)]
pub(crate) fn to_json_value(self) -> serde_json::Value {
let mut object = serde_json::Map::new();
if let std::option::Option::Some(commitment) = self.commitment {
@@ -315,7 +311,6 @@ impl SolanaSupply {
}
/// Decodes a supply result from its Solana JSON wire shape.
#[cfg(test)]
pub(crate) fn decode_wire(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<Self> {
let decoded = crate::decode_wire_json::<WireSupply>(method, value);
let wire = match decoded {
@@ -339,7 +334,152 @@ impl SolanaSupply {
}
}
#[cfg(test)]
impl crate::HttpTransportPool {
/// Executes typed `getInflationGovernor` and returns the runtime-provided schedule values unchanged.
pub async fn get_inflation_governor(
&self,
role: &crate::HttpRoleName,
config: std::option::Option<&crate::SolanaCommitmentConfig>,
) -> ksp_core_lib::Result<crate::SolanaInflationGovernor> {
let mut params = std::vec::Vec::new();
push_economics_commitment_config(&mut params, config);
let value = self.execute_economics_rpc("getInflationGovernor", role, params).await;
return match value {
std::result::Result::Ok(value) => crate::SolanaInflationGovernor::decode_wire("getInflationGovernor", value),
std::result::Result::Err(error) => std::result::Result::Err(error),
};
}
/// Executes typed `getInflationRate` without locally recalculating the inflation schedule.
pub async fn get_inflation_rate(&self, role: &crate::HttpRoleName) -> ksp_core_lib::Result<crate::SolanaInflationRate> {
let value = self.execute_economics_rpc("getInflationRate", role, std::vec::Vec::new()).await;
return match value {
std::result::Result::Ok(value) => crate::SolanaInflationRate::decode_wire("getInflationRate", value),
std::result::Result::Err(error) => std::result::Result::Err(error),
};
}
/// Executes typed `getStakeMinimumDelegation` and preserves the contextual runtime value in lamports.
pub async fn get_stake_minimum_delegation(
&self,
role: &crate::HttpRoleName,
config: std::option::Option<&crate::SolanaContextConfig>,
) -> ksp_core_lib::Result<crate::SolanaRpcResponse<u64>> {
let mut params = std::vec::Vec::new();
push_economics_context_config(&mut params, config);
let value = self.execute_economics_rpc("getStakeMinimumDelegation", role, params).await;
let value = match value {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return decode_economics_u64_response("getStakeMinimumDelegation", value);
}
/// Executes typed `getSupply`, preserving the explicit account-list exclusion flag and contextual totals.
pub async fn get_supply(
&self,
role: &crate::HttpRoleName,
config: std::option::Option<&crate::SolanaSupplyConfig>,
) -> ksp_core_lib::Result<crate::SolanaRpcResponse<crate::SolanaSupply>> {
let mut params = std::vec::Vec::new();
if let std::option::Option::Some(config) = config
&& !config.is_empty()
{
params.push((*config).to_json_value());
}
let value = self.execute_economics_rpc("getSupply", role, params).await;
let value = match value {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return decode_supply_response("getSupply", value);
}
async fn execute_economics_rpc(
&self,
method_name: &'static str,
role: &crate::HttpRoleName,
params: std::vec::Vec<serde_json::Value>,
) -> ksp_core_lib::Result<serde_json::Value> {
let descriptor = economics_descriptor(method_name);
let descriptor = match descriptor {
std::result::Result::Ok(descriptor) => descriptor,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return self.execute_standard_rpc(role, descriptor, params).await;
}
}
fn push_economics_commitment_config(params: &mut std::vec::Vec<serde_json::Value>, config: std::option::Option<&crate::SolanaCommitmentConfig>) {
if let std::option::Option::Some(config) = config
&& config.commitment().is_some()
{
params.push((*config).to_json_value());
}
return;
}
fn push_economics_context_config(params: &mut std::vec::Vec<serde_json::Value>, config: std::option::Option<&crate::SolanaContextConfig>) {
if let std::option::Option::Some(config) = config
&& (config.commitment().is_some() || config.min_context_slot().is_some())
{
params.push((*config).to_json_value());
}
return;
}
fn decode_economics_u64_response(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<crate::SolanaRpcResponse<u64>> {
let decoded = crate::decode_wire_json::<WireEconomicsRpcResponse<u64>>(method, value);
let wire = match decoded {
std::result::Result::Ok(wire) => wire,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let context = crate::SolanaRpcContext::decode_wire(method, wire.context);
return match context {
std::result::Result::Ok(context) => std::result::Result::Ok(crate::SolanaRpcResponse::new(context, wire.value)),
std::result::Result::Err(error) => std::result::Result::Err(error),
};
}
fn decode_supply_response(method: &str, value: serde_json::Value) -> ksp_core_lib::Result<crate::SolanaRpcResponse<crate::SolanaSupply>> {
let decoded = crate::decode_wire_json::<WireEconomicsRpcResponse<serde_json::Value>>(method, value);
let wire = match decoded {
std::result::Result::Ok(wire) => wire,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let context = crate::SolanaRpcContext::decode_wire(method, wire.context);
let context = match context {
std::result::Result::Ok(context) => context,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let supply = crate::SolanaSupply::decode_wire(method, wire.value);
return match supply {
std::result::Result::Ok(supply) => std::result::Result::Ok(crate::SolanaRpcResponse::new(context, supply)),
std::result::Result::Err(error) => std::result::Result::Err(error),
};
}
fn economics_descriptor(method: &str) -> ksp_core_lib::Result<&'static crate::HttpRpcMethodDescriptor> {
let descriptor = crate::find_http_rpc_method(method);
return match descriptor {
std::option::Option::Some(descriptor)
if descriptor.category() == crate::HttpRpcCategory::Economics && descriptor.coverage_release() == crate::HttpRpcCoverageRelease::V0_2_4 =>
{
std::result::Result::Ok(descriptor)
},
_ => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_RESPONSE, "typed Economics descriptor is missing from the audited 0.2.4 registry")
.with_context("rpc_method", method),
),
};
}
#[derive(serde::Deserialize)]
struct WireEconomicsRpcResponse<T> {
context: serde_json::Value,
value: T,
}
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireInflationGovernor {
@@ -350,7 +490,6 @@ struct WireInflationGovernor {
foundation_term: f64,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireInflationRate {
@@ -374,7 +513,6 @@ struct WireInflationReward {
commission_bps: crate::SolanaWireField<u16>,
}
#[cfg(test)]
#[derive(serde::Deserialize)]
#[serde(rename_all = "camelCase")]
struct WireSupply {