v0.2.11-pre.007

This commit is contained in:
2026-08-26 10:06:21 +02:00
parent 98093d859b
commit 5aeff5ca14
14 changed files with 1142 additions and 45 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/src/market_price_provider.rs
// version: 3
// version: 4
/// Maximum UTF-8 byte length of one provider display name.
pub const MARKET_PRICE_PROVIDER_DISPLAY_NAME_MAX_BYTES: usize = 96;
@@ -163,6 +163,8 @@ pub enum MarketPriceProviderQuotaPeriod {
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum MarketPriceProviderQuotaUnit {
/// Provider-defined compute units consumed by API operations.
ComputeUnits,
/// Provider-specific credits, not assumed to equal HTTP requests.
Credits,
/// HTTP/API requests.
@@ -205,6 +207,35 @@ impl MarketPriceProviderLongTermQuota {
}
}
/// Informational cost of one normalized SOL/USD request in a provider-defined quota unit.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Serialize)]
pub struct MarketPriceProviderRequestCost {
amount: u64,
unit: crate::MarketPriceProviderQuotaUnit,
}
impl crate::MarketPriceProviderRequestCost {
/// Creates a non-zero informational request-cost descriptor.
pub fn new(amount: u64, unit: crate::MarketPriceProviderQuotaUnit) -> ksp_core_lib::Result<Self> {
if amount == 0 {
return std::result::Result::Err(provider_descriptor_error());
}
return std::result::Result::Ok(Self { amount, unit });
}
/// Returns the documented amount consumed by one SOL/USD request.
#[must_use]
pub const fn amount(&self) -> u64 {
return self.amount;
}
/// Returns the provider-defined quota unit used by this request cost.
#[must_use]
pub const fn unit(&self) -> crate::MarketPriceProviderQuotaUnit {
return self.unit;
}
}
/// Opaque validated provider identifier owned by Off-chain Transport.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
#[serde(try_from = "std::string::String", into = "std::string::String")]
@@ -261,6 +292,7 @@ pub struct MarketPriceProviderDescriptor {
long_term_quota: std::option::Option<crate::MarketPriceProviderLongTermQuota>,
rate_limit: crate::MarketPriceProviderRateLimit,
semantics: crate::MarketPriceSemantics,
sol_usd_request_cost: std::option::Option<crate::MarketPriceProviderRequestCost>,
supports_sol_usd: bool,
}
@@ -281,7 +313,27 @@ impl MarketPriceProviderDescriptor {
ksp_logging_lib::warn!(target: crate::TRACING_TARGET, field = "display_name", "rejected invalid market-price provider descriptor");
return std::result::Result::Err(provider_descriptor_error());
}
return std::result::Result::Ok(Self { auth_mode, display_name, id, long_term_quota, rate_limit, semantics, supports_sol_usd });
return std::result::Result::Ok(Self {
auth_mode,
display_name,
id,
long_term_quota,
rate_limit,
semantics,
sol_usd_request_cost: std::option::Option::None,
supports_sol_usd,
});
}
/// Attaches informational provider cost metadata for one normalized SOL/USD request.
pub fn with_sol_usd_request_cost(mut self, request_cost: crate::MarketPriceProviderRequestCost) -> ksp_core_lib::Result<Self> {
if let std::option::Option::Some(quota) = self.long_term_quota
&& quota.unit() != request_cost.unit()
{
return std::result::Result::Err(provider_descriptor_error());
}
self.sol_usd_request_cost = std::option::Option::Some(request_cost);
return std::result::Result::Ok(self);
}
/// Returns the configured authentication capability.
@@ -320,6 +372,12 @@ impl MarketPriceProviderDescriptor {
return self.semantics;
}
/// Returns optional informational provider cost for one normalized SOL/USD request.
#[must_use]
pub const fn sol_usd_request_cost(&self) -> std::option::Option<crate::MarketPriceProviderRequestCost> {
return self.sol_usd_request_cost;
}
/// Reports whether this descriptor can serve the V1 SOL/USD pair.
#[must_use]
pub const fn supports_sol_usd(&self) -> bool {
@@ -353,6 +411,24 @@ pub enum MarketPriceProviderAvailability {
},
}
impl crate::MarketPriceProviderAvailability {
/// Reports whether a generic refresh may be attempted immediately.
#[must_use]
pub const fn is_refresh_eligible(&self) -> bool {
return matches!(self, Self::Ready);
}
/// Returns the known next retry timestamp for cooling-down or temporary states.
#[must_use]
pub const fn retry_at(&self) -> std::option::Option<crate::MarketPriceTimestamp> {
return match self {
Self::CoolingDown { retry_at } => std::option::Option::Some(*retry_at),
Self::TemporarilyUnavailable { retry_at } => *retry_at,
Self::AuthenticationUnavailable | Self::Disabled | Self::Misconfigured | Self::QuotaUnavailable | Self::Ready => std::option::Option::None,
};
}
}
/// Current provider-neutral runtime state projection.
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub struct MarketPriceProviderState {