v0.2.11-pre.002-fix.003
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
// file: crates/ksp-offchain-transport-lib/src/market_price_observation.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
/// Maximum UTF-8 byte length accepted for safe provider provenance.
|
||||
pub const PRICE_PROVENANCE_MAX_BYTES: usize = 256;
|
||||
pub const MARKET_PRICE_PROVENANCE_MAX_BYTES: usize = 256;
|
||||
|
||||
/// Millisecond UTC timestamp used by provider-neutral public projections.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
|
||||
pub struct PriceTimestamp {
|
||||
pub struct MarketPriceTimestamp {
|
||||
unix_millis: u64,
|
||||
}
|
||||
|
||||
impl PriceTimestamp {
|
||||
impl MarketPriceTimestamp {
|
||||
/// Creates a UTC timestamp from whole milliseconds since Unix epoch.
|
||||
#[must_use]
|
||||
pub const fn from_unix_millis(unix_millis: u64) -> Self {
|
||||
@@ -27,9 +27,9 @@ impl PriceTimestamp {
|
||||
/// Safe bounded provenance supplied by one provider adapter.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(try_from = "std::string::String", into = "std::string::String")]
|
||||
pub struct PriceProvenance(std::string::String);
|
||||
pub struct MarketPriceProvenance(std::string::String);
|
||||
|
||||
impl PriceProvenance {
|
||||
impl MarketPriceProvenance {
|
||||
/// Creates bounded non-empty provenance without accepting control characters.
|
||||
pub fn new(value: impl std::convert::Into<std::string::String>) -> ksp_core_lib::Result<Self> {
|
||||
let value = value.into();
|
||||
@@ -46,49 +46,49 @@ impl PriceProvenance {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::TryFrom<std::string::String> for PriceProvenance {
|
||||
impl std::convert::TryFrom<std::string::String> for MarketPriceProvenance {
|
||||
type Error = ksp_core_lib::Error;
|
||||
|
||||
fn try_from(value: std::string::String) -> std::result::Result<Self, Self::Error> {
|
||||
return crate::PriceProvenance::new(value);
|
||||
return crate::MarketPriceProvenance::new(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<PriceProvenance> for std::string::String {
|
||||
fn from(value: PriceProvenance) -> Self {
|
||||
impl std::convert::From<MarketPriceProvenance> for std::string::String {
|
||||
fn from(value: MarketPriceProvenance) -> Self {
|
||||
return value.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Public V1 SOL/USD observation normalized by Off-chain Transport.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
pub struct SolUsdPriceObservation {
|
||||
pair: crate::PricePair,
|
||||
price: crate::PriceDecimal,
|
||||
provider_id: crate::PriceProviderId,
|
||||
provider_timestamp: std::option::Option<crate::PriceTimestamp>,
|
||||
provenance: crate::PriceProvenance,
|
||||
received_at: crate::PriceTimestamp,
|
||||
request_started_at: crate::PriceTimestamp,
|
||||
semantics: crate::PriceSemantics,
|
||||
pub struct MarketPriceObservation {
|
||||
pair: crate::MarketPricePair,
|
||||
price: crate::MarketPriceDecimal,
|
||||
provider_id: crate::MarketPriceProviderId,
|
||||
provider_timestamp: std::option::Option<crate::MarketPriceTimestamp>,
|
||||
provenance: crate::MarketPriceProvenance,
|
||||
received_at: crate::MarketPriceTimestamp,
|
||||
request_started_at: crate::MarketPriceTimestamp,
|
||||
semantics: crate::MarketPriceSemantics,
|
||||
}
|
||||
|
||||
impl SolUsdPriceObservation {
|
||||
impl MarketPriceObservation {
|
||||
/// Creates one successful normalized SOL/USD observation.
|
||||
pub fn new(
|
||||
provider_id: crate::PriceProviderId,
|
||||
price: crate::PriceDecimal,
|
||||
semantics: crate::PriceSemantics,
|
||||
request_started_at: crate::PriceTimestamp,
|
||||
received_at: crate::PriceTimestamp,
|
||||
provider_timestamp: std::option::Option<crate::PriceTimestamp>,
|
||||
provenance: crate::PriceProvenance,
|
||||
provider_id: crate::MarketPriceProviderId,
|
||||
price: crate::MarketPriceDecimal,
|
||||
semantics: crate::MarketPriceSemantics,
|
||||
request_started_at: crate::MarketPriceTimestamp,
|
||||
received_at: crate::MarketPriceTimestamp,
|
||||
provider_timestamp: std::option::Option<crate::MarketPriceTimestamp>,
|
||||
provenance: crate::MarketPriceProvenance,
|
||||
) -> ksp_core_lib::Result<Self> {
|
||||
if received_at < request_started_at {
|
||||
return std::result::Result::Err(observation_error());
|
||||
}
|
||||
return std::result::Result::Ok(Self {
|
||||
pair: crate::PricePair::SolUsd,
|
||||
pair: crate::MarketPricePair::SolUsd,
|
||||
price,
|
||||
provider_id,
|
||||
provider_timestamp,
|
||||
@@ -101,59 +101,59 @@ impl SolUsdPriceObservation {
|
||||
|
||||
/// Returns the only V1 pair represented by this observation.
|
||||
#[must_use]
|
||||
pub const fn pair(&self) -> crate::PricePair {
|
||||
pub const fn pair(&self) -> crate::MarketPricePair {
|
||||
return self.pair;
|
||||
}
|
||||
|
||||
/// Returns the exact positive SOL/USD price.
|
||||
#[must_use]
|
||||
pub const fn price(&self) -> crate::PriceDecimal {
|
||||
pub const fn price(&self) -> crate::MarketPriceDecimal {
|
||||
return self.price;
|
||||
}
|
||||
|
||||
/// Returns the opaque provider identifier.
|
||||
#[must_use]
|
||||
pub const fn provider_id(&self) -> &crate::PriceProviderId {
|
||||
pub const fn provider_id(&self) -> &crate::MarketPriceProviderId {
|
||||
return &self.provider_id;
|
||||
}
|
||||
|
||||
/// Returns a provider timestamp only when the provider adapter has a real price-time field.
|
||||
#[must_use]
|
||||
pub const fn provider_timestamp(&self) -> std::option::Option<crate::PriceTimestamp> {
|
||||
pub const fn provider_timestamp(&self) -> std::option::Option<crate::MarketPriceTimestamp> {
|
||||
return self.provider_timestamp;
|
||||
}
|
||||
|
||||
/// Returns safe provider provenance.
|
||||
#[must_use]
|
||||
pub const fn provenance(&self) -> &crate::PriceProvenance {
|
||||
pub const fn provenance(&self) -> &crate::MarketPriceProvenance {
|
||||
return &self.provenance;
|
||||
}
|
||||
|
||||
/// Returns the KSP wall-clock receipt timestamp.
|
||||
#[must_use]
|
||||
pub const fn received_at(&self) -> crate::PriceTimestamp {
|
||||
pub const fn received_at(&self) -> crate::MarketPriceTimestamp {
|
||||
return self.received_at;
|
||||
}
|
||||
|
||||
/// Returns the KSP wall-clock request-start timestamp.
|
||||
#[must_use]
|
||||
pub const fn request_started_at(&self) -> crate::PriceTimestamp {
|
||||
pub const fn request_started_at(&self) -> crate::MarketPriceTimestamp {
|
||||
return self.request_started_at;
|
||||
}
|
||||
|
||||
/// Returns the provider-specific semantic class retained by the normalized observation.
|
||||
#[must_use]
|
||||
pub const fn semantics(&self) -> crate::PriceSemantics {
|
||||
pub const fn semantics(&self) -> crate::MarketPriceSemantics {
|
||||
return self.semantics;
|
||||
}
|
||||
}
|
||||
|
||||
fn observation_error() -> ksp_core_lib::Error {
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_PROVIDER_OBSERVATION_INVALID, "invalid off-chain price observation");
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_MARKET_PRICE_OBSERVATION_INVALID, "invalid off-chain market-price observation");
|
||||
}
|
||||
|
||||
fn valid_provenance(value: &str) -> bool {
|
||||
if value.is_empty() || value.len() > crate::PRICE_PROVENANCE_MAX_BYTES || value.trim() != value {
|
||||
if value.is_empty() || value.len() > crate::MARKET_PRICE_PROVENANCE_MAX_BYTES || value.trim() != value {
|
||||
return false;
|
||||
}
|
||||
for character in value.chars() {
|
||||
|
||||
Reference in New Issue
Block a user