473 lines
47 KiB
Markdown
473 lines
47 KiB
Markdown
<!-- file: docs/architecture/011-RAW_TRANSACTION_ACQUISITION.md -->
|
||
<!-- version: 2 -->
|
||
|
||
# Acquisition RAW Transaction
|
||
|
||
## 1. Rôle
|
||
|
||
Ce document est l'owner durable de la taxonomie d'acquisition `RawTransaction` de KSP. Il sépare volontairement :
|
||
|
||
- les invariants durables de convergence vers Store ;
|
||
- les rôles/capabilities d'acquisition ;
|
||
- les audits datés de protocoles/providers ;
|
||
- les gaps à transmettre aux releases d'implémentation.
|
||
|
||
Il ne définit ni un endpoint secret, ni un quota provider figé, ni une configuration utilisateur. Les disponibilités et limites externes sont réauditées à la date indiquée dans chaque section d'audit.
|
||
|
||
## 2. Invariants durables
|
||
|
||
La convergence RAW reste indépendante de la source :
|
||
|
||
```text
|
||
identité canonique transaction = (network, signature)
|
||
contenu canonique = source-independent
|
||
acquisition utile = RawTransactionObservation distincte
|
||
provider/protocole/endpoint = provenance, jamais identité transactionnelle
|
||
même identité + même contenu = idempotence
|
||
même identité + contenu divergent = conflit explicite
|
||
```
|
||
|
||
Une source n'est admise pour persister un `RawTransaction` que si KSP peut reconstruire le payload canonique complet attendu par Store. Un signal incomplet reste une discovery et doit être hydraté par une autre capability.
|
||
|
||
## 3. Taxonomie de rôles
|
||
|
||
| Rôle | Responsabilité | Exemple standard actuel |
|
||
|-------------------------|-----------------------------------------------------------|------------------------------------------------------------------|
|
||
| `live_direct_full` | transaction/bloc complet reçu directement | WS blockSubscribe aujourd’hui ; autres sources en pre.005 |
|
||
| `live_discovery` | référence/signature reçue puis hydration séparée | WS logsSubscribe |
|
||
| `targeted_confirmation` | signature déjà connue surveillée jusqu’au commitment | WS signatureSubscribe |
|
||
| `history_discovery` | énumération de références historiques | HTTP getSignaturesForAddress ; HTTP getBlocks/getBlocksWithLimit |
|
||
| `hydration` | récupération de transaction complète depuis une référence | HTTP getTransaction |
|
||
| `gap_boundary` | détermination d’une fenêtre ou d’une limite de rétention | getSlot/getFirstAvailableBlock/minimumLedgerSlot |
|
||
| `gap_repair` | réacquisition explicite après perte de continuité | HTTP bloc ou adresse selon le scope disponible |
|
||
|
||
Ces rôles sont orthogonaux au protocole. Une stratégie concrète peut combiner plusieurs rôles et plusieurs transports ; la configuration future ne doit pas réduire le modèle à `Http | WebSocket | Grpc`.
|
||
|
||
## 4. Audit daté A — Solana standard
|
||
|
||
Audit effectué le **4 septembre 2026** à partir de la documentation RPC Solana courante et de la surface KSP `0.3.9-pre.3`.
|
||
|
||
### 4.1 Matrice fonctionnelle
|
||
|
||
| Voie | Capability | RAW complet | Temporalité utile | Décision | État KSP |
|
||
|------------------------------------------------------|------------------------------------|----------------------------------|-----------------------------------------|------------------------|-----------------------------------------------------------------------------------|
|
||
| HTTP `getSignaturesForAddress` + `getTransaction` | discovery adresse + hydration | non / oui | historique, catch-up, repair ciblé | ADMIS | déjà utilisé par Backfill ; `getTransaction` observé conserve provider + endpoint |
|
||
| HTTP `getBlocks` / `getBlocksWithLimit` + `getBlock` | discovery slots/blocs + extraction | non / oui | catch-up global, gap repair, historique | ADMIS SOUS GAP | `getBlock` typé existe mais pas de variante observée |
|
||
| HTTP `getSlot` | borne haute selon commitment | non | pilotage catch-up / gap | AUXILIAIRE | surface typée KSP disponible |
|
||
| HTTP `getFirstAvailableBlock` | borne basse des blocs conservés | non | admission historique / diagnostic | AUXILIAIRE | surface typée KSP disponible |
|
||
| HTTP `minimumLedgerSlot` | borne basse ledger du nœud | non | diagnostic de rétention/provider | AUXILIAIRE | surface typée KSP disponible |
|
||
| WS `logsSubscribe` | discovery live par logs | non | live + signal de gap | ADMIS | hydration `getTransaction` obligatoire pour RAW complet |
|
||
| WS `signatureSubscribe` | suivi d’une signature déjà connue | non | confirmation/repair ciblé | SECONDAIRE | one-shot ; ne découvre pas un flux de transactions |
|
||
| WS `blockSubscribe` | bloc live contenant transactions | oui si `transactionDetails=full` | live / catch-up très court | ADMIS SOUS CONTRAINTES | méthode Solana instable + activation validator requise |
|
||
| WS `slotSubscribe` | signal slot/parent/root | non | détection/pilotage de gap | AUXILIAIRE | stable mais ne transporte aucune transaction |
|
||
| WS `slotsUpdatesSubscribe` | lifecycle détaillé de slot | non | diagnostic de continuité | OPTIONNEL | méthode Solana instable ; pas une source RAW directe |
|
||
|
||
### 4.2 HTTP adresse : discovery + hydration
|
||
|
||
`getSignaturesForAddress` retourne des signatures confirmées associées à une adresse, ordonnées du plus récent au plus ancien, avec `before`, `until`, `limit`, `commitment` et `minContextSlot`. La discovery est donc naturellement **adressée** : elle ne constitue pas une discovery globale de toutes les transactions du réseau.
|
||
|
||
`getTransaction` retourne ensuite la transaction confirmée complète ou `null`. Pour KSP, cette combinaison est la référence actuelle du Backfill et reste admise pour :
|
||
|
||
```text
|
||
historique adressé
|
||
catch-up adressé
|
||
repair ciblé
|
||
hydration d'un signal WS qui connaît déjà la signature
|
||
```
|
||
|
||
Elle n'est pas retenue comme source live globale par polling.
|
||
|
||
### 4.3 HTTP bloc : scan global par slots
|
||
|
||
`getBlocks` et `getBlocksWithLimit` énumèrent des slots confirmés ; la documentation courante borne leurs ranges/limits à 500 000. `getBlock` peut retourner les transactions complètes du bloc avec `confirmed` ou `finalized` et les options de détail/encodage.
|
||
|
||
Cette famille est admise comme stratégie potentielle de :
|
||
|
||
```text
|
||
catch-up global par slots
|
||
gap repair global
|
||
historique lorsque le provider conserve la plage demandée
|
||
```
|
||
|
||
Elle n'est pas équivalente à `getSignaturesForAddress` : la discovery est par slot/bloc et l'hydration est un conteneur de plusieurs transactions. Le worker doit extraire chaque transaction, reconstruire son identité `(network, signature)` et produire une observation propre à chaque acquisition durable.
|
||
|
||
### 4.4 Bornes de continuité HTTP
|
||
|
||
`getSlot`, `getFirstAvailableBlock` et `minimumLedgerSlot` ne produisent aucune transaction. Ils servent à décider si un gap est encore réparable sur un endpoint et à borner un scan :
|
||
|
||
```text
|
||
getSlot -> borne haute selon commitment
|
||
getFirstAvailableBlock -> premier bloc confirmé encore disponible
|
||
minimumLedgerSlot -> plus ancien slot encore présent dans le ledger du nœud
|
||
```
|
||
|
||
Ces méthodes ne prouvent pas à elles seules qu'une transaction précise est disponible ; elles sont des primitives d'admission/diagnostic.
|
||
|
||
### 4.5 WS logsSubscribe : discovery live
|
||
|
||
`logsSubscribe` peut écouter `all`, `allWithVotes` ou les transactions mentionnant **un seul** pubkey par appel. La notification KSP contient le contexte de slot, la signature, l'erreur nullable et les logs ordonnés.
|
||
|
||
Cette notification n'est pas un `RawTransaction` complet. Elle est admise comme **live discovery** :
|
||
|
||
```text
|
||
logsSubscribe notification
|
||
-> signature + slot
|
||
-> getTransaction observed
|
||
-> normalisation RAW
|
||
-> persistence transaction + observation
|
||
```
|
||
|
||
Le filtre `mentions` limité à une adresse par subscription implique que la surveillance de nombreux programmes/comptes consomme plusieurs subscriptions, sauf utilisation de `all`/`allWithVotes` avec filtrage côté consumer.
|
||
|
||
### 4.6 WS signatureSubscribe : confirmation ciblée
|
||
|
||
`signatureSubscribe` surveille une signature déjà connue et s'arrête automatiquement après la notification terminale au commitment demandé. Il ne découvre donc aucune nouvelle transaction.
|
||
|
||
Décision : **capability secondaire** pour confirmation/repair ciblé, jamais source principale d'ingestion. Une hydration reste nécessaire pour persister le RAW complet.
|
||
|
||
### 4.7 WS blockSubscribe : direct full sous contraintes
|
||
|
||
`blockSubscribe` peut fournir les blocs `confirmed`/`finalized`, filtrés par `all` ou par `mentionsAccountOrProgram`. Avec `transactionDetails=full`, il peut transporter directement les transactions nécessaires à la normalisation RAW.
|
||
|
||
La méthode reste toutefois documentée comme **instable** par Solana et n'est disponible que si le validator active explicitement la block subscription ainsi que l'historique transactionnel requis. KSP doit donc la traiter comme capability annoncée/testée par endpoint, pas comme propriété universelle de tout endpoint WS standard.
|
||
|
||
### 4.8 slotSubscribe et slotsUpdatesSubscribe
|
||
|
||
`slotSubscribe` fournit slot/parent/root et peut aider le worker à détecter que la chaîne avance. `slotsUpdatesSubscribe` fournit un lifecycle de slot plus détaillé, mais reste officiellement instable.
|
||
|
||
Aucune de ces voies ne transporte une transaction. Elles restent auxiliaires pour continuité/diagnostic et ne justifient jamais une observation Store `RawTransaction` seules.
|
||
|
||
### 4.9 Reconnect, ordering et gaps
|
||
|
||
Le protocole standard ne transforme pas une reconnexion en replay des notifications perdues. KSP Transport sait resouscrire les subscriptions logiques après reconnexion et expose un compteur de gaps de continuité, mais cela ne prouve pas quels slots/transactions ont été manqués.
|
||
|
||
Invariants de composition retenus :
|
||
|
||
```text
|
||
reconnect WS != replay
|
||
duplicate notification = acceptable et dédupliquée par identité/contenu/observation
|
||
gap détecté = déclenche une stratégie de repair distincte
|
||
repair = HTTP slot/block ou HTTP adresse selon le scope connu
|
||
```
|
||
|
||
## 5. Inventaire KSP existant
|
||
|
||
### 5.1 Transport
|
||
|
||
| Surface KSP | Disponible | Filtres / entrée | Provenance / remarque |
|
||
|------------------------------------------------------------------|---------------|-----------------------------------------|--------------------------------------------------------------|
|
||
| `get_signatures_for_address` | oui | adresse + before/until/limit/commitment | aucune observation durable nécessaire pour la discovery |
|
||
| `get_transaction_observed` | oui | signature + config | provider + endpoint gagnant sûrs |
|
||
| `get_blocks` / `get_blocks_with_limit` | oui | range/limit + commitment | discovery de slots uniquement |
|
||
| `get_block` | oui | slot + config | GAP : pas de provider/endpoint gagnant observé |
|
||
| `get_slot` / `get_first_available_block` / `minimum_ledger_slot` | oui | bornes de continuité | auxiliaires, sans payload RAW |
|
||
| `logs_subscribe` | oui | all / allWithVotes / mentions(1 pubkey) | session snapshot fournit endpoint/provider/cluster/protocole |
|
||
| `signature_subscribe` | oui | signature connue + commitment | one-shot, terminal côté serveur |
|
||
| `block_subscribe` | oui, instable | all / mentionsAccountOrProgram + config | session snapshot fournit provenance de session |
|
||
| `slot_subscribe` / `slots_updates_subscribe` | oui | aucun filtre | signaux de continuité uniquement |
|
||
|
||
Le runtime WS possède déjà des queues bornées. Une overflow d'une subscription lente est terminale pour cette subscription plutôt que de créer un backlog non borné. Le worker devra traiter cette terminaison comme une cause potentielle de gap et réparer avant de déclarer la continuité retrouvée.
|
||
|
||
### 5.2 Store
|
||
|
||
Store possède déjà les invariants nécessaires à la convergence multi-source :
|
||
|
||
```text
|
||
RawTransactionReference = network + signature
|
||
RawTransaction = reference + slot + block_time + payload canonique
|
||
RawTransactionObservation
|
||
RawAcquisitionProvenance
|
||
RawTransactionWrite::persist_raw_transaction_acquisition
|
||
RawTransactionObservationWrite::record_raw_transaction_observation
|
||
```
|
||
|
||
`RawAcquisitionProvenance` sait déjà conserver de manière sûre : provider, protocole, méthode, origin, endpoint logique, commitment, filter id, capture session id, timestamps et hash/taille du payload source. Aucun DTO Transport ne doit être persistant directement.
|
||
|
||
### 5.3 Normalisation RAW actuelle
|
||
|
||
Le premier canonicalizer RAW v1 est actuellement implémenté dans `ksp-job-backfill-lib::conversion` autour de `getTransaction` observé. Cette implémentation a démontré le format, le hash canonique, la provenance et la persistence du vertical slice Backfill, mais son ownership Job n'est pas réutilisable comme dépendance du futur Worker.
|
||
|
||
Décision de cette tranche : **ne pas copier** cette logique dans `0.3.10`. Le handoff final devra choisir une ownership commune ou une extraction compatible avec les frontières de dépendances.
|
||
|
||
### 5.4 Config et réseaux
|
||
|
||
| Profil | Cluster Transport | Surfaces standard | État |
|
||
|-------------------------|-------------------|---------------------------|------------------------------------|
|
||
| `devnet_public` | devnet | HTTP + WS standard | déjà présent |
|
||
| `mainnet_public` | mainnet-beta | HTTP + WS standard | déjà présent |
|
||
| `mainnet_backfill_pool` | mainnet-beta | HTTP pool + WS standard | déjà présent ; rôles backfill HTTP |
|
||
| `publicnode_mainnet` | mainnet-beta | HTTP + WS standard + gRPC | gRPC traité en pre.005 |
|
||
| `publicnode_testnet` | testnet | HTTP + WS standard + gRPC | gRPC traité en pre.005 |
|
||
|
||
Les URLs et secrets restent exclusivement Config-owned. `0.3.9` n'ajoute aucun endpoint ni secret.
|
||
|
||
#### Canonicalisation Mainnet
|
||
|
||
L'audit interne montre une distinction existante :
|
||
|
||
```text
|
||
profile/composite id : mainnet
|
||
network / cluster : mainnet-beta
|
||
```
|
||
|
||
`std.store.json` et `std.transport.json` utilisent déjà `mainnet-beta` comme identité réseau/cluster. Quelques exemples/tests de Backfill utilisent encore `RawNetworkId("mainnet")` comme valeur synthétique. Pour l'ingestion durable, la direction retenue est de conserver **`mainnet-beta` comme identité réseau canonique** et de réserver `mainnet` aux identifiants de profil/UI lorsque nécessaire. Aucune migration n'est effectuée en `pre.004`.
|
||
|
||
### 5.5 Interface passive
|
||
|
||
`ksp-interface-lib` possède `TransactionExecutionEvent` et `SlotLifecycleEvent`, utiles lorsque plusieurs producers/consumers partagent exactement ces faits passifs. Ils ne remplacent ni les DTOs Transport riches ni `RawTransaction`/`RawTransactionObservation` et ne doivent pas être utilisés comme conteneurs d'acquisition génériques.
|
||
|
||
## 6. Gaps préparatoires identifiés en pre.004
|
||
|
||
| ID | Owner futur | Gap / décision à matérialiser | Release cible | Motif |
|
||
|-------|-------------------------|---------------------------------------------------------------------------------------------------------------|-----------------|---------------------------------------------------------------------------------------------------------------------|
|
||
| TR-A | Transport | ajouter une voie observée pour `getBlock` si le scan bloc est admis en V1 | 0.3.10 | nécessaire pour provider/endpoint exacts dans `RawTransactionObservation` avec pool multi-endpoint |
|
||
| TR-B | Transport/ingest | définir l’extraction déterministe transaction-par-transaction depuis `SolanaConfirmedBlock` | 0.3.10 | le DTO bloc existe, la conversion RAW transactionnelle commune n’existe pas encore |
|
||
| RAW-A | Architecture/code owner | sortir la normalisation RAW v1 de l’enfermement Backfill sans duplication | 0.3.10 | la logique canonique actuelle vit dans `ksp-job-backfill-lib::conversion` |
|
||
| REC-A | Worker ingest | associer reconnect WS à une stratégie explicite de gap repair | 0.3.10 | resubscribe != replay ; `continuity_gap_count` n’identifie pas les transactions manquées |
|
||
| CFG-A | Config/composition | exprimer des rôles/capabilities d’acquisition, pas un simple enum HTTP/WS/gRPC | 0.3.10 | les profils existent déjà mais le rôle ingest multi-source n’est pas matérialisé |
|
||
| NET-A | Naming | retenir `mainnet-beta` comme identité réseau durable/configurée et `mainnet` seulement comme profile/UI alias | 0.3.10 / 0.3.12 | Store + Transport Config utilisent déjà `mainnet-beta`; quelques exemples/tests Backfill utilisent encore `mainnet` |
|
||
|
||
Ces gaps sont des entrées de handoff. `pre.004` ne les implémente pas.
|
||
|
||
## 7. Sources externes de l'audit daté
|
||
|
||
Consultées le 4 septembre 2026 :
|
||
|
||
| Source Solana | URL |
|
||
|-------------------------|-------------------------------------------------------------|
|
||
| getSignaturesForAddress | https://solana.com/docs/rpc/http/getsignaturesforaddress |
|
||
| getTransaction | https://solana.com/docs/rpc/http/gettransaction |
|
||
| getBlocks | https://solana.com/docs/rpc/http/getblocks |
|
||
| getBlocksWithLimit | https://solana.com/docs/rpc/http/getblockswithlimit |
|
||
| getBlock | https://solana.com/docs/rpc/http/getblock |
|
||
| getSlot | https://solana.com/docs/rpc/http/getslot |
|
||
| getFirstAvailableBlock | https://solana.com/docs/rpc/http/getfirstavailableblock |
|
||
| minimumLedgerSlot | https://solana.com/docs/rpc/http/minimumledgerslot |
|
||
| logsSubscribe | https://solana.com/docs/rpc/websocket/logssubscribe |
|
||
| signatureSubscribe | https://solana.com/docs/rpc/websocket/signaturesubscribe |
|
||
| blockSubscribe | https://solana.com/docs/rpc/websocket/blocksubscribe |
|
||
| slotSubscribe | https://solana.com/docs/rpc/websocket/slotsubscribe |
|
||
| slotsUpdatesSubscribe | https://solana.com/docs/rpc/websocket/slotsupdatessubscribe |
|
||
|
||
Les quotas, tiers provider et capacités Helius/Yellowstone ne sont volontairement pas documentés ici ; ils appartiennent à l'audit `pre.005`.
|
||
|
||
## 8. État après pre.004
|
||
|
||
Décisions fermées pour le standard Solana :
|
||
|
||
```text
|
||
HTTP address discovery + hydration = admis historique/catch-up/repair
|
||
HTTP block scan = admis sous gap de provenance observée
|
||
WS logsSubscribe = admis comme live discovery + hydration
|
||
WS signatureSubscribe = secondaire, signature déjà connue
|
||
WS blockSubscribe = admis sous capability explicite et instabilité
|
||
slot/ledger methods = auxiliaires de continuité
|
||
reconnect WS = jamais considéré comme replay
|
||
mainnet-beta = identité réseau canonique à préserver
|
||
```
|
||
|
||
Restent ouverts pour `pre.005`/`pre.006` : Helius, Yellowstone, autres providers, replay provider-specific, quotas/tier, stratégie multi-source V1 exacte et décision finale d'ownership du canonicalizer RAW.
|
||
|
||
## 9. Audit daté B — Helius, Yellowstone/providers et kbot3 historique
|
||
|
||
Audit effectué le **4 septembre 2026**. Cette tranche réaudite les capacités providers et le protocole Yellowstone avec sources primaires courantes. L'archive kbot3 fournie par l'opérateur est utilisée exclusivement comme référence fonctionnelle historique ; aucun code, DTO, URL d'endpoint, Config, secret, dependency ou convention de version n'est transféré.
|
||
|
||
### 9.1 Helius — surfaces et tiers courants
|
||
|
||
Depuis le 31 mars 2026, Helius indique que ses WebSockets standard et enhanced sont servis par l'infrastructure LaserStream. Cela améliore l'ingestion multi-nœuds, le failover et l'ordering côté provider, mais ne change pas le contrat filaire consommé par KSP : les méthodes WSS standard/enhanced n'exposent toujours pas de `from_slot` adressable comme Yellowstone gRPC.
|
||
|
||
| Surface | Réseau | Accès courant | Rôle RAW | Replay / continuité | Limites utiles auditées | Décision KSP |
|
||
|------------------------------|---------------------------------------|----------------------|---------------------------------------------|-------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------|
|
||
| RPC HTTP standard | Mainnet + Devnet | Free+ | history_discovery + hydration + gap_repair | aucun replay stream ; archive standard | RPC RPS 10 / 50 / 200 / 500 selon Free / Developer / Business / Professional | ADMIS ; réutilise les wrappers standard KSP |
|
||
| WSS standard LaserStream | Mainnet + Devnet | Free+ | rôles WS standard de pre.004 | failover/replay annoncés côté service ; pas de curseur replay KSP | 5 / 150 / 250 / 1 000 connexions ; 1 000 subscriptions/connexion | ADMIS ; gap repair explicite KSP conservé |
|
||
| WSS transactionSubscribe | Mainnet + Devnet | Developer+ | live_direct_full si transactionDetails=full | continuité provider-managed ; pas de from_slot WSS KSP | filtres include/exclude/required jusqu’à 50 000 adresses ; Developer annoncé jusqu’à 100 tx subscriptions/connexion | ADMIS spécialisé ; surface KSP déjà typée |
|
||
| LaserStream gRPC Yellowstone | Devnet Developer+ ; Mainnet Business+ | Developer+/Business+ | live_direct_full + gap_repair court | from_slot + replay explicite jusqu’à 24 h | 10 M pubkeys ; 10 connexions Business, 100 Professional | PRIORITAIRE pour V1 multi-source si Config l’active |
|
||
| getTransactionsForAddress | archive adressée | Developer+ | history_discovery + hydration combinées | pagination historique, pas stream | 100 crédits/appel ; 1 000 signatures ou 100 transactions full/page | SPÉCIALISÉ backfill 0.3.12 ; option 0.3.10 non nécessaire |
|
||
| Preconfirmations | signal leader partiel | Professional+ | signal ultra-précoce spécialisé | couverture partielle ; confirmation downstream obligatoire | 10 crédits/transaction ; filtres server-side | HORS RAW canonique V1 comme source autoritative |
|
||
| Parsed Streams | live confirmed décodé | plans payants, beta | flux sémantique provider-decoded | beta ; pas owner RAW | décodage provider de 3 600+ programmes annoncé | HORS RAW canonique V1 ; utile plus tard côté decode |
|
||
|
||
Les tarifs généraux Helius consultés affichent actuellement Free / Developer / Business / Professional à **$0 / $49 / $499 / $999** par mois, avec **10 / 50 / 200 / 500 RPC RPS**. Le trafic WSS et LaserStream est unifié à 20 crédits/MB. Ces valeurs sont des données d'audit datées et ne deviennent jamais des constantes KSP.
|
||
|
||
#### Replay WSS Helius : distinction provider/KSP
|
||
|
||
Helius annonce un replay de 24 heures et des reconnexions automatiques pour l'infrastructure LaserStream qui sous-tend désormais les WSS. KSP ne doit toutefois pas transformer cette annonce en garantie de protocole native :
|
||
|
||
```text
|
||
provider Helius WSS : continuité/failover/replay gérés par le service
|
||
protocole WSS KSP : aucun curseur from_slot ni fenêtre de replay explicitement demandable
|
||
conclusion KSP : conserver gap detection + repair explicite tant que le client ne peut pas adresser la plage manquée
|
||
```
|
||
|
||
Cette distinction empêche de déclarer une continuité vérifiable seulement parce qu'un provider annonce une infrastructure gapless.
|
||
|
||
#### transactionSubscribe
|
||
|
||
`transactionSubscribe` est une extension Helius et non une méthode Solana standard. Avec `transactionDetails=full`, la notification transporte un contenu transactionnel suffisamment riche pour être candidate `live_direct_full`, sans hydration HTTP obligatoire. Les filtres `accountInclude`, `accountExclude` et `accountRequired` acceptent jusqu'à 50 000 adresses selon la documentation Helius courante.
|
||
|
||
La surface KSP correspondante existe déjà dans `ksp-onchain-transport-lib` avec types/filtres dédiés et `HeliusLaserStreamWsSession::transaction_subscribe`. Aucune nouvelle API Transport n'est requise pour la recevoir en `0.3.10`; restent à définir la conversion RAW commune, la provenance ingest et la composition Config.
|
||
|
||
#### LaserStream gRPC
|
||
|
||
LaserStream gRPC est Yellowstone-compatible et documente explicitement `fromSlot` avec une rétention de replay jusqu'à 24 heures. C'est la première voie auditée qui combine :
|
||
|
||
```text
|
||
live transaction full
|
||
filters server-side
|
||
reconnect/replay adressable par slot
|
||
gap repair court sur le même protocole
|
||
provenance provider explicite
|
||
```
|
||
|
||
Le tier courant est Devnet à partir de Developer et Mainnet à partir de Business. KSP possède déjà le moteur Yellowstone générique ; `0.3.10` devra donc préférer une composition provider/capability plutôt qu'une deuxième implémentation Helius gRPC. Aucun endpoint Helius gRPC n'est ajouté en `0.3.9`.
|
||
|
||
#### getTransactionsForAddress
|
||
|
||
Helius propose aussi `getTransactionsForAddress`, qui combine discovery adressée et hydration avec tri ascendant/descendant, filtres temporels/slot/statut et pagination. La documentation annonce jusqu'à 1 000 signatures ou 100 transactions complètes par page, pour 100 crédits/appel, sur les plans payants.
|
||
|
||
Cette voie est principalement un candidat **Backfill `0.3.12`**. Elle ne doit pas remplacer la primitive standard `getSignaturesForAddress + getTransaction` dans l'architecture générique, mais peut devenir une stratégie provider spécialisée lorsque son coût/capability est explicitement sélectionné.
|
||
|
||
#### Signaux Helius non retenus comme RAW canonique V1
|
||
|
||
Deux surfaces actuelles sont enregistrées sans les promouvoir comme sources RAW autoritatives :
|
||
|
||
- **Preconfirmations** : signal après exécution locale du leader mais avant propagation/finalité ; couverture partielle et confirmation downstream obligatoire. Le flux transporte la transaction et le statut mais ne prouve pas que le bloc deviendra canonique. Il est complémentaire aux sources on-chain normales, pas leur remplacement.
|
||
- **Parsed Streams** : flux confirmed déjà décodé côté provider, en beta. Il est utile pour des couches de decode/analytics futures mais ne doit pas devenir la vérité RAW canonique, précisément parce que la sémantique est transformée par le provider.
|
||
|
||
### 9.2 Yellowstone upstream — sémantique du protocole
|
||
|
||
Le protobuf upstream courant expose dans `SubscribeRequest` les maps `transactions`, `transactions_status`, `blocks`, `blocks_meta`, `accounts`, `slots`, `entry`, ainsi qu'un `commitment`, un `ping` et un `from_slot` optionnel. La présence de `from_slot` prouve une primitive de protocole ; elle ne prouve pas la profondeur réelle de rétention d'un provider.
|
||
|
||
| Surface Yellowstone | Contenu | RAW complet | Filtres principaux | Rôle | Décision |
|
||
|---------------------|------------------------------------------------------|-----------------------------|-------------------------------------------------------------------------------------|----------------------------------|---------------------------------------------------------------------------------------|
|
||
| transactions | transaction + meta/execution | oui | vote/failed/signature/account include/exclude/required + extensions proto courantes | live_direct_full | source générique V1 privilégiée |
|
||
| transactions_status | signature + statut/erreur/index | non | mêmes familles de filtres transactionnels | live_discovery / targeted status | hydration requise si utilisée pour RAW |
|
||
| blocks | bloc assemblé + transactions optionnelles | oui si include_transactions | account_include + include_transactions/accounts/entries | live_direct_full par conteneur | utile pour couverture globale ; coût/volume supérieurs |
|
||
| blocks_meta | métadonnées de bloc | non | tous les blocs | gap_boundary / continuity | aucune persistence RawTransaction seule |
|
||
| from_slot | curseur de reprise | n/a | champ SubscribeRequest | gap_repair / catch-up court | capability à qualifier par provider et rétention réelle |
|
||
| SubscribeReplayInfo | first_available | n/a | unary | gap_boundary | permet de borner une rétention si le provider l’implémente |
|
||
| SubscribeDeshred | transaction pré-exécution sans TransactionStatusMeta | partiel | vote + accounts include/exclude/required | signal précoce spécialisé | proto/client exposés ; serveur OSS standard UNIMPLEMENTED, extension Triton seulement |
|
||
|
||
Les limites de filtres Yellowstone ne sont **pas des constantes universelles du protocole** : le serveur upstream permet de configurer des limites différentes, voire de ne pas appliquer certaines contraintes lorsque la section correspondante est absente. KSP doit donc découvrir/documenter les limites provider et garder ses propres bornes défensives.
|
||
|
||
Le changelog upstream du 22 juillet 2026 est également une alerte de conception : une régression avait accepté `from_slot` avec un filtre `blocks` tout en ne rejouant aucun bloc. La présence syntaxique du replay ne suffit donc jamais ; KSP doit caractériser la version/service provider et vérifier la reprise observée.
|
||
|
||
### 9.3 Replay provider par provider
|
||
|
||
| Provider / voie | Réseaux prouvés | Protocole | Replay explicite audité | Applicabilité | Conclusion |
|
||
|-------------------------|-------------------------------------------------|------------------------|-----------------------------------------------------------|-------------------------------|-------------------------------------------------------------------------------------|
|
||
| Helius LaserStream gRPC | Mainnet + Devnet selon tier | Yellowstone compatible | PROUVÉ : 24 h | live_direct_full + gap_repair | provider spécialisé du standard Yellowstone ; candidat V1 prioritaire |
|
||
| PublicNode Yellowstone | Mainnet + Testnet | Yellowstone gRPC | NON PROUVÉ par source officielle consultée | live_direct_full | alternative générique ; KSP possède déjà profils/smokes live, replay à caractériser |
|
||
| OrbitFlare Yellowstone | Devnet gratuit/Developer ; accès payant au-delà | Yellowstone gRPC | NON PROUVÉ explicitement dans docs Yellowstone consultées | live_direct_full | alternative générique ; archive HTTP complète comme complément repair/history |
|
||
| OrbitFlare archive HTTP | historique depuis genesis annoncé | Solana HTTP standard | n/a | history + gap_repair | complément historique fort, pas remplacement du live |
|
||
|
||
Pour **PublicNode**, la page Solana officielle du provider expose Mainnet/Testnet avec RPC, WS RPC, Yellowstone gRPC et archive disponible. Aucune source officielle consultée pendant cette tranche ne donne une profondeur `from_slot`, des limites de filtres ou une fenêtre de replay contractualisable. Les smokes KSP historiques prouvent le streaming live, pas le replay.
|
||
|
||
Pour **OrbitFlare**, la documentation Yellowstone expose transactions/slots/blocks/accounts/entries, filtres et keepalive. Le pricing courant donne gRPC Devnet sur Free/Developer, puis accès payant sur les tiers supérieurs. Les docs consultées ne matérialisent pas `fromSlot` dans le request de base et ne donnent pas de profondeur de replay ; cette capability reste donc **NON PROUVÉE** pour le provider. En revanche, OrbitFlare annonce une archive Solana complète depuis genesis via les méthodes HTTP standard, ce qui constitue un complément de repair/history indépendant du flux live.
|
||
|
||
### 9.4 État KSP face aux providers
|
||
|
||
L'inventaire `ksp-onchain-transport-lib` montre que les deux familles les plus importantes sont déjà présentes :
|
||
|
||
```text
|
||
Helius LaserStream WSS + transactionSubscribe -> surface provider-specific déjà typée
|
||
Yellowstone gRPC standard -> transactions/status/blocks/meta + from_slot + replay info
|
||
```
|
||
|
||
Le runtime Yellowstone KSP sait conserver la dernière requête, avancer `from_slot` à partir du plus haut slot observé, consulter/clamp la reprise au `first_available` et compter gaps/duplicates/replay. Cette mécanique est générique ; elle ne doit pas être transformée en garantie de lossless/exactly-once.
|
||
|
||
La conséquence architecturale pour `0.3.10` est de **réutiliser le moteur Yellowstone existant** pour Helius/PublicNode/OrbitFlare lorsque leur configuration le permet, avec des descriptors/capabilities provider-specific. Le Worker ingest ne doit pas brancher directement sur des SDK providers.
|
||
|
||
### 9.5 Audit fonctionnel historique de kbot3
|
||
|
||
L'archive kbot3 fournie a été inspectée uniquement pour identifier des comportements déjà utiles historiquement. Les constats pertinents sont :
|
||
|
||
| Domaine historique | Comportement observé | Propriété | Leçon KSP |
|
||
|--------------------|-----------------------------------------------------------------------|--------------------------------------|--------------------------------------------------------------------------------------------|
|
||
| Historique HTTP | `BackfillSource::ExplicitSignatures` ou `AddressHistory` before/after | discovery + hydration getTransaction | concept déjà refondé dans ksp-job-backfill-lib ; ne rien recopier |
|
||
| Pagination/reprise | page_size/max_pages + `resume_before_signature` + frontier contigu | reprise historique bornée | confirme l’intérêt d’un checkpoint de job, pas d’un Worker API commun |
|
||
| Hydration | client getTransaction sélectionné puis retries bornés | payload transaction canonique | faible failover dynamique : 0.3.10 doit préférer routing/capability multi-source explicite |
|
||
| Live WS | session persistante + standard subscriptions dont logsSubscribe | reconnect/resubscribe bornés | resubscribe sans replay explicite ; repair externe requis |
|
||
| Provenance | provider/endpoint/protocol/method/commitment/capture/filter | observation par acquisition | principe conservé par Store KSP ; aucun DTO historique repris |
|
||
| Fallback | pools HTTP/WS round-robin par rôle/capability | sélection initiale | utile comme référence fonctionnelle, insuffisant seul pour continuité multi-source V1 |
|
||
|
||
L'audit ne trouve pas de voie Yellowstone ou `transactionSubscribe` servant de fondation générique dans le chemin fonctionnel historique principal de kbot3. Il ne doit donc pas limiter les capabilities plus récentes déjà présentes dans KSP.
|
||
|
||
La leçon conservée est fonctionnelle seulement : séparer discovery/hydration, borner retries/concurrency, conserver une frontier de reprise contiguë pour les jobs historiques, maintenir une session live persistante, et enregistrer une provenance par acquisition. Les noms de types, structures, endpoints, secrets et implémentations de kbot3 ne sont pas réutilisés.
|
||
|
||
### 9.6 Relations entre les voies auditées
|
||
|
||
Les premières relations sont désormais suffisamment claires pour préparer la synthèse `pre.006` :
|
||
|
||
```text
|
||
Yellowstone transactions <-> Helius LaserStream gRPC : même famille protocolaire ; provider specialization
|
||
PublicNode Yellowstone <-> OrbitFlare Yellowstone : alternatives provider pour live direct full
|
||
Helius transactionSubscribe <-> Yellowstone tx : alternatives de transport, JSON spécialisé vs gRPC générique
|
||
standard logsSubscribe + getTransaction : alternative live discovery+hydration, plus coûteuse mais très portable
|
||
Yellowstone blocks / blockSubscribe : alternatives par conteneur bloc pour couverture globale
|
||
Helius gTFA / OrbitFlare archive / standard HTTP : stratégies historiques complémentaires ou alternatives pour Backfill
|
||
preconfirmations / deshred / parsed streams : spécialisations précoces ou sémantiques, pas vérité RAW V1
|
||
```
|
||
|
||
La sélection V1 exacte, les priorités/fallbacks et les règles de combinaison restent volontairement ouvertes jusqu'à `pre.006`.
|
||
|
||
### 9.7 Gaps supplémentaires ouverts en pre.005
|
||
|
||
| ID | Owner futur | Gap / décision | Cible | Motif |
|
||
|--------|--------------------|-----------------------------------------------------------------------------------------------------------------|--------|--------------------------------------------------------------------------------------------|
|
||
| TR-C | Transport/ingest | caractériser une observation RAW commune pour transactionSubscribe et Yellowstone transaction | 0.3.10 | les DTOs live diffèrent mais doivent converger vers le même contenu canonique |
|
||
| GRPC-A | Config/composition | déclarer provider/network/capabilities Yellowstone sans SDK ni protocole provider parallèle | 0.3.10 | le moteur gRPC KSP est déjà générique ; seule la composition doit sélectionner le provider |
|
||
| GRPC-B | Ingest | ne considérer from_slot comme gap repair que si replay + first_available sont réellement supportés/observés | 0.3.10 | capability protocolaire != garantie de rétention provider |
|
||
| WS-A | Ingest | conserver un repair externe pour WSS même chez Helius tant que le replay n’est pas adressable par le client KSP | 0.3.10 | continuité provider-managed non équivalente à reprise déterministe KSP |
|
||
| CFG-B | Config | réutiliser exclusivement KSP_SECRET_HELIUS_API_KEY pour toutes les surfaces Helius sélectionnées | 0.3.10 | aucun second secret Helius ne doit être créé |
|
||
| BF-A | Backfill | évaluer gTFA/archives provider comme stratégies spécialisées derrière capabilities historiques | 0.3.12 | optimiser le backfill sans contaminer le Worker live |
|
||
|
||
Aucun de ces gaps n'est implémenté en `pre.005`.
|
||
|
||
### 9.8 Sources externes de l'audit providers
|
||
|
||
Consultées le 4 septembre 2026 :
|
||
|
||
| Source | URL |
|
||
|------------------------------------|---------------------------------------------------------------------------------------------------|
|
||
| Helius — LaserStream WebSockets | https://www.helius.dev/blog/laserstream-websockets |
|
||
| Helius — RPC quickstart | https://www.helius.dev/docs/quickstart |
|
||
| Helius — WebSocket quickstart | https://www.helius.dev/docs/rpc/websocket/quickstart |
|
||
| Helius — pricing | https://www.helius.dev/pricing |
|
||
| Helius — rate limits | https://www.helius.dev/docs/billing/rate-limits |
|
||
| Helius — LaserStream gRPC | https://www.helius.dev/blog/introducing-laserstream |
|
||
| Helius — getTransactionsForAddress | https://www.helius.dev/blog/introducing-gettransactionsforaddress |
|
||
| Helius — Enhanced WebSockets | https://www.helius.dev/blog/introducing-next-generation-enhanced-websockets |
|
||
| Helius — Preconfirmations | https://www.helius.dev/blog/solana-preconfirmations |
|
||
| Helius — Parsed Streams | https://www.helius.dev/blog/parsed-events-and-streams |
|
||
| Yellowstone — protobuf | https://github.com/rpcpool/yellowstone-grpc/blob/master/yellowstone-grpc-proto/proto/geyser.proto |
|
||
| Yellowstone — README | https://github.com/rpcpool/yellowstone-grpc/blob/master/README.md |
|
||
| Yellowstone — changelog | https://github.com/rpcpool/yellowstone-grpc/blob/master/CHANGELOG.md |
|
||
| PublicNode — Solana | https://solana.publicnode.com/ |
|
||
| OrbitFlare — Yellowstone docs | https://docs.orbitflare.com/data-streaming/yellowstone |
|
||
| OrbitFlare — pricing | https://orbitflare.com/pricing |
|
||
| OrbitFlare — archive | https://orbitflare.com/products/historical-data |
|
||
| OrbitFlare — gRPC | https://orbitflare.com/products/solana-grpc |
|
||
|
||
Les URLs ci-dessus sont des **sources documentaires**. Aucun endpoint runtime provider n'est ajouté ou modifié dans KSP par cette tranche.
|
||
|
||
## 10. État après pre.005
|
||
|
||
Décisions fermées par l'audit B :
|
||
|
||
```text
|
||
Helius standard WSS = admis, continuité provider-managed mais repair KSP conservé
|
||
Helius transactionSubscribe = admis comme live_direct_full spécialisé
|
||
Helius LaserStream gRPC = admis comme Yellowstone provider + replay 24 h prouvé
|
||
Yellowstone transactions = source générique live_direct_full prioritaire
|
||
Yellowstone transaction_status = signal/status incomplet ; hydration requise pour RAW
|
||
Yellowstone blocks = direct full si transactions incluses
|
||
Yellowstone blocks_meta = continuité seulement
|
||
from_slot = capability à qualifier provider par provider
|
||
PublicNode replay = non prouvé par docs officielles consultées
|
||
OrbitFlare replay gRPC = non prouvé ; archive HTTP depuis genesis prouvée
|
||
kbot3 = référence fonctionnelle seulement, aucune source de code/Config
|
||
```
|
||
|
||
La synthèse `pre.006` doit maintenant convertir ces faits en matrice complète, stratégie multi-source V1, priorités/fallbacks et handoff exact `0.3.10` / `0.3.12`.
|
||
|