# Delta `0.2.3-pre.006` — `requestAirdrop` + `sendTransaction` et preuve no-resend ## Base requise Livraison précédente validée localement par l'opérateur : ```text 0.2.3-pre.005 workspace.package.version = "0.2.3-pre.5" ``` 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 168 unit tests 17 public API tests 11 release completeness tests 0 warning signalé par check/clippy ``` ## Objectif Activer les deux écritures de la famille Transactions : ```text requestAirdrop sendTransaction ``` Les deux wrappers restent attachés aux descriptors centraux déjà audités : ```text RpcOperationKind::WriteSubmission TransportRetryClass::NeverAfterDispatch ``` Après cette tranche : ```text 10 / 11 wrappers Transactions exécutés 8 Read 2 WriteSubmission 1 Simulation encore différée ``` `simulateTransaction` reste réservée à `pre.007`. ## Version Cargo Conformément à `VER-ID-009` : ```text 0.2.3-pre.5 -> 0.2.3-pre.6 ``` Aucune dépendance ni feature Cargo n'est ajoutée. ## Complétude `requestAirdrop` API publique : ```text HttpTransportPool::request_airdrop( role, recipient: &Pubkey, lamports: u64, Option<&SolanaRequestAirdropConfig>, ) -> Result ``` La page publique Solana courante documente `commitment` dans l'objet de config. La source primaire Agave `v4.2.1` conserve en plus : ```text recentBlockhash: Option ``` KSP l'expose donc conformément à `KSP-TRANSPORT-007` au lieu de réduire la surface au seul exemple/document public visible. Le résultat reste la signature de transaction retournée par le faucet sous forme de chaîne wire. Transport ne prend pas une dépendance Signature uniquement pour redécoder une valeur que le provider vient de produire. Une config vide est canonicalisée vers l'omission du troisième paramètre, syntaxe strictement équivalente autorisée par `KSP-TRANSPORT-007`. ## Complétude `sendTransaction` API publique : ```text HttpTransportPool::send_transaction( role, transaction: &str, Option<&SolanaSendTransactionConfig>, ) -> Result ``` Transport reçoit une transaction déjà construite, signée et encodée. Il ne la décode, ne la signe et ne la modifie pas. La config expose la surface courante complète : ```text encoding Base58 | Base64 skipPreflight Option preflightCommitment Option maxRetries Option minContextSlot Option ``` Les deux encodings binaires sont exercés par fixtures HTTP locales. Une config vide est canonicalisée vers l'omission du second paramètre. ### Distinction impérative des retries ```text SolanaSendTransactionConfig.maxRetries = retransmissions node-side après acceptation RPC HttpRetrySettings = retries HTTP Transport KSP ``` Le premier champ n'accorde aucune permission de resoumission HTTP au wrapper. ## Preuves end-to-end de no-resend Les tests ne se limitent pas à `evaluate_transport_retry`. Ils exercent réellement : ```text wrapper typed -> descriptor central -> execute_standard_rpc -> client HTTP fixture ``` Pour **chacun** de `requestAirdrop` et `sendTransaction`, un serveur local compte les requêtes reçues. Cas ambigus après dispatch : ```text HTTP 429 -> erreur rate_limited -> compteur = 1 HTTP 503 -> erreur http_request_failed -> compteur = 1 timeout -> erreur timeout -> compteur = 1 ``` Même avec plusieurs retries configurés dans `HttpRetrySettings`, aucune seconde soumission n'est émise après ces trois états ambigus. Cas explicitement sûr : ```text connexion refusée -> ERROR_CODE_HTTP_CONNECTION_FAILED -> NotDispatched ``` Avec deux endpoints de même priorité, la première tentative échoue avant dispatch et le retry central peut atteindre le second endpoint. Cette preuve est exercée séparément pour les deux wrappers. ## Erreurs RPC applicatives Les fixtures couvrent aussi : - une erreur `requestAirdrop` de paramètres/blockhash ; - une erreur `sendTransaction` de preflight/simulation. Ces réponses restent `ERROR_CODE_RPC_APPLICATION_ERROR` et ne deviennent jamais des retries transport. ## `KSP-TRANSPORT-007` rétroactif La question opérateur sur les wrappers antérieurs est enregistrée dans le plan `010`. Les audits `0.2.1`/`0.2.2` avaient déjà recherché la surface complète. Un contrôle ciblé pendant cette tranche confirme notamment l'alignement KSP avec Agave `v4.2.1` pour : ```text RpcAccountInfoConfig RpcProgramAccountsConfig RpcLargestAccountsConfig RpcLeaderScheduleConfig RpcGetVoteAccountsConfig ``` Mais la règle n'était pas encore un critère de clôture nommé. La prévision devient donc : ```text pre.007 simulateTransaction complet pre.008 audit rétroactif KSP-TRANSPORT-007 sur 0.2.1 -> 0.2.3 + corrections éventuelles pre.009 clôture finale documentaire/validation/smoke/prompt 0.2.4 ``` Cette tranche supplémentaire évite de transformer la clôture en remédiation fonctionnelle tardive. ## Documentation/source synchronisée `crates/ksp-onchain-transport-lib/src/lib.rs` est corrigé pour refléter la surface réellement disponible après `pre.006` : ```text 8 reads Transactions 2 write submissions simulateTransaction encore staged ``` Le plan `docs/plans/010-V0_2_3_HTTP_TRANSACTIONS_PLAN.md` passe en version 5 et enregistre le nouveau découpage jusqu'à `pre.009`. `CHANGELOG.md` reste réservé à `0.2.3-rel.001`. ## Tests ajoutés Sept tests unitaires couvrent : ```text requestAirdrop config complète + canonicalisation config vide sendTransaction config complète + base58/base64 + config vide erreurs RPC applicatives des deux writes no-resend après HTTP 429 pour les deux writes no-resend après HTTP 503 pour les deux writes no-resend après timeout ambigu pour les deux writes retry/fallback autorisé après connexion NotDispatched pour les deux writes ``` Un test public vérifie la disponibilité des deux wrappers/configs à la racine de crate. Une canarie release vérifie le sous-ensemble `pre.006` : ```text 8 Read / RetrySafe 2 WriteSubmission / NeverAfterDispatch simulateTransaction encore différée ``` Cible après application : ```text 175 unit tests 18 public API tests 12 release completeness tests ``` ## Fichiers du delta 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 ``` Ajoutés : ```text crates/ksp-onchain-transport-lib/fixtures/http/request_airdrop.success.json crates/ksp-onchain-transport-lib/fixtures/http/request_airdrop.error.json crates/ksp-onchain-transport-lib/fixtures/http/send_transaction.success.json crates/ksp-onchain-transport-lib/fixtures/http/send_transaction.preflight_error.json deltas/0.2.3/pre.006.md ``` ## Validations attendues opérateur ```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. Aucune de ces commandes n'est donc déclarée réussie avant preuve opérateur.