7.2 KiB
Delta 0.2.11-pre.006 — Jupiter Price V3 + DexScreener
1. Base requise
Cette tranche s'applique exclusivement après 0.2.11-pre.005 accepté par l'opérateur.
Version Cargo attendue à l'entrée :
0.2.11-pre.5
Version Cargo de sortie :
0.2.11-pre.6
Le gate d'entrée ciblé du 2026-08-25 est PASS : cargo fmt --all, audit Rust clean avec 0 candidate export, audit Markdown clean à 119 tables / 110 fichiers, cargo check --workspace, cargo clippy --workspace --all-targets et cargo test -p ksp-offchain-transport-lib avec 37 unitaires + 3 boundary + 4 public API. cargo test --workspace n'a pas été rejoué sur l'état exact pre.005 avant le passage explicite à cette tranche.
2. Objet strict de la tranche
pre.006 ajoute uniquement les deux providers prévus par le forecast :
Jupiter Price V3
DexScreener
Le contrat reste :
SOL/USD uniquement
HTTP REST direct via reqwest
aucun SDK provider
aucune découverte automatique de pool
aucun fallback/consensus/agrégation KSP
pas de registry global
pas de Config
pas de refresh multiple
pas de smoke live revendiqué
3. Jupiter Price V3
Ajout de :
market_price_jupiter.rs
unit_tests/market_price_jupiter.rs
MarketPriceJupiterAccessMode
MarketPriceJupiterSettings
MarketPriceJupiterProvider
Le réaudit officiel courant confirme le Developer Platform unifié :
base URL https://api.jup.ag
endpoint /price/v3
mint SOL So11111111111111111111111111111111111111112
keyless 0.5 RPS
Free avec API key 1 RPS
header keyed x-api-key
Les deux modes utilisent la même origine officielle. Le mode keyless n'accepte aucun credential ; le mode Free exige une clé lorsqu'il est activé. La clé reste dans MarketPriceApiKey, n'est jamais lue depuis l'environnement par cette crate et n'apparaît pas dans Debug, les logs ou les erreurs.
Price V3 expose usdPrice comme prix USD unique. KSP le lit via serde_json::RawValue puis MarketPriceDecimal, sans passage canonique par f64.
Le contrat V3 expose également blockId, qui peut servir à raisonner sur la récence du prix. KSP le conserve uniquement dans la provenance sûre :
jupiter:price_v3:<mint>:block:<blockId>
createdAt décrit la création du token et n'est pas un timestamp de prix. blockId n'est pas un timestamp non plus. L'observation conserve donc explicitement :
provider_timestamp = None
MarketPriceSemantics::SolanaHeuristic
Le parser exige la clé exacte du mint WSOL, decimals = 9, un usdPrice présent et positif, et un blockId présent. Une réponse sans prix est une réponse provider non exploitable pour une observation réussie ; le registry/availability générique sera matérialisé en pre.007.
4. DexScreener
Ajout de :
market_price_dexscreener.rs
unit_tests/market_price_dexscreener.rs
MarketPriceDexScreenerSettings
MarketPriceDexScreenerProvider
Le V1 suit strictement la décision opérateur : un client SOL/USD lié à une paire Solana explicitement configurée.
L'endpoint officiel utilisé est uniquement :
https://api.dexscreener.com/latest/dex/pairs/solana/{pairId}
La documentation DexScreener le borne actuellement à :
300 requêtes / minute
Le pair address est validé comme ksp_core_lib::Pubkey dans les settings. Le client construit le chemin à partir de l'origine officielle fixe et du seul segment Pubkey validé ; aucune base URL configurable n'est introduite.
Avant d'accepter priceUsd, le parser vérifie :
une seule paire retournée
chainId = solana
pairAddress = pair address configuré
baseToken.address = So11111111111111111111111111111111111111112
priceUsd présent et exact
KSP ne consulte pas :
/latest/dex/search
/token-pairs/v1
/tokens/v1
et ne fait aucun pool discovery, ranking de liquidité, sélection automatique, moyenne ou consensus.
La provenance conserve le pair address, considéré comme sûr :
dexscreener:solana:<pairAddress>:priceUsd
La sémantique publique reste :
MarketPriceSemantics::DexPairUsd
provider_timestamp = None
5. HTTP commun
HttpGetRequest gagne uniquement une primitive crate-private :
append_path_segment
Elle permet de construire un endpoint provider à origine fixe lorsque le contrat nécessite un segment dynamique validé, ici le Pubkey de la paire DexScreener. Cette évolution ne crée aucune API HTTP publique et ne permet pas au consumer de fournir une URL arbitraire.
6. Façade publique
La taxonomie reste capability-scoped :
MarketPriceJupiter*
MarketPriceDexScreener*
Aucun type wire provider, client HTTP générique ou primitive d'admission n'est exporté aux consumers.
Le futur ksp-app-solprices-desk ne devra pas construire ces settings provider directement ; pre.009 donnera cette responsabilité à Config et le service générique prévu en pre.007/pre.008 masquera les variantes provider à l'HID.
7. Tests déterministes ajoutés
Les nouveaux canaries couvrent :
Jupiter keyless 0.5 RPS
Jupiter Free 1 RPS + API key redacted
query Jupiter fixée au mint WSOL
Jupiter prix exact via RawValue
Jupiter blockId conservé en provenance
Jupiter provider_timestamp absent
Jupiter prix absent rejeté
Jupiter identité/decimals incohérents rejetés
DexScreener pair address Pubkey explicite
URL pair directe construite sans discovery
DexScreener 300 req/min
chainId Solana vérifié
pairAddress retourné vérifié
base token WSOL vérifié
priceUsd exact
réponse multi-pair rejetée
prix absent rejeté
absence des endpoints search/token discovery
façade publique des deux adapters
8. Documentation réconciliée
Mise à jour de :
docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md
docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md
Le plan enregistre également le réaudit Jupiter/DexScreener courant et distingue explicitement blockId Jupiter d'un timestamp provider.
9. Fichiers ajoutés
crates/ksp-offchain-transport-lib/src/market_price_dexscreener.rs
crates/ksp-offchain-transport-lib/src/market_price_jupiter.rs
crates/ksp-offchain-transport-lib/unit_tests/market_price_dexscreener.rs
crates/ksp-offchain-transport-lib/unit_tests/market_price_jupiter.rs
deltas/0.2.11/pre.006.md
10. Fichiers modifiés
Cargo.toml
crates/ksp-offchain-transport-lib/src/http_client.rs
crates/ksp-offchain-transport-lib/src/lib.rs
crates/ksp-offchain-transport-lib/tests/dependency_boundary.rs
crates/ksp-offchain-transport-lib/tests/public_api.rs
docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md
docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md
11. Validation attendue
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 --workspace
pre.007 ne doit commencer qu'après un gate propre de pre.006 ou un delta fix explicite.