v0.2.11-pre.002-fix.001

This commit is contained in:
2026-08-25 20:17:31 +02:00
parent 4f92fb03f1
commit 3fd540a9db
18 changed files with 358 additions and 67 deletions

View File

@@ -1,5 +1,5 @@
# file: crates/ksp-offchain-transport-lib/Cargo.toml
# version: 1
# version: 2
[package]
name = "ksp-offchain-transport-lib"
@@ -9,6 +9,7 @@ repository.workspace = true
[dependencies]
ksp-core-lib = { path = "../ksp-core-lib" }
ksp-logging-lib = { path = "../ksp-logging-lib" }
serde = { workspace = true, features = ["derive"] }
[dev-dependencies]

View File

@@ -0,0 +1,7 @@
// file: crates/ksp-offchain-transport-lib/src/constants.rs
// version: 1
//! Off-chain Transport-owned tracing constants.
/// Owning tracing target for events emitted by the off-chain transport crate.
pub(crate) const TRACING_TARGET: &str = "ksp-offchain-transport-lib";

View File

@@ -1,13 +1,13 @@
// file: crates/ksp-offchain-transport-lib/src/error.rs
// version: 1
// version: 2
/// Stable off-chain transport error for an invalid exact decimal price.
pub const ERROR_CODE_PRICE_DECIMAL_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("offchain_transport", "price_decimal_invalid");
/// Stable off-chain transport error for an invalid provider descriptor.
/// Stable off-chain transport error for an invalid market-price provider descriptor.
pub const ERROR_CODE_PROVIDER_DESCRIPTOR_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("offchain_transport", "provider_descriptor_invalid");
/// Stable off-chain transport error for an invalid provider identifier.
/// Stable off-chain transport error for an invalid market-price provider identifier.
pub const ERROR_CODE_PROVIDER_ID_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("offchain_transport", "provider_id_invalid");
/// Stable off-chain transport error for an invalid normalized observation.
/// Stable off-chain transport error for an invalid normalized market-price observation.
pub const ERROR_CODE_PROVIDER_OBSERVATION_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("offchain_transport", "provider_observation_invalid");
/// Stable off-chain transport error for invalid common provider settings.
/// Stable off-chain transport error for invalid common market-price provider settings.
pub const ERROR_CODE_PROVIDER_SETTINGS_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("offchain_transport", "provider_settings_invalid");

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/src/lib.rs
// version: 1
// version: 2
#![warn(missing_docs)]
#![deny(unreachable_pub)]
@@ -7,22 +7,19 @@
//! KSP-owned off-chain transport foundation.
//!
//! `0.2.11-pre.002` opens the first deliberately narrow public surface: exact SOL/USD price values, provider-neutral observations, provider descriptors,
//! common provider settings and generic availability/rate-limit metadata. No provider wire type, HTTP client, provider SDK, Config dependency or active
//! `0.2.11-pre.002` opens the first deliberately narrow capability family: `market_price`, currently limited to exact SOL/USD values, provider-neutral
//! observations, provider descriptors, common provider settings and generic availability/rate-limit metadata. The crate itself is deliberately broader than
//! market prices: future off-chain capabilities such as amount-specific swap quotes belong to separate capability families instead of extending the
//! `market_price_*` modules. Shared transport/runtime concerns stay crate-wide. No provider wire type, HTTP client, provider SDK, Config dependency or active
//! rate limiter is introduced by this tranche.
mod decimal;
mod constants;
mod error;
mod observation;
mod provider;
mod settings;
mod market_price_decimal;
mod market_price_observation;
mod market_price_provider;
mod market_price_settings;
/// Maximum accepted byte length for one textual decimal input.
pub use self::decimal::PRICE_DECIMAL_MAX_INPUT_BYTES;
/// Maximum decimal scale retained by the canonical SOL/USD price representation.
pub use self::decimal::PRICE_DECIMAL_MAX_SCALE;
/// Exact positive decimal value used by the public off-chain price contract.
pub use self::decimal::PriceDecimal;
/// Stable error code for an invalid exact decimal price.
pub use self::error::ERROR_CODE_PRICE_DECIMAL_INVALID;
/// Stable error code for an invalid provider descriptor.
@@ -33,43 +30,52 @@ pub use self::error::ERROR_CODE_PROVIDER_ID_INVALID;
pub use self::error::ERROR_CODE_PROVIDER_OBSERVATION_INVALID;
/// Stable error code for invalid common provider settings.
pub use self::error::ERROR_CODE_PROVIDER_SETTINGS_INVALID;
/// Maximum accepted byte length for one textual decimal input.
pub use self::market_price_decimal::PRICE_DECIMAL_MAX_INPUT_BYTES;
/// Maximum decimal scale retained by the canonical SOL/USD price representation.
pub use self::market_price_decimal::PRICE_DECIMAL_MAX_SCALE;
/// Exact positive decimal value used by the public off-chain price contract.
pub use self::market_price_decimal::PriceDecimal;
/// Maximum safe provenance length attached to one normalized observation.
pub use self::observation::PRICE_PROVENANCE_MAX_BYTES;
pub use self::market_price_observation::PRICE_PROVENANCE_MAX_BYTES;
/// Safe bounded provenance supplied by one provider adapter.
pub use self::observation::PriceProvenance;
pub use self::market_price_observation::PriceProvenance;
/// Millisecond UTC timestamp used for request, receipt, provider and cooldown projections.
pub use self::observation::PriceTimestamp;
pub use self::market_price_observation::PriceTimestamp;
/// Public V1 SOL/USD observation normalized by Off-chain Transport.
pub use self::observation::SolUsdPriceObservation;
pub use self::market_price_observation::SolUsdPriceObservation;
/// Maximum provider display-name length accepted by descriptors.
pub use self::provider::PRICE_PROVIDER_DISPLAY_NAME_MAX_BYTES;
pub use self::market_price_provider::PRICE_PROVIDER_DISPLAY_NAME_MAX_BYTES;
/// Maximum opaque provider identifier length accepted by the public contract.
pub use self::provider::PRICE_PROVIDER_ID_MAX_BYTES;
pub use self::market_price_provider::PRICE_PROVIDER_ID_MAX_BYTES;
/// Only price pair exposed by the `0.2.11` V1 public contract.
pub use self::provider::PricePair;
pub use self::market_price_provider::PricePair;
/// Generic authentication capability exposed by a configured provider descriptor.
pub use self::provider::PriceProviderAuthMode;
pub use self::market_price_provider::PriceProviderAuthMode;
/// Generic runtime availability state exposed without provider-specific error parsing.
pub use self::provider::PriceProviderAvailability;
pub use self::market_price_provider::PriceProviderAvailability;
/// Provider capability and presentation descriptor consumed by provider-agnostic callers.
pub use self::provider::PriceProviderDescriptor;
pub use self::market_price_provider::PriceProviderDescriptor;
/// Opaque validated provider identifier owned by Off-chain Transport.
pub use self::provider::PriceProviderId;
pub use self::market_price_provider::PriceProviderId;
/// Long-term provider quota descriptor that is informational rather than an authoritative local counter.
pub use self::provider::PriceProviderLongTermQuota;
pub use self::market_price_provider::PriceProviderLongTermQuota;
/// Period used by a documented long-term provider quota.
pub use self::provider::PriceProviderQuotaPeriod;
pub use self::market_price_provider::PriceProviderQuotaPeriod;
/// Unit used by a documented long-term provider quota.
pub use self::provider::PriceProviderQuotaUnit;
pub use self::market_price_provider::PriceProviderQuotaUnit;
/// Generic provider request-limit capability.
pub use self::provider::PriceProviderRateLimit;
pub use self::market_price_provider::PriceProviderRateLimit;
/// Shape of one generic provider request-limit capability.
pub use self::provider::PriceProviderRateLimitKind;
pub use self::market_price_provider::PriceProviderRateLimitKind;
/// Scope to which a provider documents one request limit.
pub use self::provider::PriceProviderRateLimitScope;
pub use self::market_price_provider::PriceProviderRateLimitScope;
/// Current provider-neutral runtime state projection.
pub use self::provider::PriceProviderState;
pub use self::market_price_provider::PriceProviderState;
/// Price semantics retained so consumers never assume all providers report equivalent market values.
pub use self::provider::PriceSemantics;
pub use self::market_price_provider::PriceSemantics;
/// Common provider settings shared by provider-specific runtime settings.
pub use self::settings::PriceProviderCommonSettings;
pub use self::market_price_settings::PriceProviderCommonSettings;
/// Owning tracing target for events emitted by Off-chain Transport.
pub(crate) use self::constants::TRACING_TARGET;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/src/decimal.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/src/market_price_decimal.rs
// version: 2
/// Maximum accepted UTF-8 byte length for one textual decimal input.
pub const PRICE_DECIMAL_MAX_INPUT_BYTES: usize = 96;
@@ -221,5 +221,5 @@ fn split_exponent(source: &str) -> std::result::Result<(&str, i32), ()> {
}
#[cfg(test)]
#[path = "../unit_tests/decimal.rs"]
#[path = "../unit_tests/market_price_decimal.rs"]
mod tests;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/src/observation.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/src/market_price_observation.rs
// version: 2
/// Maximum UTF-8 byte length accepted for safe provider provenance.
pub const PRICE_PROVENANCE_MAX_BYTES: usize = 256;
@@ -165,5 +165,5 @@ fn valid_provenance(value: &str) -> bool {
}
#[cfg(test)]
#[path = "../unit_tests/observation.rs"]
#[path = "../unit_tests/market_price_observation.rs"]
mod tests;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/src/provider.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/src/market_price_provider.rs
// version: 2
/// Maximum UTF-8 byte length of one provider display name.
pub const PRICE_PROVIDER_DISPLAY_NAME_MAX_BYTES: usize = 96;
@@ -208,9 +208,14 @@ pub struct PriceProviderId(std::string::String);
impl PriceProviderId {
/// Creates one bounded stable provider identifier.
pub fn new(value: impl std::convert::Into<std::string::String>) -> ksp_core_lib::Result<Self> {
ksp_logging_lib::trace!(target: crate::TRACING_TARGET, "validating market-price provider identifier");
let value = value.into();
if !valid_provider_id(value.as_str()) {
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_PROVIDER_ID_INVALID, "invalid off-chain provider identifier"));
ksp_logging_lib::warn!(target: crate::TRACING_TARGET, field = "provider_id", "rejected invalid market-price provider identifier");
return std::result::Result::Err(ksp_core_lib::Error::new(
crate::ERROR_CODE_PROVIDER_ID_INVALID,
"invalid off-chain market-price provider identifier",
));
}
return std::result::Result::Ok(Self(value));
}
@@ -265,8 +270,10 @@ impl PriceProviderDescriptor {
long_term_quota: std::option::Option<crate::PriceProviderLongTermQuota>,
supports_sol_usd: bool,
) -> ksp_core_lib::Result<Self> {
ksp_logging_lib::trace!(target: crate::TRACING_TARGET, "validating market-price provider descriptor");
let display_name = display_name.into();
if !valid_display_name(display_name.as_str()) {
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 });
@@ -369,7 +376,7 @@ impl PriceProviderState {
}
fn provider_descriptor_error() -> ksp_core_lib::Error {
return ksp_core_lib::Error::new(crate::ERROR_CODE_PROVIDER_DESCRIPTOR_INVALID, "invalid off-chain provider descriptor");
return ksp_core_lib::Error::new(crate::ERROR_CODE_PROVIDER_DESCRIPTOR_INVALID, "invalid off-chain market-price provider descriptor");
}
fn valid_display_name(value: &str) -> bool {
@@ -397,5 +404,5 @@ fn valid_provider_id(value: &str) -> bool {
}
#[cfg(test)]
#[path = "../unit_tests/provider.rs"]
#[path = "../unit_tests/market_price_provider.rs"]
mod tests;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/src/settings.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/src/market_price_settings.rs
// version: 2
/// Common provider settings embedded by future provider-specific runtime settings.
///
@@ -15,6 +15,7 @@ impl PriceProviderCommonSettings {
/// Creates common settings for one uniquely identified runtime provider instance.
#[must_use]
pub fn new(provider_id: crate::PriceProviderId, enabled: bool) -> Self {
ksp_logging_lib::trace!(target: crate::TRACING_TARGET, enabled = enabled, "constructed common market-price provider settings");
return Self { enabled, provider_id };
}
@@ -32,5 +33,5 @@ impl PriceProviderCommonSettings {
}
#[cfg(test)]
#[path = "../unit_tests/settings.rs"]
#[path = "../unit_tests/market_price_settings.rs"]
mod tests;

View File

@@ -1,14 +1,17 @@
// file: crates/ksp-offchain-transport-lib/tests/dependency_boundary.rs
// version: 1
// version: 2
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
//! Dependency, observability and module-taxonomy canaries for the Off-chain Transport foundation.
#[test]
fn pre_002_manifest_keeps_foundation_provider_and_config_independent() {
let manifest = include_str!("../Cargo.toml");
assert!(manifest.contains("ksp-core-lib"));
assert!(manifest.contains("ksp-logging-lib"));
assert!(manifest.contains("serde"));
assert!(!manifest.contains("ksp-config-lib"));
assert!(!manifest.contains("reqwest"));
@@ -17,4 +20,17 @@ fn pre_002_manifest_keeps_foundation_provider_and_config_independent() {
assert!(!manifest.contains("jupiter"));
assert!(!manifest.contains("birdeye"));
assert!(!manifest.contains("dexscreener"));
assert!(!manifest.lines().any(|line| line.trim_start().starts_with("tracing =")));
let crate_root = include_str!("../src/lib.rs");
assert!(crate_root.contains("mod constants;"));
assert!(crate_root.contains("mod market_price_decimal;"));
assert!(crate_root.contains("mod market_price_observation;"));
assert!(crate_root.contains("mod market_price_provider;"));
assert!(crate_root.contains("mod market_price_settings;"));
assert!(!crate_root.contains("mod decimal;"));
assert!(!crate_root.contains("mod observation;"));
assert!(!crate_root.contains("mod provider;"));
assert!(!crate_root.contains("mod settings;"));
let constants = include_str!("../src/constants.rs");
assert!(constants.contains("pub(crate) const TRACING_TARGET: &str = \"ksp-offchain-transport-lib\";"));
}

View File

@@ -1,10 +1,12 @@
// file: crates/ksp-offchain-transport-lib/tests/public_api.rs
// version: 1
// version: 2
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
//! Public API canaries for the first Off-chain Transport market-price capability family.
#[test]
fn public_pre_002_price_foundation_is_available_from_crate_root() -> ksp_core_lib::Result<()> {
assert_eq!(ksp_offchain_transport_lib::PricePair::SolUsd.code(), "SOL/USD");

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/unit_tests/decimal.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/unit_tests/market_price_decimal.rs
// version: 2
#[test]
fn decimal_normalizes_fractional_and_scientific_forms_without_f64() -> ksp_core_lib::Result<()> {

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/unit_tests/observation.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/unit_tests/market_price_observation.rs
// version: 2
#[test]
fn observation_preserves_pair_exact_price_semantics_timestamps_and_safe_provenance() -> ksp_core_lib::Result<()> {

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/unit_tests/provider.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/unit_tests/market_price_provider.rs
// version: 2
#[test]
fn provider_id_is_opaque_bounded_and_stable() -> ksp_core_lib::Result<()> {

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-offchain-transport-lib/unit_tests/settings.rs
// version: 1
// file: crates/ksp-offchain-transport-lib/unit_tests/market_price_settings.rs
// version: 2
#[test]
fn common_settings_contain_only_generic_identity_and_enablement() -> ksp_core_lib::Result<()> {