v0.2.12-pre.008-fix.002

This commit is contained in:
2026-08-27 15:18:34 +02:00
parent fe46cbe3bd
commit f0493df09e
13 changed files with 248 additions and 38 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-wallet-desk/src/wallet_balance.rs
// version: 3
// version: 4
//! Safe Wallet balance projection produced by the typed HTTP Transport path.
@@ -20,6 +20,8 @@ pub(crate) struct WalletBalanceDto {
pub(crate) sol: String,
/// Arithmetic mean of successful SOL/USD observations produced by this refresh, or unavailable when no provider returned one.
pub(crate) sol_usd_average: std::option::Option<String>,
/// Exact USD equivalent of the current SOL balance using `sol_usd_average`, or unavailable when the auxiliary price is unavailable.
pub(crate) sol_usd_equivalent: std::option::Option<String>,
/// Composite-selected Transport profile used for the RPC.
pub(crate) transport_profile: String,
/// Logical Transport role used for the RPC.
@@ -111,6 +113,58 @@ pub(crate) fn average_sol_usd_prices(prices: &[ksp_offchain_transport_lib::Marke
return std::option::Option::Some(format_scaled_decimal(coefficient, target_scale));
}
/// Computes the exact USD equivalent of a lamport balance from the current SOL/USD average.
///
/// The output is rounded half-up to at most eight fractional digits. Missing or invalid auxiliary price data and arithmetic overflow degrade to `None`; the
/// authoritative SOL balance remains unaffected.
#[must_use]
pub(crate) fn sol_usd_equivalent(lamports: u64, sol_usd_average: std::option::Option<&str>) -> std::option::Option<String> {
const LAMPORT_SCALE: u8 = 9;
const OUTPUT_SCALE: u8 = 8;
let source = match sol_usd_average {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
let average = match ksp_offchain_transport_lib::MarketPriceDecimal::parse(source) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return std::option::Option::None,
};
let coefficient = match u128::from(lamports).checked_mul(average.coefficient()) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
let source_scale = u16::from(LAMPORT_SCALE) + u16::from(average.scale());
let target_scale = u16::from(OUTPUT_SCALE);
let rounded_coefficient = if source_scale <= target_scale {
let exponent = u32::from(target_scale - source_scale);
let factor = match 10_u128.checked_pow(exponent) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
match coefficient.checked_mul(factor) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
}
} else {
let exponent = u32::from(source_scale - target_scale);
let divisor = match 10_u128.checked_pow(exponent) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
};
let quotient = coefficient / divisor;
let remainder = coefficient % divisor;
if remainder >= divisor.div_ceil(2) {
match quotient.checked_add(1) {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::option::Option::None,
}
} else {
quotient
}
};
return std::option::Option::Some(format_scaled_decimal(rounded_coefficient, OUTPUT_SCALE));
}
fn format_scaled_decimal(mut coefficient: u128, mut scale: u8) -> String {
while scale > 0 && coefficient.is_multiple_of(10) {
coefficient /= 10;