190 lines
6.7 KiB
Markdown
190 lines
6.7 KiB
Markdown
<!-- file: deltas/0.2.7/pre.010.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `0.2.7-pre.010` — wrappers WebSocket stables lot B
|
|
|
|
## Base
|
|
|
|
Base requise :
|
|
|
|
```text
|
|
0.2.7-pre.009-fix.002
|
|
workspace.package.version = 0.2.7-pre.9.fix.2
|
|
```
|
|
|
|
Le checkpoint opérateur de cette base est entièrement vert : `cargo fmt --all`, audit Python KSP, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, 295 tests unitaires Transport, 33 tests d'API publique, 22 tests de release completeness puis `cargo test --workspace`.
|
|
|
|
Le canari ajouté par `pre.009-fix.002` pour une première connexion HTTP locale abandonnée passe dans le run Transport isolé comme dans le run workspace.
|
|
|
|
## Signal de version
|
|
|
|
```text
|
|
livraison = 0.2.7-pre.010
|
|
workspace.package.version = 0.2.7-pre.10
|
|
commit = v0.2.7-pre.010
|
|
tag = aucun
|
|
```
|
|
|
|
## Objectif
|
|
|
|
Compléter les six familles WebSocket standard non instables en ajoutant le lot B :
|
|
|
|
```text
|
|
signatureSubscribe / signatureUnsubscribe
|
|
slotSubscribe / slotUnsubscribe
|
|
rootSubscribe / rootUnsubscribe
|
|
```
|
|
|
|
Les trois familles unstable `block`, `slotsUpdates` et `vote` restent explicitement différées à `pre.011`.
|
|
|
|
## `signatureSubscribe`
|
|
|
|
Nouvelle configuration publique :
|
|
|
|
```text
|
|
SolanaSignatureSubscribeConfig
|
|
commitment
|
|
enable_received_notification
|
|
```
|
|
|
|
Les deux options sont indépendamment optionnelles. `enableReceivedNotification = false` explicite est préservé comme distinct de l'option omise ; un config explicitement vide est canonisé en absence du second paramètre.
|
|
|
|
Le résultat typed conserve les deux variantes wire actuelles :
|
|
|
|
```text
|
|
SolanaRpcResponse<SolanaSignatureNotification>
|
|
|
|
SolanaSignatureNotification::ReceivedSignature
|
|
SolanaSignatureNotification::Processed { err }
|
|
```
|
|
|
|
`ReceivedSignature` correspond au littéral wire `receivedSignature` et reste non terminal. `Processed { err }` est terminal ; `err = None` représente un succès et `err = Some(Value)` conserve sans interprétation locale le `TransactionError` wire.
|
|
|
|
Un littéral string inconnu ou un objet terminal sans champ `err` est rejeté comme `invalid_response` pour la subscription concernée, sans faire tomber une session physique autrement saine.
|
|
|
|
## Terminaison one-shot signature
|
|
|
|
Le serveur Solana annule automatiquement `signatureSubscribe` après la notification terminale. Le runtime KSP doit donc fermer le handle au même instant logique, sans envoyer d'unsubscribe redondant et surtout sans restaurer cette subscription après une reconnexion ultérieure.
|
|
|
|
Le moteur typed acquiert pour cela une classification interne :
|
|
|
|
```text
|
|
Delivered
|
|
DeliveredTerminal
|
|
ReceiverClosed
|
|
QueueFull
|
|
DecodeFailed
|
|
```
|
|
|
|
La notification terminale est d'abord insérée dans la queue typed, puis l'actor retire la subscription du registry et du mapping remote/local et publie `WsSubscriptionState::Closed` avec `terminal_error_code = None`.
|
|
|
|
Cette séquence garantit :
|
|
|
|
```text
|
|
consumer reçoit la valeur terminale
|
|
-> handle Closed
|
|
-> canal se ferme après la valeur déjà queueée
|
|
-> aucune signatureUnsubscribe automatique
|
|
-> aucune présence dans une sélection de resubscribe future
|
|
```
|
|
|
|
Une cancellation explicite avant la notification terminale conserve le chemin générique `WsSubscription::unsubscribe()` et émet `signatureUnsubscribe` avec le remote ID détenu uniquement par l'actor. Après la terminaison observée, `unsubscribe()` retourne `false` localement.
|
|
|
|
## `slotSubscribe`
|
|
|
|
Nouveau DTO public :
|
|
|
|
```text
|
|
SolanaSlotNotification
|
|
slot
|
|
parent
|
|
root
|
|
```
|
|
|
|
`WsSession::slot_subscribe()` n'accepte aucun paramètre et retourne :
|
|
|
|
```text
|
|
WsSubscription<SolanaSlotNotification>
|
|
```
|
|
|
|
La subscription est continue et utilise normalement reconnect, resubscribe, backpressure et cancellation.
|
|
|
|
## `rootSubscribe`
|
|
|
|
`WsSession::root_subscribe()` n'accepte aucun paramètre et retourne directement :
|
|
|
|
```text
|
|
WsSubscription<u64>
|
|
```
|
|
|
|
Le `u64` conserve le dernier root slot rapporté par `rootNotification`. La subscription est continue et son unsubscribe passe par le handle générique.
|
|
|
|
## Tests déterministes ajoutés
|
|
|
|
Cinq tests unitaires supplémentaires couvrent :
|
|
|
|
```text
|
|
signature config commitment + enableReceivedNotification omitted/false/true
|
|
signature decoder receivedSignature + succès terminal + erreur transactionnelle terminale
|
|
signature variants invalides -> invalid_response typed
|
|
signatureUnsubscribe exact avant terminaison
|
|
signature terminale -> valeur livrée puis Closed sans terminal_error_code
|
|
signature terminale -> aucun signatureUnsubscribe redondant
|
|
perte physique après signature terminale -> session reconnectée, aucune resubscription signature
|
|
slotNotification -> slot/parent/root exacts
|
|
slotSubscribe/rootSubscribe -> params vides et notifications typed exactes
|
|
slotUnsubscribe/rootUnsubscribe -> remote IDs internes via handles
|
|
```
|
|
|
|
Un canari d'API publique supplémentaire vérifie les trois nouvelles méthodes et les DTOs depuis la racine de crate.
|
|
|
|
Comptages attendus après compilation :
|
|
|
|
```text
|
|
Transport unit tests = 300
|
|
Transport public API tests = 34
|
|
release completeness = 22
|
|
```
|
|
|
|
## Sécurité / observabilité
|
|
|
|
Aucun remote subscription ID n'est ajouté à l'API publique. La signature fournie au wrapper n'est pas ajoutée aux logs de lifecycle. Le log de terminaison one-shot contient uniquement `session_id`, `subscription_id` local et `subscription_kind`.
|
|
|
|
La valeur `err` terminale reste accessible au consumer dans le DTO typed mais n'est jamais projetée dans `terminal_error_code`, car une transaction échouée reste une notification métier valide et non une erreur Transport.
|
|
|
|
## Fichiers ajoutés ou modifiés
|
|
|
|
```text
|
|
Cargo.toml
|
|
crates/ksp-onchain-transport-lib/README.md
|
|
crates/ksp-onchain-transport-lib/USAGE.md
|
|
crates/ksp-onchain-transport-lib/src/lib.rs
|
|
crates/ksp-onchain-transport-lib/src/ws_cluster.rs
|
|
crates/ksp-onchain-transport-lib/src/ws_session.rs
|
|
crates/ksp-onchain-transport-lib/src/ws_subscription.rs
|
|
crates/ksp-onchain-transport-lib/src/ws_transactions.rs
|
|
crates/ksp-onchain-transport-lib/tests/public_api.rs
|
|
crates/ksp-onchain-transport-lib/unit_tests/ws_cluster.rs
|
|
crates/ksp-onchain-transport-lib/unit_tests/ws_transactions.rs
|
|
docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md
|
|
docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
|
|
deltas/0.2.7/pre.010.md
|
|
```
|
|
|
|
`ROADMAP.md` et `CHANGELOG.md` restent inchangés pendant cette tranche.
|
|
|
|
## Validation opérateur requise
|
|
|
|
```bash
|
|
cargo fmt --all
|
|
python3 scripts/audit_rust_workspace_rules.py
|
|
cargo check --workspace
|
|
cargo clippy --workspace --all-targets
|
|
cargo test -p ksp-onchain-transport-lib
|
|
cargo test --workspace
|
|
```
|
|
|
|
## Tranche suivante
|
|
|
|
Si ce checkpoint est vert, `0.2.7-pre.011` ouvre les trois familles unstable : `blockSubscribe`, `slotsUpdatesSubscribe` et `voteSubscribe`, avec warnings centralisés, variantes wire évolutives et compliance `KSP-TRANSPORT-007`.
|