Files
khadhroony-solana-project/deltas/0.2.11/pre.007.md
2026-08-26 10:06:21 +02:00

8.0 KiB

Delta 0.2.11-pre.007 — Birdeye + registry + availability

1. Base requise

Cette tranche s'applique exclusivement après 0.2.11-pre.006 accepté par l'opérateur.

Version Cargo attendue à l'entrée :

0.2.11-pre.6

Version Cargo de sortie :

0.2.11-pre.7

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 à 120 tables / 111 fichiers, cargo check --workspace, cargo clippy --workspace --all-targets et cargo test -p ksp-offchain-transport-lib avec 43 unitaires + 4 boundary + 5 public API. cargo test --workspace n'a pas été rejoué sur l'état exact pre.006 avant le passage explicite à cette tranche.

2. Objet strict de la tranche

pre.007 ferme l'inventaire V1 des huit providers et matérialise le registry provider-neutral :

Birdeye Standard
MarketPriceProviderRegistry
MarketPriceProviderRegistryEntry
availability générique consultable
metadata de coût provider informatif

La tranche n'ajoute pas encore :

refresh(provider_id)
refresh multiple/all
service de dispatch provider
Config Off-chain Transport
smoke live
fallback/consensus

3. Birdeye Standard

Ajout de :

market_price_birdeye.rs
unit_tests/market_price_birdeye.rs
MarketPriceBirdeyeSettings
MarketPriceBirdeyeProvider

Le réaudit officiel courant confirme :

base URL             https://public-api.birdeye.so
endpoint             GET /defi/price
mint SOL             So11111111111111111111111111111111111111112
chain header         x-chain: solana
auth header          X-API-KEY
Standard             0 USD, 30 000 compute units inclus
limite compte        1 RPS
Price Single         3 compute units par appel

Une clé Birdeye est obligatoire lorsque le provider est activé. Un provider désactivé peut être construit sans secret afin que Config et le futur service puissent représenter un état non actif sans inventer de credential.

La clé reste dans MarketPriceApiKey, n'est jamais lue directement depuis l'environnement par Off-chain Transport et n'apparaît ni dans Debug, ni dans les logs, ni dans les erreurs.

Le request builder utilise uniquement l'origine officielle fixe, le mint WSOL fixe et x-chain = solana.

La réponse Price Single est normalisée depuis :

data.value
data.updateUnixTime
success

data.value passe par serde_json::RawValue puis MarketPriceDecimal sans round-trip f64. updateUnixTime devient un vrai provider_timestamp en secondes Unix converties en millisecondes.

La sémantique retenue est :

MarketPriceSemantics::SolanaSpot

La provenance sûre est :

birdeye:solana:wsol:value

Une réponse success = false, un prix absent/null, un timestamp absent/pathologique ou un JSON incompatible sont rejetés sans copier le body distant dans les diagnostics.

4. Quota et coût provider informatifs

Birdeye utilise des compute units. Pour ne pas les confondre avec des crédits abstraits ou des requêtes HTTP, MarketPriceProviderQuotaUnit gagne :

ComputeUnits

MarketPriceProviderRequestCost représente un coût unitaire documenté pour l'opération SOL/USD courante.

Le descriptor Birdeye expose :

long_term_quota = 30 000 ComputeUnits / Month
sol_usd_request_cost = 3 ComputeUnits

Ces valeurs sont informatives. KSP ne décrémente pas localement le quota et ne prétend pas connaître un solde authoritative : un autre processus ou une autre API du même compte peut consommer les mêmes compute units.

MarketPriceProviderDescriptor::with_sol_usd_request_cost vérifie que le coût et le quota utilisent la même unité lorsqu'un quota est présent.

5. Registry provider-neutral

Ajout de :

market_price_registry.rs
unit_tests/market_price_registry.rs
MarketPriceProviderRegistry
MarketPriceProviderRegistryEntry
ERROR_CODE_MARKET_PRICE_REGISTRY_INVALID

Une entrée contient seulement :

MarketPriceProviderDescriptor
MarketPriceProviderState

Le registry :

est borné à 64 entrées
trie les entrées par provider_id
rejette les provider_id dupliqués
permet lookup descriptor/state/entry par identifiant opaque
expose une slice déterministe d'entrées
ne contient aucun nom ou dispatch provider spécifique

Le constructeur reste public et provider-neutral, comme MarketPriceProviderDescriptor::new déjà existant. Cela ne donne aucun accès à un endpoint ou à un client HTTP. Le futur service pre.008 possédera les transitions runtime et le dispatch des adapters ; la HID ne devra pas construire ou matcher des providers spécifiques.

Un canari de complétude construit les huit adapters V1 en mode désactivé et vérifie l'inventaire ordonné :

birdeye
coinbase_exchange
coingecko
coinmarketcap
coinpaprika
dexscreener
jupiter
kraken

6. Availability générique

MarketPriceProviderAvailability gagne deux helpers publics provider-neutral :

is_refresh_eligible()
retry_at()

Ils permettent à un consumer d'interpréter Ready, CoolingDown ou TemporarilyUnavailable sans parser des erreurs ni connaître le fournisseur.

Les catégories existantes restent distinctes :

AuthenticationUnavailable
CoolingDown
Disabled
Misconfigured
QuotaUnavailable
Ready
TemporarilyUnavailable

pre.007 ne relie pas encore automatiquement les erreurs d'un refresh à ces transitions. Cette mutation runtime appartient au service de pre.008.

7. Façade publique

La taxonomie reste capability-scoped :

MarketPriceBirdeye*
MarketPriceProviderRegistry*
MarketPriceProviderRequestCost

Aucun DTO wire Birdeye, HttpRestClient, limiter interne ou primitive reqwest n'est exporté.

Le registry public reste générique ; aucun consumer n'a besoin d'un enum CoinGecko/Birdeye/Jupiter pour l'inspecter.

8. Tests déterministes ajoutés

Les nouveaux canaries couvrent :

Birdeye API key obligatoire si enabled
redaction du secret Birdeye
endpoint fixe et headers attendus
mint WSOL fixe
1 RPS par compte
30 000 compute units informatifs
3 compute units par Price Single
prix exact via RawValue
updateUnixTime -> provider_timestamp
success false rejeté
prix null rejeté
timestamp absent rejeté
request cost nul rejeté
mismatch unité quota/coût rejeté
registry des huit providers complet
ordre déterministe du registry
doublons provider_id rejetés
lookup descriptor/state générique
availability is_refresh_eligible/retry_at
absence de noms provider dans le module registry

9. 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 le réaudit Birdeye courant et précise que quotas/cost metadata restent non-authoritative.

10. Fichiers ajoutés

crates/ksp-offchain-transport-lib/src/market_price_birdeye.rs
crates/ksp-offchain-transport-lib/src/market_price_registry.rs
crates/ksp-offchain-transport-lib/unit_tests/market_price_birdeye.rs
crates/ksp-offchain-transport-lib/unit_tests/market_price_registry.rs
deltas/0.2.11/pre.007.md

11. Fichiers modifiés

Cargo.toml
crates/ksp-offchain-transport-lib/src/error.rs
crates/ksp-offchain-transport-lib/src/lib.rs
crates/ksp-offchain-transport-lib/src/market_price_provider.rs
crates/ksp-offchain-transport-lib/tests/dependency_boundary.rs
crates/ksp-offchain-transport-lib/tests/public_api.rs
crates/ksp-offchain-transport-lib/unit_tests/market_price_provider.rs
docs/plans/018-V0_2_11_OFFCHAIN_PRICE_TRANSPORT_PLAN.md
docs/validation/014-V0_2_11_OFFCHAIN_PRICE_TRANSPORT.md

12. 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.008 ne doit commencer qu'après un gate propre de pre.007 ou un delta fix explicite.