# kb_decoder_spl_token Ce crate décode exclusivement le programme SPL Token classique `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`. Token-2022, ATA, les interfaces de métadonnées et les programmes qui invoquent Token par CPI ne sont pas absorbés dans sa surface. Une instruction Token inner reste néanmoins décodée grâce à son Program ID exact et à son chemin core stable. ## Surface couverte La couverture compilée contient les 28 tags publiés par `spl-token-interface 3.0.0` : `0..24`, `38`, `45` et `255`. Elle inclut les variantes historiques, checked, les deux générations sans Rent, les conversions montant/UI, `WithdrawExcessLamports`, `UnwrapLamports` et `Batch`. La publication d'un tag et son déploiement sont traités séparément. `UnwrapLamports` et `Batch` sont constructibles dans l'interface `3.0.0` et implémentés par p-token `1.0.0`. Leur déploiement sur le programme classique Devnet est observé par deux simulations réussies le 16 juillet 2026 ; Localnet et Mainnet restent non testés pour ces tags récents. Les opérations classiques observées sur Mainnet ou exécutées sur Devnet portent séparément leurs preuves réelles. La matrice normative est `docs/SPL_TOKEN_MATRIX.json`. ## Contrat de décodage `SplTokenDecoder` implémente les deux contrats communs : - `ProtocolDecoder` annonce `Yes` uniquement pour le Program ID Token classique exact ; - `InstructionDecoder` fournit une surface, 28 déclarations de couverture, une reconnaissance par tag et un résultat contextualisé pour le replay commun. Chaque observation conserve le tag, le wire borné et son SHA-256, le chemin outer/inner, les comptes dans leur ordre d'origine avec doublons et flags, les rôles prouvables, les paramètres bruts, la forme d'autorité structurelle et les diagnostics. Les montants `u64` sont écrits en chaînes décimales dans le JSON pour éviter toute perte à la frontière Tauri. Un `Transfer` non checked ne reçoit jamais de mint ou de decimals inventés. Le champ d'inférence reste explicitement vide tant qu'aucune corrélation core prouvée n'est implémentée. Le décodeur n'effectue aucune lecture RPC. ## Transactions échouées et autorités Une transaction échouée mais lisible produit une intention structurée avec `committed=false`. Elle ne prouve aucune mutation de compte Token. Les formes simple et multisig sont distinguées depuis les metas fournies ; la validation de `M/N` et des membres d'un multisig existant exige un snapshot stateful et n'est jamais inventée par le décodeur. Pour `InitializeMultisig` et `InitializeMultisig2`, le wire `M`, le nombre `N` déduit des comptes et les bornes officielles `1 <= M <= N <= 11` sont contrôlés structurellement. ## Batch `Batch` est analysé avec des bornes locales de 64 sous-instructions, 512 comptes cumulés et 16 384 octets de payload. Chaque entrée conserve son slice de comptes, son offset de données, son ordre et un chemin dérivé `/batch/`. Un batch vide, tronqué, avec longueur nulle, comptes insuffisants ou batch imbriqué échoue avec un diagnostic borné. ## Limites actuelles - Le contrat `CoreInstructionReplayInput` ne transporte pas encore les return data canoniques ; les trois conversions concernées restent décodées comme intentions, avec validation de return data explicitement indisponible. - Le corpus Mainnet prouve les opérations réellement observées, pas l'exhaustivité des 28 tags sur ce cluster. Les initialisations normalisées par la matérialisation ne sont pas attribuées à une variante wire sans preuve supplémentaire. - Localnet et Mainnet restent sans preuve de déploiement de `UnwrapLamports` et `Batch` ; la preuve Devnet n'est pas extrapolée aux autres clusters. ## Corpus réel Le replay Mainnet du 15 juillet 2026 a décodé 370 instructions sans entrée unsupported, failed ou unmatched. Il a produit 371 sorties commitées, huit refus correspondant exactement aux huit transactions échouées et un second replay avec zéro sélection. Les signatures représentatives de `Transfer`, `Approve`, `CloseAccount`, `TransferChecked`, `BurnChecked` et `SyncNative` sont conservées par instruction dans la matrice. Le lifecycle Devnet y conserve séparément les signatures exactes de ses opérations courantes. Le probe Devnet du 16 juillet 2026 a simulé sans signature ni envoi un `Batch` contenant un `TransferChecked` de montant nul, puis un `UnwrapLamports` d'un lamport depuis un compte wrapped SOL auxiliaire classique. Les deux simulations ont réussi sans erreur runtime, avec respectivement 270 et 140 compute units. ## Exemple ```rust let decoder = kb_decoder_spl_token::SplTokenDecoder; let result = kb_decoder_api::InstructionDecoder::decode(&decoder, &input); ```