From b5a129395337ed42e0075d400323fe4b495eb287 Mon Sep 17 00:00:00 2001 From: SinuS Von SifriduS Date: Wed, 26 Aug 2026 14:56:44 +0200 Subject: [PATCH] v0.2.11-pre.011-fix.001 --- Cargo.toml | 4 +- .../src/market_price_coinmarketcap.rs | 4 +- .../unit_tests/market_price_coinmarketcap.rs | 4 +- deltas/0.2.11/pre.011-fix.001.md | 86 +++++++++++++++++++ ...8-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md | 10 ++- .../014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md | 45 +++++++--- 6 files changed, 132 insertions(+), 21 deletions(-) create mode 100644 deltas/0.2.11/pre.011-fix.001.md diff --git a/Cargo.toml b/Cargo.toml index 3e7b520..6564d2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 282 +# version: 283 [workspace] resolver = "3" members = ["crates/ksp-app-config-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.2.11-pre.11" +version = "0.2.11-pre.11.fix.1" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-offchain-transport-lib/src/market_price_coinmarketcap.rs b/crates/ksp-offchain-transport-lib/src/market_price_coinmarketcap.rs index 7d44ccc..5034937 100644 --- a/crates/ksp-offchain-transport-lib/src/market_price_coinmarketcap.rs +++ b/crates/ksp-offchain-transport-lib/src/market_price_coinmarketcap.rs @@ -1,5 +1,5 @@ // file: crates/ksp-offchain-transport-lib/src/market_price_coinmarketcap.rs -// version: 3 +// version: 4 //! CoinMarketCap SOL/USD market-price adapter using the current Simple Price V2 REST surface. @@ -166,7 +166,7 @@ fn build_request(settings: &crate::MarketPriceCoinMarketCapSettings) -> ksp_core std::result::Result::Ok(value) => value, std::result::Result::Err(error) => return std::result::Result::Err(error), }; - request.append_query_pair("ids", "5426"); + request.append_query_pair("id", "5426"); request.append_query_pair("convert", "USD"); request.append_query_pair("include_last_updated", "true"); if let std::option::Option::Some(api_key) = settings.api_key() diff --git a/crates/ksp-offchain-transport-lib/unit_tests/market_price_coinmarketcap.rs b/crates/ksp-offchain-transport-lib/unit_tests/market_price_coinmarketcap.rs index d52b74b..a75b22e 100644 --- a/crates/ksp-offchain-transport-lib/unit_tests/market_price_coinmarketcap.rs +++ b/crates/ksp-offchain-transport-lib/unit_tests/market_price_coinmarketcap.rs @@ -1,5 +1,5 @@ // file: crates/ksp-offchain-transport-lib/unit_tests/market_price_coinmarketcap.rs -// version: 2 +// version: 3 #[test] fn coinmarketcap_modes_use_v2_and_map_exact_free_capabilities() -> ksp_core_lib::Result<()> { @@ -12,6 +12,7 @@ fn coinmarketcap_modes_use_v2_and_map_exact_free_capabilities() -> ksp_core_lib: std::result::Result::Err(error) => return std::result::Result::Err(error), }; assert_eq!(request.url_for_test().path(), "/public-api/v2/simple/price"); + assert_eq!(request.url_for_test().query(), std::option::Option::Some("id=5426&convert=USD&include_last_updated=true")); assert!(!request.has_header_for_test(super::COINMARKETCAP_API_KEY_HEADER)); let keyless_provider = match crate::MarketPriceCoinMarketCapProvider::new(keyless) { std::result::Result::Ok(value) => value, @@ -28,6 +29,7 @@ fn coinmarketcap_modes_use_v2_and_map_exact_free_capabilities() -> ksp_core_lib: std::result::Result::Err(error) => return std::result::Result::Err(error), }; assert_eq!(request.url_for_test().path(), "/v2/simple/price"); + assert_eq!(request.url_for_test().query(), std::option::Option::Some("id=5426&convert=USD&include_last_updated=true")); assert!(request.has_header_for_test(super::COINMARKETCAP_API_KEY_HEADER)); let basic_provider = match crate::MarketPriceCoinMarketCapProvider::new(basic) { std::result::Result::Ok(value) => value, diff --git a/deltas/0.2.11/pre.011-fix.001.md b/deltas/0.2.11/pre.011-fix.001.md new file mode 100644 index 0000000..352a3f9 --- /dev/null +++ b/deltas/0.2.11/pre.011-fix.001.md @@ -0,0 +1,86 @@ + + + +# Delta `0.2.11-pre.011-fix.001` — CoinMarketCap Simple Price V2 `id` + +## 1. Déclencheur + +Le gate déterministe de `0.2.11-pre.011` est PASS : audits Rust/Markdown, `cargo check`, Clippy, tests ciblés, `cargo test --workspace` et `cargo tree` Off-chain Transport. Le smoke live keyless a ensuite tenté les sept providers et a échoué uniquement sur CoinMarketCap : + +```text +live market-price providers did not all refresh successfully after every provider was attempted: +["coinmarketcap:TemporarilyUnavailable { retry_at: None }"] +``` + +Les six autres providers keyless ont donc produit une observation valide pendant le même batch. + +## 2. Diagnostic officiel actuel + +Le réaudit CoinMarketCap du `2026-08-26` confirme : + +```text +GET /v2/simple/price +keyless = /public-api/v2/simple/price +identifiant CoinMarketCap = query parameter `id` +SOL = id 5426 +include_last_updated = true supporté +``` + +L'adapter KSP utilisait encore : + +```text +ids=5426 +``` + +Cette query n'est pas le contrat V2 officiel courant. + +## 3. Correctif + +`market_price_coinmarketcap.rs` remplace uniquement : + +```text +ids=5426 -> id=5426 +``` + +Le builder est commun aux modes `Keyless` et `Basic`, donc les deux sont corrigés simultanément. Les endpoints, headers, parser, rate-limit, quota, provenance et sémantique `AggregatedMarket` restent inchangés. + +Le test unitaire existant verrouille désormais la query exacte pour les deux modes : + +```text +id=5426&convert=USD&include_last_updated=true +``` + +## 4. Version + +```text +workspace.package.version = 0.2.11-pre.11.fix.1 +commit attendu = v0.2.11-pre.011-fix.001 +aucun tag prerelease +``` + +## 5. Gate requis + +Après application : + +```bash +cargo fmt --all +python3 scripts/audit_rust_workspace_rules.py +python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.11 +cargo check --workspace +cargo clippy --workspace --all-targets +cargo test -p ksp-offchain-transport-lib +cargo test -p ksp-config-lib +cargo test --workspace +cargo tree -p ksp-offchain-transport-lib --edges normal +``` + +Puis le re-smoke keyless obligatoire : + +```bash +cargo test -p ksp-offchain-transport-lib \ + --test market_price_live_smoke \ + keyless_market_price_providers_live_smoke \ + -- --ignored --exact --nocapture --test-threads=1 +``` + +Le smoke keyed reste opt-in et peut être consigné `SKIP opérateur` si les quatre credentials gratuits ne sont pas disponibles. diff --git a/docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md b/docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md index 465f04a..48e8282 100644 --- a/docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md +++ b/docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md @@ -1,9 +1,9 @@ - + # Plan `0.2.11` — Off-chain price transport SOL/USD multi-provider -**Statut courant : `0.2.11-pre.011` matérialise le gate technique/live final. Le gate complet de `pre.010-fix.001` est PASS. Les contrats officiels des huit providers sont réaudités au `2026-08-26`, un smoke keyless de sept providers et un smoke keyed de quatre modes gratuits sont désormais durables et opt-in ; leur exécution opérateur reste requise avant la réconciliation documentaire finale de `pre.012`.** +**Statut courant : `0.2.11-pre.011-fix.001` corrige le contrat de requête CoinMarketCap Simple Price V2 après le premier smoke live. Le gate déterministe de `pre.011` est PASS et six providers keyless sur sept ont répondu correctement ; CoinMarketCap a échoué parce que KSP envoyait encore `ids=5426` alors que la surface V2 officielle exige `id=5426`. Le re-smoke keyless opérateur reste requis avant `pre.012`.** ## 1. Base et autorité @@ -809,6 +809,12 @@ Durcissement de la façade publique avec `#[non_exhaustive]` sur les enums évol Nouvel audit final des huit contrats provider, ajout de `tests/market_price_live_smoke.rs`, smoke keyless de sept providers, smoke keyed des quatre modes gratuits avec secrets sur `stdin`, vérification des graphes Cargo et reprise du gate workspace complet. Aucun endpoint, parser, rate-limit, Config ou comportement de refresh n'est modifié par cette tranche. +#### `pre.011-fix.001` — Paramètre CoinMarketCap Simple Price V2 + +**Statut : implémenté ; re-smoke keyless opérateur requis.** + +Le premier smoke live keyless de `pre.011` a tenté les sept providers et n'a remonté qu'un échec CoinMarketCap. Le réaudit officiel ciblé a confirmé que `GET /v2/simple/price` et son équivalent keyless `/public-api/v2/simple/price` utilisent le paramètre `id`, singulier. L'adapter KSP envoyait encore `ids`, hérité d'une forme préparatoire erronée. Le correctif remplace uniquement `ids=5426` par `id=5426` pour les modes Keyless et Basic et ajoute un canari exact sur la query string. Aucun endpoint, parser, rate-limit, credential, sémantique ou contrat générique de refresh n'est modifié. + ### `pre.012` — Réconciliation documentaire finale **Statut : planifié.** diff --git a/docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md b/docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md index 2626351..1eb17ea 100644 --- a/docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md +++ b/docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md @@ -1,5 +1,5 @@ - + # Validation `0.2.11` — Off-chain price transport SOL/USD @@ -354,25 +354,42 @@ La tranche n'ajoute aucune URL provider configurable, aucun SDK provider et aucu | aucun prix exact live figé | PASS | validation identité/pair/sémantique/prix positif uniquement | | audit Rust sandbox | PASS | clean, 0 candidate export | | audit Markdown sandbox | PASS | clean, 125 tables / 120 fichiers | -| gate Cargo déterministe complet | PENDING | opérateur | -| `cargo tree` Off-chain | PENDING | opérateur, aucun SDK provider / aucune dépendance Config | -| smoke keyless réel | PENDING | obligatoire avant `pre.012` | +| gate Cargo déterministe complet | PASS | opérateur, workspace complet | +| `cargo tree` Off-chain | PASS | opérateur, aucun SDK provider / aucune dépendance Config | +| smoke keyless réel | FAIL | 6/7 PASS, CoinMarketCap seul échec avant fix | | smoke keyed réel | PENDING | exécuter si les quatre credentials gratuits sont disponibles | La tranche `pre.011` ne change aucune logique réseau de production. Elle rend uniquement le gate live durable et réaudite les contrats externes avant stable. Le smoke keyless est le gate live sans credential obligatoire. Le smoke keyed peut être `SKIP opérateur` si les quatre clés ne sont pas disponibles ; ce statut doit être consigné explicitement dans la validation finale et ne doit jamais être transformé en PASS fictif. +## 3.15 Correctif `0.2.11-pre.011-fix.001` + +Le smoke keyless opérateur de `pre.011` a bien exécuté les sept providers avant assertion finale. Les six adapters Coinbase Exchange, CoinGecko, CoinPaprika, DexScreener, Jupiter et Kraken ont produit une observation valide. CoinMarketCap seul a terminé `TemporarilyUnavailable`. Le réaudit officiel ciblé a identifié un écart déterministe dans le builder KSP : Simple Price V2 attend `id=5426`, alors que l'adapter envoyait `ids=5426`. + +| Critère | Statut | Preuve / condition opérateur | +|----------------------------------------------------|---------|----------------------------------------------------------------| +| version workspace `0.2.11-pre.11.fix.1` | PASS | `Cargo.toml` racine | +| endpoint CoinMarketCap V2 inchangé | PASS | `/v2/simple/price` et `/public-api/v2/simple/price` | +| identifiant SOL CoinMarketCap corrigé en `id=5426` | PASS | builder commun Keyless / Basic | +| query V2 exacte canarisée | PASS | `id=5426&convert=USD&include_last_updated=true` | +| parser/rate-limit/auth/sémantique inchangés | PASS | aucun autre contrat runtime modifié | +| six autres providers keyless du smoke initial | PASS | outcomes live `pre.011`, aucun autre échec | +| re-smoke keyless après fix | PENDING | obligatoire avant `pre.012` | +| smoke keyed réel | PENDING | `SKIP opérateur` permis si les quatre credentials sont absents | + +Ce correctif est technique et appartient toujours à la lane `pre.011`. Il ne transfère aucune responsabilité documentaire à `pre.012`. + ## 4. Matrice provider prévue -| Provider | SOL/USD V1 | Gratuit V1 | Mode auth prévu | Test déterministe | Smoke live | Statut courant | -|-------------------|------------|------------|----------------------|-------------------|------------|----------------| -| CoinGecko | Oui | Oui | keyless ou Demo key | PASS | PENDING | IMPLEMENTED | -| CoinMarketCap | Oui | Oui | keyless ou Basic key | PASS | PENDING | IMPLEMENTED | -| CoinPaprika | Oui | Oui | aucune | PASS | PENDING | IMPLEMENTED | -| Kraken | Oui | Oui | aucune | PASS | PENDING | IMPLEMENTED | -| Coinbase Exchange | Oui | Oui | aucune | PASS | PENDING | IMPLEMENTED | -| Jupiter Price V3 | Oui | Oui | keyless ou Free key | PASS | PENDING | IMPLEMENTED | -| Birdeye | Oui | Oui | API key Standard | PASS | PENDING | IMPLEMENTED | -| DexScreener | Oui | Oui | aucune | PASS | PENDING | IMPLEMENTED | +| Provider | SOL/USD V1 | Gratuit V1 | Mode auth prévu | Test déterministe | Smoke live | Statut courant | +|-------------------|------------|------------|----------------------|-------------------|------------------|----------------| +| CoinGecko | Oui | Oui | keyless ou Demo key | PASS | PASS keyless | IMPLEMENTED | +| CoinMarketCap | Oui | Oui | keyless ou Basic key | PASS | PENDING re-smoke | IMPLEMENTED | +| CoinPaprika | Oui | Oui | aucune | PASS | PASS | IMPLEMENTED | +| Kraken | Oui | Oui | aucune | PASS | PASS | IMPLEMENTED | +| Coinbase Exchange | Oui | Oui | aucune | PASS | PASS | IMPLEMENTED | +| Jupiter Price V3 | Oui | Oui | keyless ou Free key | PASS | PASS keyless | IMPLEMENTED | +| Birdeye | Oui | Oui | API key Standard | PASS | PENDING keyed | IMPLEMENTED | +| DexScreener | Oui | Oui | aucune | PASS | PASS | IMPLEMENTED | `AUDITED` signifie uniquement que la documentation officielle actuelle satisfait le gate d'entrée. Ce statut ne vaut pas preuve d'un smoke réseau KSP.