Files
2026-08-26 15:45:02 +02:00

182 lines
7.4 KiB
Markdown

<!-- file: crates/ksp-offchain-transport-lib/USAGE.md -->
<!-- version: 2 -->
# Usage de ksp-offchain-transport-lib
Cette page documente la surface stable préparée pour `0.2.11`. Les credentials et documents runtime doivent normalement être résolus par `ksp-config-lib`; les constructions directes ci-dessous servent surtout aux tests, outils bas niveau et compositions programmatiques maîtrisées.
## 1. Construire un service programmatique
Un service reçoit une liste de `MarketPriceProviderSetup`. Le setup est provider-specific uniquement au moment de la composition :
```rust
let coingecko = ksp_offchain_transport_lib::MarketPriceCoinGeckoSettings::keyless(true)?;
let kraken = ksp_offchain_transport_lib::MarketPriceKrakenSettings::new(true)?;
let service = ksp_offchain_transport_lib::MarketPriceService::new(std::vec![
ksp_offchain_transport_lib::MarketPriceProviderSetup::CoinGecko(coingecko),
ksp_offchain_transport_lib::MarketPriceProviderSetup::Kraken(kraken),
])?;
```
Une application normale n'a pas à reproduire le mapping des huit providers. `ksp-config-lib::ResolvedOffchainTransportConfig` construit cette composition depuis `cfg.std.offchain_transport`.
## 2. Découvrir le registry générique
Après construction, le consumer travaille sur le registry sans matcher les variants provider :
```rust
for entry in service.registry().entries() {
let descriptor = entry.descriptor();
let state = entry.state();
println!(
"{} {:?} {:?}",
descriptor.display_name(),
descriptor.semantics(),
state.availability(),
);
}
```
Le `provider_id` est opaque. Il sert d'identité stable pour rappeler le service, pas de signal autorisant le consumer à reconstruire un endpoint ou une règle provider.
## 3. Rafraîchir un provider
```rust
let provider_id = ksp_offchain_transport_lib::MarketPriceProviderId::new("coingecko")?;
let outcome = service.refresh(&provider_id).await?;
```
L'outcome expose génériquement l'observation éventuelle et l'état provider. Une erreur provider normalisée n'oblige pas le consumer à parser CoinGecko, Kraken ou Jupiter.
Avant un refresh, l'état peut être consulté via le registry. `MarketPriceProviderAvailability::retry_at()` expose le prochain instant connu lorsqu'il existe réellement.
## 4. Rafraîchir plusieurs providers
```rust
let ids = service
.registry()
.entries()
.iter()
.map(|entry| return entry.descriptor().id().clone())
.collect::<std::vec::Vec<_>>();
let outcomes = service.refresh_many(ids.as_slice()).await?;
```
La V1 exécute ce batch **séquentiellement**, dans l'ordre demandé. Elle valide les IDs avant le premier dispatch, rejette les doublons, ne dort pas pour un cooldown et produit un outcome générique par provider lorsque l'opération est valide.
`refresh_all()` applique le même contrat dans l'ordre stable du registry :
```rust
let outcomes = service.refresh_all().await?;
```
Il n'existe pas de fallback, consensus ou moyenne implicite. Une application voulant comparer les observations doit conserver leurs sémantiques et provenances ; elle ne doit pas présenter leurs différences comme une erreur de KSP.
## 5. Construire depuis Config
La voie runtime normale est :
```rust
let resolved = engine.load_resolved_offchain_transport_config(
std::option::Option::None,
&environment,
)?;
let service = resolved.service();
let registry = service.registry();
```
Le profil `public_keyless` du document standard peut être résolu sans credentials. Le profil `all_free` attend les secrets/public fields inventoriés dans `.env.example` et validés par `ksp-config-lib`.
Off-chain Transport ne lit pas l'environnement lui-même. Ne passez pas un credential via une URL, une query arbitraire ou une surface UI libre pour contourner Config.
## 6. DexScreener
DexScreener doit recevoir la paire SOL/USD Solana explicitement approuvée par la composition lorsqu'il est activé :
```rust
let pair = ksp_core_lib::Pubkey::parse("<PAIR_ADDRESS_APPROUVEE>")?;
let settings = ksp_offchain_transport_lib::MarketPriceDexScreenerSettings::new(
true,
std::option::Option::Some(pair),
)?;
```
La paire n'est pas un secret. Aucun helper V1 ne découvre automatiquement une autre pool, ne trie par liquidité ou ne remplace la paire configurée.
## 7. Exactitude numérique
Ne convertissez pas l'observation canonique en `f64` pour la stocker ou la comparer comme vérité KSP. `MarketPriceDecimal` conserve une forme décimale exacte et sérialise une représentation canonique.
Pour l'affichage, un consumer peut utiliser sa représentation textuelle publique. Toute conversion approximative éventuelle appartient à une couche de présentation qui accepte explicitement cette perte ; elle ne doit pas remplacer le type canonique dans le transport.
## 8. Forward compatibility
Les enums publiques susceptibles d'évoluer sont `#[non_exhaustive]`. Hors de la crate, les matches doivent donc prévoir un fallback :
```rust
match entry.state().availability() {
ksp_offchain_transport_lib::MarketPriceProviderAvailability::Ready => {},
ksp_offchain_transport_lib::MarketPriceProviderAvailability::Disabled => {},
_ => {},
}
```
La branche `_` est intentionnelle : de nouveaux providers, états, sémantiques ou paires pourront être ajoutés sans imposer une rupture source aux consumers bien écrits.
## 9. Diagnostics sûrs
Les diagnostics applicatifs peuvent journaliser :
```text
provider_id validé
code d'erreur KSP
classe d'availability
retry_at borné lorsqu'il existe
durée/opération générique
```
Ils ne doivent pas journaliser :
```text
API key
URL complète sensible
header provider secret
body distant brut
payload de Config secret
```
`ksp-offchain-transport-lib` utilise `ksp-logging-lib` et son `TRACING_TARGET` propriétaire ; une application ne doit pas ajouter un bypass direct `tracing` pour obtenir les payloads rejetés.
## 10. Smokes live de release
Le smoke keyless final ne requiert aucun secret et couvre les sept modes V1 concernés :
```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 gate `0.2.11-pre.011-fix.001` a passé ce smoke en `7/7`. Le test ne compare jamais les providers à un prix exact commun : il valide l'identité, la paire SOL/USD, la sémantique, un prix canonique positif et la cohérence des timestamps disponibles.
Le smoke keyed reste volontairement distinct. Il lit quatre clés sur `stdin`, dans l'ordre Birdeye, CoinGecko Demo, CoinMarketCap Basic et Jupiter Free :
```bash
printf '%s\n%s\n%s\n%s\n' \
"$KSP_SECRET_BIRDEYE_API_KEY" \
"$KSP_SECRET_COINGECKO_DEMO_API_KEY" \
"$KSP_SECRET_COINMARKETCAP_API_KEY" \
"$KSP_SECRET_JUPITER_API_KEY" \
| cargo test -p ksp-offchain-transport-lib \
--test market_price_live_smoke \
keyed_market_price_providers_live_smoke \
-- --ignored --exact --nocapture --test-threads=1
```
Ce second smoke peut être omis si l'opérateur ne possède pas les quatre credentials ; l'absence de credentials doit alors rester explicitement `SKIP opérateur`.
## 11. Statut documentaire
Ce document est la référence d'usage durable de la surface `market_price` livrée par `0.2.11`. Il ne promet ni prix identique entre providers, ni disponibilité permanente de leurs plans gratuits, ni compatibilité avec une surface provider qui changerait après la release.