Files
khadhroony-solana-project/deltas/0.2.2/pre.004.md
2026-08-18 08:09:20 +02:00

325 lines
11 KiB
Markdown

<!-- file: deltas/0.2.2/pre.004.md -->
<!-- version: 1 -->
# Delta `0.2.2-pre.004` — cinq wrappers HTTP Tokens typés
## Base requise
Livraison précédente corrigée et validée localement par l'opérateur :
```text
0.2.2-pre.003-fix.001
workspace.package.version = "0.2.2-pre.3.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
98 unit tests
10 public API tests
3 release completeness tests
0 warning signalé par check/clippy
```
Le plan canonique reste `docs/plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md` version 3.
## Objectif
Clôturer la famille Tokens attribuée à `0.2.2` avec cinq wrappers publics typés :
```text
getTokenAccountBalance
getTokenAccountsByDelegate
getTokenAccountsByOwner
getTokenLargestAccounts
getTokenSupply
```
Tous passent par la foundation HTTP commune :
```text
wrapper typé
-> descriptor audité
-> execute_standard_rpc
-> pool/admission/retry/deadline
-> reqwest HTTP
-> JSON-RPC validation
-> décodage DTO KSP
```
Aucun wrapper Token ne contacte `reqwest` directement et aucune crate SPL n'est ajoutée.
## Version Cargo
Conformément à `VER-ID-009` :
```text
0.2.2-pre.3.fix.1 -> 0.2.2-pre.4
```
Aucune dépendance ni feature Cargo n'est ajoutée ou retirée.
## Réaudit ciblé du contrat courant
Les pages RPC Solana courantes ont été revérifiées le 2026-08-18 pour cette tranche :
```text
https://solana.com/docs/rpc/http/gettokenaccountbalance
https://solana.com/docs/rpc/http/gettokenaccountsbydelegate
https://solana.com/docs/rpc/http/gettokenaccountsbyowner
https://solana.com/docs/rpc/http/gettokenlargestaccounts
https://solana.com/docs/rpc/http/gettokensupply
```
Le contrat reste cohérent avec le plan `009` :
- `getTokenAccountBalance`, `getTokenLargestAccounts` et `getTokenSupply` acceptent un `commitment` optionnel ;
- `getTokenAccountsByDelegate` et `getTokenAccountsByOwner` prennent un selector exclusif `{mint}` ou `{programId}` puis une config Account optionnelle ;
- les cinq réponses sont contextualisées ;
- les deux méthodes de liste renvoient des `pubkey + account` et réutilisent donc le DTO Account générique ;
- `TokenAmount.uiAmount` reste nullable ; `uiAmountString` reste la représentation textuelle à préserver ;
- `getTokenLargestAccounts` renvoie les 20 plus gros token accounts côté RPC, sans que KSP invente un tri supplémentaire.
Le réaudit complémentaire Agave `v4.2.1` déjà fixé en `pre.001-fix.001` reste la référence d'implémentation ciblée ; aucune divergence
nouvelle nécessitant un changement de DTO n'a été identifiée pour cette tranche.
## Surface typée Tokens
### `getTokenAccountBalance`
Signature publique conceptuelle :
```text
role + token account Pubkey + Option<SolanaCommitmentConfig>
-> SolanaRpcResponse<SolanaTokenAmount>
```
Le wrapper préserve `amount`, `decimals`, `uiAmount` nullable et `uiAmountString`, et conserve une erreur JSON-RPC distante comme erreur
applicative RPC.
### `getTokenAccountsByDelegate`
Signature publique conceptuelle :
```text
role + delegate Pubkey + SolanaTokenAccountSelector + Option<SolanaAccountInfoConfig>
-> SolanaRpcResponse<Vec<SolanaKeyedAccount>>
```
Le selector KSP empêche par construction les objets contenant simultanément `mint` et `programId`. La config Account réutilise les encodings,
`dataSlice`, `commitment` et `minContextSlot` activés en `pre.003`.
### `getTokenAccountsByOwner`
Signature publique conceptuelle :
```text
role + owner Pubkey + SolanaTokenAccountSelector + Option<SolanaAccountInfoConfig>
-> SolanaRpcResponse<Vec<SolanaKeyedAccount>>
```
Le wrapper partage le même chemin privé de sérialisation/décodage que la variante Delegate afin d'éviter deux implémentations de wire parallèles.
Un config Account explicitement vide est omis du tableau `params`.
### `getTokenLargestAccounts`
Signature publique conceptuelle :
```text
role + mint Pubkey + Option<SolanaCommitmentConfig>
-> SolanaRpcResponse<Vec<SolanaTokenAccountBalance>>
```
L'ordre retourné par le serveur est conservé. Chaque `address` est validée et convertie en `ksp_core_lib::Pubkey` sans recopier une valeur wire
invalide dans le diagnostic.
### `getTokenSupply`
Signature publique conceptuelle :
```text
role + mint Pubkey + Option<SolanaCommitmentConfig>
-> SolanaRpcResponse<SolanaTokenAmount>
```
`amount` reste une chaîne exacte et KSP ne convertit pas la supply en type métier SPL ni en entier borné localement.
## Mutualisation activée en production
Les helpers Token préparés en `pre.002` deviennent production-live uniquement parce qu'ils ont maintenant des consommateurs runtime réels :
- sérialisation de `SolanaTokenAccountSelector` ;
- décodage `SolanaTokenAmount` ;
- décodage `SolanaTokenAccountBalance` ;
- wire structs Token privés.
`SolanaAccountInfoConfig::is_empty` devient `pub(crate)` pour permettre aux deux wrappers de liste Token de réutiliser la règle d'omission de
config vide déjà utilisée par Accounts. Cette modification reste interne à la crate et n'élargit pas l'API publique externe.
Les helpers Cluster préparatoires restent inchangés et ne deviennent pas production-live avant `pre.005`/`pre.006`.
## Validation locale des paramètres
Aucun nouveau code d'erreur local n'est nécessaire dans cette tranche :
- le selector `Mint | ProgramId` garantit exactement une variante par construction ;
- les owner/delegate/mint/token-account sont des `Pubkey` typées avant l'appel ;
- les configs Account/Commitment réutilisent les types déjà validés ;
- aucune cardinalité supplémentaire documentée ne doit être imposée côté client.
`ERROR_CODE_INVALID_RPC_PARAMETERS` introduit en `pre.003` reste inchangé.
## Fixtures HTTP déterministes ajoutées
```text
crates/ksp-onchain-transport-lib/fixtures/http/get_token_account_balance.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_account_balance.error.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_accounts_by_delegate.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_accounts_by_owner.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_accounts_by_owner.invalid_pubkey.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_largest_accounts.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_largest_accounts.invalid_address.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_supply.success.json
```
Les tests utilisent un serveur HTTP loopback et n'accèdent pas à Internet.
## Couverture de tests ajoutée
Les tests Token couvrent notamment :
- request exacte de chacune des cinq méthodes ;
- selector `programId` pour Delegate ;
- selector `mint` pour Owner ;
- config Account complète et omission d'un config explicitement vide ;
- commitment optionnel ;
- `uiAmount: null` ;
- montant/supply textuel exact ;
- conservation de l'ordre pour `getTokenLargestAccounts` ;
- décodage `jsonParsed` des accounts sous forme JSON opaque Transport ;
- erreur JSON-RPC applicative ;
- rejet d'une `pubkey` ou `address` invalide dans une réponse typée.
Le test public compile explicitement les cinq méthodes depuis `HttpTransportPool`.
Un canari release fige l'ensemble Tokens `0.2.2` exact :
```text
getTokenAccountBalance
getTokenAccountsByDelegate
getTokenAccountsByOwner
getTokenLargestAccounts
getTokenSupply
```
Il vérifie également `Read + RetrySafe` pour chacun. Les 12 wrappers Cluster restent hors de cette tranche.
Après application, la cible Transport attendue devient :
```text
106 unit tests
11 public API tests
4 release completeness tests
```
## Fichiers ajoutés
```text
crates/ksp-onchain-transport-lib/fixtures/http/get_token_account_balance.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_account_balance.error.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_accounts_by_delegate.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_accounts_by_owner.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_accounts_by_owner.invalid_pubkey.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_largest_accounts.success.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_largest_accounts.invalid_address.json
crates/ksp-onchain-transport-lib/fixtures/http/get_token_supply.success.json
deltas/0.2.2/pre.004.md
```
## Fichiers modifiés
```text
Cargo.toml
crates/ksp-onchain-transport-lib/src/lib.rs
crates/ksp-onchain-transport-lib/src/rpc_accounts.rs
crates/ksp-onchain-transport-lib/src/rpc_tokens.rs
crates/ksp-onchain-transport-lib/unit_tests/rpc_tokens.rs
crates/ksp-onchain-transport-lib/tests/public_api.rs
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
```
## Fichiers supprimés
Aucun.
## Fichiers volontairement inchangés
```text
deltas/0.2.2/pre.003.md
deltas/0.2.2/pre.003-fix.001.md
docs/plans/009-V0_2_2_HTTP_ACCOUNTS_TOKENS_CLUSTER_PLAN.md
ROADMAP.md
CHANGELOG.md
crates/ksp-onchain-transport-lib/src/rpc_common.rs
crates/ksp-onchain-transport-lib/src/rpc_cluster.rs
crates/ksp-onchain-transport-lib/src/rpc_method.rs
crates/ksp-config-lib/**
config/**
```
Les deltas déjà publiés restent des traces historiques et ne sont pas réécrits.
## Contrôles statiques effectués pendant la préparation
- `workspace.package.version` vaut `0.2.2-pre.4` ;
- les huit nouvelles fixtures JSON sont syntaxiquement valides ;
- les cinq wrappers utilisent `execute_standard_rpc` ;
- aucun `reqwest` direct n'est ajouté dans `rpc_tokens.rs` ;
- aucun `#[allow(dead_code)]` ou suppression de lint n'est ajouté ;
- aucun helper Cluster n'est activé en production ;
- aucune dépendance ou feature Cargo n'est ajoutée ;
- aucune crate SPL n'est importée ;
- la surface publique Accounts de `pre.003` reste présente ;
- les deltas historiques restent inchangés.
## Validations Rust non exécutées dans le sandbox
Le sandbox de préparation ne fournit pas la toolchain Cargo utilisée par le checkout opérateur. Les commandes suivantes doivent donc être rejouées
après application :
```bash
cargo fmt --all
cargo check --workspace
cargo clippy --workspace --all-targets
cargo test -p ksp-onchain-transport-lib
```
Les validations ne sont pas déclarées réussies tant qu'elles n'ont pas été exécutées sur le checkout opérateur.
## Questions ouvertes
Aucune question bloquante.
## Suite
Après validation et commit de `0.2.2-pre.004`, poursuivre avec `0.2.2-pre.005` pour les sept wrappers Cluster simples :
```text
getClusterNodes
getEpochInfo
getEpochSchedule
getHighestSnapshotSlot
getIdentity
getMaxRetransmitSlot
getMaxShredInsertSlot
```