147 lines
7.3 KiB
Markdown
147 lines
7.3 KiB
Markdown
<!-- file: crates/ksp-offchain-transport-lib/README.md -->
|
|
<!-- version: 2 -->
|
|
|
|
# ksp-offchain-transport-lib
|
|
|
|
`ksp-offchain-transport-lib` est le propriétaire des transports et adaptations de données **off-chain** utilisés par KSP. La release `0.2.11` matérialise sa première famille fonctionnelle, `market_price`, limitée à des observations SOL/USD multi-provider.
|
|
|
|
La crate n'est pas une crate « prix uniquement ». Les responsabilités durables sont séparées par famille :
|
|
|
|
```text
|
|
http_* mécanique HTTP partagée réellement commune
|
|
market_price_* prix de marché / spot normalisés
|
|
swap_quote_* future famille de quotes montant/route
|
|
<future_capability>_* ajoutée uniquement lorsqu'un scope réel l'exige
|
|
```
|
|
|
|
## Contrat `market_price` V1
|
|
|
|
La façade publique fournit :
|
|
|
|
- `MarketPriceDecimal`, représentation décimale exacte positive sans vérité canonique `f64` ;
|
|
- `MarketPriceObservation`, avec paire, prix, sémantique, timestamps KSP/provider et provenance sûre ;
|
|
- `MarketPriceProviderDescriptor` et `MarketPriceProviderState`, pour décrire capacités et availability sans logique provider côté consumer ;
|
|
- `MarketPriceProviderRegistry`, inventaire déterministe des providers configurés ;
|
|
- `MarketPriceService`, façade provider-agnostic pour `refresh`, `refresh_many` et `refresh_all` ;
|
|
- `MarketPriceProviderSetup`, frontière de composition initiale provider-specific qui ne doit pas devenir la surface runtime de la HID.
|
|
|
|
La paire publique V1 est exclusivement :
|
|
|
|
```text
|
|
SOL/USD
|
|
```
|
|
|
|
Les enums publiques susceptibles d'évoluer sont `#[non_exhaustive]`. Un consumer externe doit donc conserver une branche future-safe et ne pas supposer que les paires, sémantiques, états ou providers resteront définitivement fermés à ceux de `0.2.11`.
|
|
|
|
## Providers V1
|
|
|
|
L'inventaire fonctionnel comporte exactement huit adapters :
|
|
|
|
```text
|
|
birdeye
|
|
coinbase_exchange
|
|
coingecko
|
|
coinmarketcap
|
|
coinpaprika
|
|
dexscreener
|
|
jupiter
|
|
kraken
|
|
```
|
|
|
|
Ils ne prétendent pas produire la même vérité de marché. `MarketPriceSemantics` conserve notamment la différence entre agrégateur, dernier trade d'exchange, heuristique Solana, spot Solana et paire DEX.
|
|
|
|
Les origines HTTPS, chemins, headers d'authentification, identités d'asset et limites provider restent possédés par les adapters. V1 n'expose aucune URL provider arbitraire ni aucun SDK fournisseur.
|
|
|
|
DexScreener reste un cas volontairement strict : une paire Solana explicite est fournie à la composition lorsqu'il est activé ; l'adapter appelle uniquement la paire configurée et ne découvre, ne classe ni n'agrège automatiquement des pools.
|
|
|
|
## HTTP et résilience
|
|
|
|
Les primitives `http_*` sont crate-private. Elles appliquent notamment :
|
|
|
|
```text
|
|
reqwest uniquement
|
|
HTTPS provider fixe
|
|
redirects désactivés
|
|
Referer automatique désactivé
|
|
proxy système implicite désactivé
|
|
retries reqwest implicites désactivés
|
|
connect/request timeouts bornés
|
|
body borné pendant la lecture
|
|
JSON validé avant mapping typed
|
|
URL retirée des erreurs reqwest
|
|
aucun body distant brut dans KspError
|
|
429 et Retry-After classés
|
|
```
|
|
|
|
Le rate limiting est provider-owned et non bloquant. Un provider non éligible est projeté en availability/cooldown ; le service ne dort pas pour attendre sa prochaine fenêtre.
|
|
|
|
## Refresh individuel et multiple
|
|
|
|
`MarketPriceService` est la surface runtime générique.
|
|
|
|
La V1 garde un comportement multiple **séquentiel et déterministe** :
|
|
|
|
```text
|
|
refresh(provider_id) un provider opaque
|
|
refresh_many(provider_ids) ordre demandé conservé
|
|
refresh_all() ordre stable du registry
|
|
```
|
|
|
|
Un provider en cooldown ou en erreur n'empêche pas la projection des autres outcomes. Le service ne fait aucun fallback, aucun consensus et aucune agrégation de prix entre providers.
|
|
|
|
Le séquentiel de V1 est un contrat volontaire de simplicité et de déterminisme, pas une obligation architecturale éternelle. Une évolution vers une orchestration concurrente demanderait un contrat explicite sur l'ordre, les limites et les effets observables.
|
|
|
|
## Config et secrets
|
|
|
|
Cette crate **ne lit jamais** directement `KSP_*`, `KSPB_*`, `.env` ou les documents Config.
|
|
|
|
La direction autorisée est :
|
|
|
|
```text
|
|
ksp-config-lib
|
|
-> ksp-offchain-transport-lib
|
|
```
|
|
|
|
`ksp-config-lib` résout les credentials, vérifie leur provenance et construit `MarketPriceProviderSetup` / `MarketPriceService`. La dépendance inverse est interdite.
|
|
|
|
Les API keys ne sont pas exposées par les projections publiques usuelles et leurs `Debug` sont redacted. Les erreurs/logs n'embarquent ni credential, ni URL sensible, ni payload distant brut.
|
|
|
|
## Numeric safety et provenance
|
|
|
|
`MarketPriceDecimal` accepte les formes décimales/scientifiques bornées nécessaires aux wire providers, puis normalise vers un coefficient `u128` et une scale limitée. Sont rejetés notamment : zéro pour une observation réussie, négatifs, valeurs non numériques, overflow, scale excessive et exposants pathologiques.
|
|
|
|
Les timestamps provider ne sont présents que lorsqu'un provider fournit réellement une information temporelle correspondant au prix. Un block id, une date de création d'asset ou une donnée de récence non temporelle n'est jamais convertie en faux timestamp.
|
|
|
|
La provenance textuelle est bornée et contrôlée afin de rester sûre pour les projections/logs.
|
|
|
|
## Hors scope de `0.2.11`
|
|
|
|
```text
|
|
SOL/EUR
|
|
fallback automatique
|
|
consensus ou moyenne multi-provider
|
|
découverte automatique de pool DexScreener
|
|
scheduler périodique
|
|
historique persistant
|
|
swap routing / Jupiter quote
|
|
soumission ou signature de transaction Solana
|
|
SDK provider
|
|
URL provider configurable
|
|
```
|
|
|
|
## Documentation
|
|
|
|
- [`USAGE.md`](USAGE.md) — construction programmatique et utilisation de la façade générique ;
|
|
- [`../../docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md`](../../docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md) — plan de release ;
|
|
- [`../../docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md`](../../docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md) — matrice de validation.
|
|
|
|
## Validation de release `0.2.11`
|
|
|
|
La candidate finale a été validée sur les huit adapters par tests déterministes. Le smoke live keyless de clôture a réellement rafraîchi les sept modes ne nécessitant aucun credential : Coinbase Exchange, CoinGecko, CoinMarketCap, CoinPaprika, DexScreener, Jupiter et Kraken. Un premier passage a révélé le paramètre CoinMarketCap V2 erroné `ids`; `pre.011-fix.001` l'a corrigé en `id=5426`, puis le re-smoke a passé les sept providers.
|
|
|
|
Birdeye n'expose pas de mode keyless V1. Le smoke keyed commun Birdeye/CoinGecko Demo/CoinMarketCap Basic/Jupiter Free reste opt-in et peut être `SKIP opérateur` lorsque les quatre credentials gratuits ne sont pas disponibles. KSP ne transforme jamais cette absence de credentials en preuve live fictive.
|
|
|
|
Les offres gratuites, quotas et conditions d'usage appartiennent aux providers et peuvent évoluer indépendamment du contrat KSP. Les descriptors représentent le snapshot audité pour `0.2.11`; un changement commercial ou de quota futur peut rendre un provider indisponible sans modifier la façade provider-neutral.
|
|
|
|
Ce README est la documentation durable de la surface `0.2.11`. Les détails de construction et les commandes de smoke sont conservés dans [`USAGE.md`](USAGE.md), tandis que le plan et la matrice de validation enregistrent les décisions et preuves de release.
|