# Delta `0.2.3-pre.007` — `simulateTransaction` complet ## Base requise Livraison précédente corrigée et validée localement par l'opérateur : ```text 0.2.3-pre.006-fix.001 workspace.package.version = "0.2.3-pre.6.fix.1" ``` 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 175 unit tests 18 public API tests 12 release completeness tests 1 smoke Devnet ignored / opt-in 0 warning signalé par check/clippy ``` ## Objectif Activer la dernière méthode Transactions de `0.2.3` : ```text simulateTransaction ``` Après cette tranche : ```text 11 / 11 wrappers Transactions exécutés 8 Read / RetrySafe 2 WriteSubmission / NeverAfterDispatch 1 Simulation / RetrySafe ``` La tranche ne décode ni ne construit une transaction Solana et n'ajoute aucune dépendance codec/SDK. ## Version Cargo Conformément à `VER-ID-009` : ```text 0.2.3-pre.6.fix.1 -> 0.2.3-pre.7 ``` Le header du `Cargo.toml` passe de `version: 127` à `version: 128`. Aucune dépendance ni feature Cargo n'est ajoutée. ## Complétude `KSP-TRANSPORT-007` La page Solana RPC courante documente pour `simulateTransaction` : ```text transaction string commitment encoding = base58 | base64 replaceRecentBlockhash sigVerify minContextSlot innerInstructions accounts ``` La source primaire Agave `v4.2.1` confirme les mêmes champs dans `RpcSimulateTransactionConfig`, avec des booléens runtime par défaut à `false`. KSP expose donc la config complète via `SolanaSimulateTransactionConfig`. Les booléens restent `Option` côté KSP afin de distinguer l'omission de l'envoi explicite de `false` sans modifier la sémantique RPC. Les deux encodings de transaction réellement acceptés sont couverts : ```text base58 base64 ``` La transaction reste une chaîne opaque : Transport ne tente pas de reproduire le décodage, la désérialisation ou la sanitization Agave. ## Sous-config `accounts` Agave `v4.2.1` utilise `RpcSimulateTransactionAccountsConfig` avec : ```text encoding: Option addresses: Vec ``` La source runtime rejette explicitement les encodings Account legacy : ```text binary base58 ``` KSP accepte donc les variantes actuellement compatibles avec ce retour : ```text base64 base64+zstd jsonParsed ``` Ces trois variantes sont exercées par tests HTTP. `binary` et `base58` sont rejetées avant I/O avec `ERROR_CODE_INVALID_RPC_PARAMETERS`. Quand aucun encoding Account n'est fourni, KSP omet le champ et laisse le runtime appliquer son défaut `base64`. Agave borne dynamiquement le nombre d'adresses demandées au nombre de comptes contenu dans la transaction. Comme KSP ne décode pas la transaction dans cette release, cette limite reste volontairement côté runtime/provider au lieu d'introduire une validation partielle ou un codec transactionnel. ## Invariant `sigVerify` / `replaceRecentBlockhash` Agave `v4.2.1` refuse explicitement : ```text sigVerify = true replaceRecentBlockhash = true ``` avec l'erreur de paramètres indiquant que `sigVerify` ne peut pas être utilisé avec `replaceRecentBlockhash`. Cet invariant est déterministe et ne dépend pas du contenu encodé de la transaction. KSP le rejette donc avant toute sélection/exécution HTTP. ## Résultat riche et lossless `SolanaSimulateTransactionResult` devient le décodeur production du résultat contextualisé. Les champs courants Agave `v4.2.1` sont tous préservés : ```text err logs accounts unitsConsumed loadedAccountsDataSize returnData innerInstructions replacementBlockhash fee preBalances postBalances preTokenBalances postTokenBalances loadedAddresses ``` La page publique Solana résume seulement un sous-ensemble de ces champs. KSP conserve également les champs runtime supplémentaires afin de respecter `KSP-TRANSPORT-007` et de ne pas perdre de données disponibles. Les champs optionnels utilisent `SolanaWireField` lorsque l'absence, le `null` explicite et la valeur concrète doivent rester distinguables : ```text Omitted Null Value(T) ``` Les comptes retournés réutilisent `SolanaAccount` et conservent les `null` positionnels. Les sous-arbres Program/SPL riches (`returnData`, inner instructions, token balances, loaded addresses) restent lossless via `serde_json::Value` aux frontières déjà prévues, sans imposer les crates transaction-status à Transport. ## Retry de simulation Le descriptor existant reste : ```text RpcOperationKind::Simulation TransportRetryClass::RetrySafe ``` Contrairement à `requestAirdrop` et `sendTransaction`, la simulation n'est pas soumise à la règle no-resend d'une écriture : elle ne diffuse pas la transaction au cluster. Un test end-to-end exerce réellement : ```text simulate_transaction -> descriptor central -> execute_standard_rpc -> HTTP 503 -> retry central -> HTTP 200 -> résultat typé ``` Le test démontre donc que la classification `RetrySafe` est utilisée par le vrai chemin wrapper/executor et pas uniquement par une fonction pure de policy. ## Tests ajoutés Sept tests unitaires ajoutent : ```text config complète + résultat riche base58 + canonicalisation config vide base64 / base64+zstd / jsonParsed pour accounts rejet avant I/O du conflit sigVerify/replaceRecentBlockhash et de binary/base58 account encoding préservation omitted/null/value d'un résultat partiel préservation d'une erreur RPC applicative retry sûr après HTTP 503 puis succès ``` Un test public vérifie la disponibilité du wrapper et de la config complète à la racine de crate. Une canarie release vérifie la couverture finale exacte : ```text 8 Read / RetrySafe 2 WriteSubmission / NeverAfterDispatch 1 Simulation / RetrySafe 11 / 11 méthodes Transactions V0_2_3 ``` Résultat attendu après application : ```text 182 unit tests 19 public API tests 13 release completeness tests 1 smoke Devnet ignored / opt-in ``` ## Documentation synchronisée `crates/ksp-onchain-transport-lib/src/lib.rs` indique désormais que les 11 wrappers Transactions sont actifs après `pre.007`. `docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md` passe en version 6 et enregistre le résultat de la tranche. Le planning reste : ```text pre.008 audit rétroactif KSP-TRANSPORT-007 sur 0.2.1 -> 0.2.3 + remédiations éventuelles pre.009 clôture finale documentaire/validation/smoke/prompt 0.2.4 ``` `CHANGELOG.md` reste réservé à `0.2.3-rel.001`. ## Fichiers modifiés ```text Cargo.toml crates/ksp-onchain-transport-lib/src/lib.rs 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/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md ``` ## Fichiers ajoutés ```text crates/ksp-onchain-transport-lib/fixtures/http/simulate_transaction.success.json crates/ksp-onchain-transport-lib/fixtures/http/simulate_transaction.partial.json crates/ksp-onchain-transport-lib/fixtures/http/simulate_transaction.error.json deltas/0.2.3/pre.007.md ``` ## Dépendances Aucune dépendance ajoutée, supprimée ou modifiée. En particulier, restent absentes : ```text base64 direct dans Transport bs58 direct dans Transport wincode solana-client crate RPC SDK transaction-status client types ``` ## Validations à exécuter ```bash cargo fmt --all cargo check --workspace cargo clippy --workspace --all-targets cargo test -p ksp-onchain-transport-lib ``` Aucune commande n'est déclarée réussie sans exécution réelle ou preuve opérateur. ## Suite Après validation et commit attendu : ```text v0.2.3-pre.007 ``` passer à : ```text 0.2.3-pre.008 réaudit rétroactif KSP-TRANSPORT-007 sur les wrappers HTTP 0.2.1 -> 0.2.3 + remédiations éventuelles avant la clôture ```