409 lines
10 KiB
Markdown
409 lines
10 KiB
Markdown
<!-- file: deltas/0.2.3/pre.005.md -->
|
||
<!-- version: 1 -->
|
||
|
||
# Delta `0.2.3-pre.005` — `getTransaction` complet, forme moderne et compatibilité legacy
|
||
|
||
## Base requise
|
||
|
||
Livraison précédente validée localement par l'opérateur :
|
||
|
||
```text
|
||
0.2.3-pre.004
|
||
workspace.package.version = "0.2.3-pre.4"
|
||
```
|
||
|
||
La validation opérateur du 2026-08-18 a confirmé :
|
||
|
||
```text
|
||
cargo fmt --all OK
|
||
cargo check --workspace OK
|
||
cargo clippy --workspace --all-targets OK
|
||
cargo test -p ksp-onchain-transport-lib OK
|
||
```
|
||
|
||
Résultats Transport de cette base :
|
||
|
||
```text
|
||
161 unit tests
|
||
16 public API tests
|
||
10 release completeness tests
|
||
0 warning signalé par check/clippy
|
||
```
|
||
|
||
## Objectif
|
||
|
||
Implémenter `getTransaction` comme huitième wrapper Transaction `Read / RetrySafe` de `0.2.3`, sans réduire la méthode à un sous-ensemble de
|
||
convenance.
|
||
|
||
La tranche couvre :
|
||
|
||
```text
|
||
forme moderne objet
|
||
forme bare encoding legacy dépréciée
|
||
commitment
|
||
encoding
|
||
maxSupportedTransactionVersion
|
||
result = null
|
||
transaction chaîne legacy
|
||
transaction tuple base58/base64
|
||
transaction JSON/jsonParsed
|
||
meta lossless
|
||
version legacy/numérique/omise/null
|
||
transactionIndex valeur/omission/null
|
||
erreurs RPC applicatives
|
||
```
|
||
|
||
Après cette tranche :
|
||
|
||
```text
|
||
8 / 11 wrappers Transactions exécutés
|
||
```
|
||
|
||
Restent différés :
|
||
|
||
```text
|
||
requestAirdrop
|
||
sendTransaction
|
||
simulateTransaction
|
||
```
|
||
|
||
## Règle générale de complétude RPC
|
||
|
||
La précision opérateur formulée avant cette tranche devient une règle durable : un wrapper de transport KSP n'est pas considéré complet lorsqu'il
|
||
n'expose qu'un sous-ensemble arbitraire des possibilités d'une méthode RPC.
|
||
|
||
`KSP-TRANSPORT-007` est ajouté dans `docs/rules/RULES_KSP.md` :
|
||
|
||
- tous les paramètres et champs de config audités doivent rester accessibles ;
|
||
- les variantes/overloads courants doivent être exposés ;
|
||
- les formes legacy encore supportées restent accessibles avec statut explicite ;
|
||
- les contraintes déterministes connues sont appliquées localement lorsque KSP peut le faire sans prendre une responsabilité wire étrangère ;
|
||
- les variantes, `null` et omissions significatives de réponse sont préservés ;
|
||
- un sous-arbre riche peut rester `serde_json::Value` lorsqu'il est conservé losslessly ;
|
||
- toute limitation volontaire doit être explicitement documentée.
|
||
|
||
`docs/architecture/003-COMPONENT_CONTRACTS.md` est synchronisé avec cette règle.
|
||
|
||
Le plan `docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md` passe en version 4 et demande désormais une canarie de complétude sémantique pour les
|
||
wrappers de la release, pas uniquement une canarie du nombre de méthodes.
|
||
|
||
## Version Cargo
|
||
|
||
Conformément à `VER-ID-009` :
|
||
|
||
```text
|
||
0.2.3-pre.4 -> 0.2.3-pre.5
|
||
```
|
||
|
||
Aucune dépendance ni feature Cargo n'est ajoutée.
|
||
|
||
## Surface moderne `getTransaction`
|
||
|
||
API publique :
|
||
|
||
```text
|
||
HttpTransportPool::get_transaction(
|
||
role,
|
||
signature,
|
||
Option<&SolanaGetTransactionConfig>,
|
||
)
|
||
-> Result<Option<SolanaConfirmedTransaction>>
|
||
```
|
||
|
||
La signature reste une chaîne base58 opaque pour Transport : KSP ne prend pas de dépendance `solana-signature` uniquement pour répliquer la
|
||
validation du provider.
|
||
|
||
Le second paramètre possède trois usages intentionnels :
|
||
|
||
```text
|
||
None -> second paramètre omis
|
||
Some(default config) -> objet moderne explicite {}
|
||
Some(config) -> objet moderne avec tous les champs fournis
|
||
```
|
||
|
||
Cette distinction permet d'exposer réellement la forme objet moderne sans empêcher la forme sans second paramètre.
|
||
|
||
`SolanaGetTransactionConfig` conserve :
|
||
|
||
```text
|
||
commitment
|
||
encoding
|
||
maxSupportedTransactionVersion
|
||
```
|
||
|
||
La documentation publique courante borne `commitment` à :
|
||
|
||
```text
|
||
confirmed
|
||
finalized
|
||
```
|
||
|
||
`processed` est donc rejeté localement avec `ERROR_CODE_INVALID_RPC_PARAMETERS` avant I/O.
|
||
|
||
`maxSupportedTransactionVersion` reste un `Option<u8>` plutôt qu'une constante figée à `0`, afin de ne pas fermer la surface KSP aux futures
|
||
versions wire que le runtime pourra supporter.
|
||
|
||
## Encodings complets
|
||
|
||
La documentation publique moderne expose :
|
||
|
||
```text
|
||
base58
|
||
base64
|
||
json
|
||
jsonParsed
|
||
```
|
||
|
||
Agave `v4.2.1` utilise encore `UiTransactionEncoding` pour `RpcTransactionConfig` et accepte également l'alias historique :
|
||
|
||
```text
|
||
binary
|
||
```
|
||
|
||
KSP conserve donc les cinq labels dans `SolanaTransactionEncoding` :
|
||
|
||
```text
|
||
Binary
|
||
Base58
|
||
Base64
|
||
Json
|
||
JsonParsed
|
||
```
|
||
|
||
`Binary` est une compatibilité runtime/legacy et n'est pas présenté comme le choix moderne recommandé.
|
||
|
||
Les cinq labels sont exercés par le wrapper moderne afin de garantir que KSP ne filtre pas une possibilité supportée par le runtime ciblé.
|
||
|
||
## Forme legacy bare encoding
|
||
|
||
La documentation Solana courante conserve :
|
||
|
||
```text
|
||
getTransaction(signature, "<encoding>")
|
||
```
|
||
|
||
mais marque explicitement cette forme bare comme dépréciée.
|
||
|
||
KSP expose donc séparément :
|
||
|
||
```text
|
||
HttpTransportPool::get_transaction_legacy(role, signature, encoding)
|
||
```
|
||
|
||
Cette API :
|
||
|
||
- est annotée `#[deprecated]` côté Rust ;
|
||
- émet un `warn` via `ksp-logging-lib` lorsqu'elle est appelée ;
|
||
- sérialise exactement la chaîne d'encoding comme second paramètre ;
|
||
- accepte les cinq labels du runtime `v4.2.1` ;
|
||
- réutilise exactement le même executor/décodeur que la forme moderne.
|
||
|
||
Le wrapper legacy ne crée donc ni nouveau client HTTP ni logique de retry parallèle.
|
||
|
||
## Réponse complète et lossless
|
||
|
||
`getTransaction` renvoie :
|
||
|
||
```text
|
||
Option<SolanaConfirmedTransaction>
|
||
```
|
||
|
||
`result = null` devient `None` sans être confondu avec une erreur RPC.
|
||
|
||
Un résultat présent conserve :
|
||
|
||
```text
|
||
slot
|
||
blockTime
|
||
transaction
|
||
meta
|
||
version
|
||
transactionIndex
|
||
```
|
||
|
||
### Transaction
|
||
|
||
`SolanaEncodedTransaction` devient production-live et conserve les formes Agave :
|
||
|
||
```text
|
||
LegacyBinary(String)
|
||
Binary { data, Base58|Base64 }
|
||
Json(serde_json::Value)
|
||
```
|
||
|
||
La variante `Json` couvre `json` et `jsonParsed` sans réimplémenter les structures Program-specific du SDK Solana. Aucun champ n'est supprimé.
|
||
|
||
### Metadata
|
||
|
||
`meta` reste :
|
||
|
||
```text
|
||
SolanaWireField<serde_json::Value>
|
||
```
|
||
|
||
Cette représentation conserve :
|
||
|
||
```text
|
||
Omitted
|
||
Null
|
||
Value(object)
|
||
```
|
||
|
||
La fixture riche couvre notamment les champs actuels :
|
||
|
||
```text
|
||
err
|
||
status legacy
|
||
fee
|
||
preBalances
|
||
postBalances
|
||
innerInstructions
|
||
logMessages
|
||
preTokenBalances
|
||
postTokenBalances
|
||
rewards
|
||
loadedAddresses
|
||
returnData
|
||
computeUnitsConsumed
|
||
costUnits
|
||
```
|
||
|
||
Le choix lossless permet aussi de transporter de nouveaux champs provider/Agave sans les effacer avant qu'un modèle KSP plus spécialisé soit
|
||
justifié.
|
||
|
||
### Version et transaction index
|
||
|
||
`version` conserve :
|
||
|
||
```text
|
||
Omitted
|
||
Null
|
||
Legacy
|
||
Number(u8)
|
||
```
|
||
|
||
`transactionIndex`, présent dans Agave `v4.2.1` mais pas historiquement chez tous les providers, conserve également :
|
||
|
||
```text
|
||
Omitted
|
||
Null
|
||
Value(u32)
|
||
```
|
||
|
||
Les fixtures préparatoires de `pre.002` qui vérifient déjà ces trois états restent actives.
|
||
|
||
## Helpers activés en production
|
||
|
||
Seuls les helpers nécessaires à `getTransaction` quittent `#[cfg(test)]` :
|
||
|
||
```text
|
||
SolanaTransactionBinaryEncoding::from_wire
|
||
SolanaGetTransactionConfig::to_json_value
|
||
SolanaEncodedTransaction::decode_wire
|
||
SolanaTransactionVersion::decode_wire
|
||
SolanaConfirmedTransaction::decode_wire
|
||
decode_binary_transaction_tuple
|
||
decode_transaction_version_field
|
||
WireConfirmedTransaction
|
||
```
|
||
|
||
Les helpers write/simulation de `pre.006`–`pre.007` restent staged/test-only. Aucun `#[allow(dead_code)]` global n'est ajouté.
|
||
|
||
## Fixtures HTTP déterministes ajoutées
|
||
|
||
```text
|
||
get_transaction.null.json
|
||
get_transaction.binary_legacy.json
|
||
get_transaction.base58.json
|
||
get_transaction.base64.json
|
||
get_transaction.json.json
|
||
get_transaction.json_parsed.json
|
||
get_transaction.error_unsupported_version.json
|
||
```
|
||
|
||
Elles couvrent les formes de résultat et les encodings sans décoder les bytes transactionnels.
|
||
|
||
## Couverture de tests ajoutée
|
||
|
||
Sept tests unitaires HTTP supplémentaires couvrent :
|
||
|
||
- second paramètre omis et objet moderne vide explicite ;
|
||
- config moderne complète ;
|
||
- rejet local de `commitment=processed` ;
|
||
- cinq encodings runtime via la forme moderne ;
|
||
- cinq encodings via la forme bare legacy dépréciée ;
|
||
- préservation d'un `jsonParsed` riche ;
|
||
- préservation du JSON brut, du meta courant, de la version et de `transactionIndex` ;
|
||
- erreur RPC `unsupported transaction version` préservée comme `RPC_APPLICATION_ERROR`.
|
||
|
||
Les tests préparatoires existants continuent en plus à couvrir :
|
||
|
||
- tuple avec encoding non binaire rejeté ;
|
||
- forme de version inconnue rejetée ;
|
||
- `meta/version/transactionIndex` omis/null/présents.
|
||
|
||
Un test public compile les deux request forms depuis la crate root.
|
||
|
||
Une nouvelle canarie release porte le sous-ensemble Read Transaction exécuté à huit méthodes et vérifie que `getTransaction` conserve
|
||
`StableWithDeprecatedLegacy` :
|
||
|
||
```text
|
||
getFeeForMessage
|
||
getLatestBlockhash
|
||
getRecentPrioritizationFees
|
||
getSignaturesForAddress
|
||
getSignatureStatuses
|
||
getTransaction
|
||
getTransactionCount
|
||
isBlockhashValid
|
||
```
|
||
|
||
Les trois opérations write/simulation restent différées.
|
||
|
||
Après application, la cible Transport attendue devient :
|
||
|
||
```text
|
||
168 unit tests
|
||
17 public API tests
|
||
11 release completeness tests
|
||
```
|
||
|
||
## Fichiers modifiés
|
||
|
||
```text
|
||
Cargo.toml
|
||
crates/ksp-onchain-transport-lib/src/rpc_transactions.rs
|
||
crates/ksp-onchain-transport-lib/unit_tests/rpc_transactions.rs
|
||
crates/ksp-onchain-transport-lib/tests/public_api.rs
|
||
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
|
||
docs/rules/RULES_KSP.md
|
||
docs/architecture/003-COMPONENT_CONTRACTS.md
|
||
docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md
|
||
```
|
||
|
||
Fichiers ajoutés :
|
||
|
||
```text
|
||
crates/ksp-onchain-transport-lib/fixtures/http/get_transaction.null.json
|
||
crates/ksp-onchain-transport-lib/fixtures/http/get_transaction.binary_legacy.json
|
||
crates/ksp-onchain-transport-lib/fixtures/http/get_transaction.base58.json
|
||
crates/ksp-onchain-transport-lib/fixtures/http/get_transaction.base64.json
|
||
crates/ksp-onchain-transport-lib/fixtures/http/get_transaction.json.json
|
||
crates/ksp-onchain-transport-lib/fixtures/http/get_transaction.json_parsed.json
|
||
crates/ksp-onchain-transport-lib/fixtures/http/get_transaction.error_unsupported_version.json
|
||
deltas/0.2.3/pre.005.md
|
||
```
|
||
|
||
`CHANGELOG.md`, `ROADMAP.md`, `rpc_method.rs`, `executor.rs` et `resilience.rs` restent inchangés.
|
||
|
||
## Validations attendues
|
||
|
||
```bash
|
||
cargo fmt --all
|
||
cargo check --workspace
|
||
cargo clippy --workspace --all-targets
|
||
cargo test -p ksp-onchain-transport-lib
|
||
```
|
||
|
||
L'environnement de préparation du delta ne possède pas Cargo/Rustfmt ; ces commandes ne sont donc pas déclarées réussies avant preuve opérateur.
|