v0.4.8-pre.005

This commit is contained in:
2026-08-05 19:36:17 +02:00
parent 4c13d7ac54
commit 4187643148
18 changed files with 2448 additions and 169 deletions

View File

@@ -1,5 +1,5 @@
# file: Cargo.toml # file: Cargo.toml
# version: 26 # version: 27
[workspace] [workspace]
resolver = "3" resolver = "3"
@@ -18,7 +18,7 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.4.8-pre.4" version = "0.4.8-pre.5"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3" repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3"

View File

@@ -1,5 +1,5 @@
<!-- file: docs/IDL_AUDIT.md --> <!-- file: docs/IDL_AUDIT.md -->
<!-- version: 2 --> <!-- version: 3 -->
# Audit des IDL v3 # Audit des IDL v3
@@ -12,6 +12,12 @@
La copie officielle `metadata.ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S.solana_program_metadata.V0_0_0.from_github_solana_program.json` a été réauditée contre lIDL Codama publiée par `solana-program/program-metadata`. Le Program ID, la version déclarée `0.0.0`, les trois PDA, les deux comptes, les neuf instructions, les types et les cinq erreurs concordent. Le JSON local reste inchangé et conserve lempreinte inventoriée. Voir `audits/V0_4_8_PRE_002_METADATA_CONTRACT_AUDIT.md`. La copie officielle `metadata.ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S.solana_program_metadata.V0_0_0.from_github_solana_program.json` a été réauditée contre lIDL Codama publiée par `solana-program/program-metadata`. Le Program ID, la version déclarée `0.0.0`, les trois PDA, les deux comptes, les neuf instructions, les types et les cinq erreurs concordent. Le JSON local reste inchangé et conserve lempreinte inventoriée. Voir `audits/V0_4_8_PRE_002_METADATA_CONTRACT_AUDIT.md`.
## Réconciliation runtime Solana Program Metadata — `0.4.8-pre.005`
LIDL conserve exactement neuf instructions et reste inchangée. Laudit des tags stables `program@v1.0.0` et `program@v1.0.1` confirme le même inventaire `0..8`. Le processeur actuel accepte toutefois quelques formes supplémentaires par rapport au client Codama : `SetData` peut omettre `data_source` et préserver les données existantes, tandis que `SetImmutable`, `Trim` et `Close` ignorent un suffixe wire. Ces formes sont couvertes comme compatibilité runtime, sans modifier ni réécrire lIDL.
Le tag `5` a porté le nom de travail `WithdrawExcessLamports` avant la première release stable, puis a été remplacé par `Trim` sur le même discriminant. Il ne constitue pas une instruction historique distincte dans linventaire IDL. Voir `audits/V0_4_8_PRE_005_SOLANA_PROGRAM_METADATA_INSTRUCTION_HISTORY_AUDIT.md`.
## Inventaire ## Inventaire
| Nom v3 | Program ID déclaré | Version déclarée | Instructions | SHA-256 | | Nom v3 | Program ID déclaré | Version déclarée | Instructions | SHA-256 |

View File

@@ -1,101 +1,101 @@
<!-- file: docs/IDL_TO_KB_LIB_NOMENCLATURE.md --> <!-- file: docs/IDL_TO_KB_LIB_NOMENCLATURE.md -->
<!-- version: 4 --> <!-- version: 5 -->
# Correspondance IDL ↔ `kb-lib` # Correspondance IDL ↔ `kb-lib`
Ce tableau constitue la cible de classification pour les futurs décodeurs et exécuteurs. Ce tableau constitue la cible de classification pour les futurs décodeurs et exécuteurs.
Il ne signifie pas que tous les modules proposés sont déjà implémentés. Il ne signifie pas que tous les modules proposés sont déjà implémentés.
| IDL v3 | Module actuel | Module cible | Action Rust | | IDL v3 | Module actuel | Module cible | Action Rust |
|-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------|------------------------------------------------|---------------------------------------------------------------------| |-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------|------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|
| `adapter.DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB.saber_decimal_wrapper.V0_0_0.from_solscan.json` | `adapter/saber_decimal_wrapper` | `adapter/saber_decimal_wrapper` | Aucune | | `adapter.DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB.saber_decimal_wrapper.V0_0_0.from_solscan.json` | `adapter/saber_decimal_wrapper` | `adapter/saber_decimal_wrapper` | Aucune |
| `adapter.TwRapQCDhWkZRrDaHfZGuHxkZ91gHDRkyuzNqeU5MgR.spl_token_wrap.V0_1_0.from_github_solana_program.json` | `—` | `adapter/spl_token_wrap` | Créer `adapter/spl_token_wrap` | | `adapter.TwRapQCDhWkZRrDaHfZGuHxkZ91gHDRkyuzNqeU5MgR.spl_token_wrap.V0_1_0.from_github_solana_program.json` | `—` | `adapter/spl_token_wrap` | Créer `adapter/spl_token_wrap` |
| `amm.2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c.lifinity_swap_v2.V0_1_1.from_solscan.json` | `amm/lifinity_swap_v2` | `amm/lifinity_swap_v2` | Aucune | | `amm.2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c.lifinity_swap_v2.V0_1_1.from_solscan.json` | `amm/lifinity_swap_v2` | `amm/lifinity_swap_v2` | Aucune |
| `amm.AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ.metadao_v0_5.V0_5_0.from_solscan.json` | `amm/metadao_v0_5` | `amm/metadao_v0_5` | Aucune | | `amm.AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ.metadao_v0_5.V0_5_0.from_solscan.json` | `amm/metadao_v0_5` | `amm/metadao_v0_5` | Aucune |
| `amm.BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p.bonk_swap.V0_1_1.from_solscan.json` | `amm/bonk_swap` | `amm/bonk_swap` | Aucune | | `amm.BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p.bonk_swap.V0_1_1.from_solscan.json` | `amm/bonk_swap` | `amm/bonk_swap` | Aucune |
| `amm.Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB.meteora_damm_v1.V0_5_2.from_solscan.json` | `amm/meteora_damm_v1` | `amm/meteora_damm_v1` | Aucune | | `amm.Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB.meteora_damm_v1.V0_5_2.from_solscan.json` | `amm/meteora_damm_v1` | `amm/meteora_damm_v1` | Aucune |
| `amm.GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT.goosefx_gamma.V0_2_0.from_solscan.json` | `amm/goosefx_gamma` | `amm/goosefx_gamma` | Aucune | | `amm.GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT.goosefx_gamma.V0_2_0.from_solscan.json` | `amm/goosefx_gamma` | `amm/goosefx_gamma` | Aucune |
| `amm.GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn.goosefx_v2.V0_3_0.from_solscan.json` | `amm/goosefx_v2` | `amm/goosefx_v2` | Aucune | | `amm.GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn.goosefx_v2.V0_3_0.from_solscan.json` | `amm/goosefx_v2` | `amm/goosefx_v2` | Aucune |
| `amm.Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1.guac_swap.V0_1_1.from_solscan.json` | `amm/guac_swap` | `amm/guac_swap` | Aucune | | `amm.Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1.guac_swap.V0_1_1.from_solscan.json` | `amm/guac_swap` | `amm/guac_swap` | Aucune |
| `amm.WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb.woofi.V0_1_0.from_solscan.json` | `amm/woofi` | `amm/woofi` | Aucune | | `amm.WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb.woofi.V0_1_0.from_solscan.json` | `amm/woofi` | `amm/woofi` | Aucune |
| `amm.cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG.meteora_damm_v2.V0_2_0.from_solscan.json` | `amm/meteora_damm_v2` | `amm/meteora_damm_v2` | Aucune | | `amm.cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG.meteora_damm_v2.V0_2_0.from_solscan.json` | `amm/meteora_damm_v2` | `amm/meteora_damm_v2` | Aucune |
| `amm.pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA.pump_swap.V0_1_0.from_solscan.json` | `amm/pump_swap` | `amm/pump_swap` | Aucune | | `amm.pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA.pump_swap.V0_1_0.from_solscan.json` | `amm/pump_swap` | `amm/pump_swap` | Aucune |
| `amm.vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ.vertigo.V0_1_0.from_solscan.json` | `amm/vertigo` | `amm/vertigo` | Aucune | | `amm.vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ.vertigo.V0_1_0.from_solscan.json` | `amm/vertigo` | `amm/vertigo` | Aucune |
| `bridge.6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn.layer_zero_executor.V0_1_0.from_solscan.json` | `bridge/layer_zero_executor` | `bridge/layer_zero_executor` | Aucune | | `bridge.6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn.layer_zero_executor.V0_1_0.from_solscan.json` | `bridge/layer_zero_executor` | `bridge/layer_zero_executor` | Aucune |
| `bridge.76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6.layer_zero_endpoint.V0_1_0.from_solscan.json` | `bridge/layer_zero_endpoint` | `bridge/layer_zero_endpoint` | Aucune | | `bridge.76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6.layer_zero_endpoint.V0_1_0.from_solscan.json` | `bridge/layer_zero_endpoint` | `bridge/layer_zero_endpoint` | Aucune |
| `bridge.CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe.circle_cctp_token_messenger_minter_v2.V0_2_0.from_solscan.json` | `bridge/circle_cctp_token_messenger_minter_v2` | `bridge/circle_cctp_token_messenger_minter_v2` | Aucune | | `bridge.CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe.circle_cctp_token_messenger_minter_v2.V0_2_0.from_solscan.json` | `bridge/circle_cctp_token_messenger_minter_v2` | `bridge/circle_cctp_token_messenger_minter_v2` | Aucune |
| `bridge.CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3.circle_cctp_token_messenger_minter.V0_1_0.from_solscan.json` | `bridge/circle_cctp_token_messenger_minter` | `bridge/circle_cctp_token_messenger_minter` | Aucune | | `bridge.CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3.circle_cctp_token_messenger_minter.V0_1_0.from_solscan.json` | `bridge/circle_cctp_token_messenger_minter` | `bridge/circle_cctp_token_messenger_minter` | Aucune |
| `clmm.6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6.stabble.V0_1_0.from_solscan.json` | `clmm/stabble` | `clmm/stabble` | Aucune | | `clmm.6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6.stabble.V0_1_0.from_solscan.json` | `clmm/stabble` | `clmm/stabble` | Aucune |
| `clmm.CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK.raydium.V0_1_0.from_solscan.json` | `clmm/raydium` | `clmm/raydium` | Aucune | | `clmm.CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK.raydium.V0_1_0.from_solscan.json` | `clmm/raydium` | `clmm/raydium` | Aucune |
| `clmm.HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq.pancake_swap.V0_1_0.from_solscan.json` | `clmm/pancake_swap` | `clmm/pancake_swap` | Aucune | | `clmm.HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq.pancake_swap.V0_1_0.from_solscan.json` | `clmm/pancake_swap` | `clmm/pancake_swap` | Aucune |
| `clmm.REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2.byreal.V0_1_0.from_solscan.json` | `clmm/byreal` | `clmm/byreal` | Aucune | | `clmm.REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2.byreal.V0_1_0.from_solscan.json` | `clmm/byreal` | `clmm/byreal` | Aucune |
| `clmm.fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9.fusion.V1_1_4.from_solscan.json` | `clmm/fusion` | `clmm/fusion` | Aucune | | `clmm.fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9.fusion.V1_1_4.from_solscan.json` | `clmm/fusion` | `clmm/fusion` | Aucune |
| `clmm.whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc.orca_whirlpool.V0_9_0.from_solscan.json` | `clmm/orca_whirlpool` | `clmm/orca_whirlpool` | Aucune | | `clmm.whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc.orca_whirlpool.V0_9_0.from_solscan.json` | `clmm/orca_whirlpool` | `clmm/orca_whirlpool` | Aucune |
| `cpmm.CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C.raydium.V0_2_0.from_solscan.json` | `cpmm/raydium` | `cpmm/raydium` | Aucune | | `cpmm.CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C.raydium.V0_2_0.from_solscan.json` | `cpmm/raydium` | `cpmm/raydium` | Aucune |
| `dlmm.LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.meteora.V0_12_0.from_solscan.json` | `dlmm/meteora` | `dlmm/meteora` | Aucune | | `dlmm.LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.meteora.V0_12_0.from_solscan.json` | `dlmm/meteora` | `dlmm/meteora` | Aucune |
| `fees.pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ.pump_fees.V0_1_0.from_solscan.json` | `admin/pump_fees` | `fees/pump_fees` | Déplacer `admin/pump_fees``fees/pump_fees` | | `fees.pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ.pump_fees.V0_1_0.from_solscan.json` | `admin/pump_fees` | `fees/pump_fees` | Déplacer `admin/pump_fees``fees/pump_fees` |
| `governance.FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq.metadao_futarchy.V0_6_1.from_solscan.json` | `amm/metadao_futarchy_amm` | `governance/metadao_futarchy` | Déplacer `amm/metadao_futarchy_amm``governance/metadao_futarchy` | | `governance.FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq.metadao_futarchy.V0_6_1.from_solscan.json` | `amm/metadao_futarchy_amm` | `governance/metadao_futarchy` | Déplacer `amm/metadao_futarchy_amm``governance/metadao_futarchy` |
| `governance.SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf.squads_multisig.V2_0_0.from_solscan.json` | `—` | `governance/squads_multisig` | Créer `governance/squads_multisig` | | `governance.SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf.squads_multisig.V2_0_0.from_solscan.json` | `—` | `governance/squads_multisig` | Créer `governance/squads_multisig` |
| `governance.WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx.metadao_bid_wall.V0_7_0.from_solscan.json` | `governance/metadao_bid_wall` | `governance/metadao_bid_wall` | Aucune | | `governance.WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx.metadao_bid_wall.V0_7_0.from_solscan.json` | `governance/metadao_bid_wall` | `governance/metadao_bid_wall` | Aucune |
| `launchpad.5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki.virtuals.V0_1_0.from_solscan.json` | `amm/virtuals` | `launchpad/virtuals` | Déplacer `amm/virtuals``launchpad/virtuals` | | `launchpad.5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki.virtuals.V0_1_0.from_solscan.json` | `amm/virtuals` | `launchpad/virtuals` | Déplacer `amm/virtuals``launchpad/virtuals` |
| `launchpad.6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P.pump_fun.V0_1_0.from_solscan.json` | `launchpad/pump_fun` | `launchpad/pump_fun` | Aucune | | `launchpad.6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P.pump_fun.V0_1_0.from_solscan.json` | `launchpad/pump_fun` | `launchpad/pump_fun` | Aucune |
| `launchpad.LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj.raydium_launchlab.V0_2_0.from_solscan.json` | `launchpad/raydium_launchlab` | `launchpad/raydium_launchlab` | Aucune | | `launchpad.LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj.raydium_launchlab.V0_2_0.from_solscan.json` | `launchpad/raydium_launchlab` | `launchpad/raydium_launchlab` | Aucune |
| `launchpad.MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG.moonit.V0_1_0.from_solscan.json` | `launchpad/moonit` | `launchpad/moonit` | Aucune | | `launchpad.MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG.moonit.V0_1_0.from_solscan.json` | `launchpad/moonit` | `launchpad/moonit` | Aucune |
| `launchpad.PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd.pump_pumpup_ai.V0_1_0.from_solscan.json` | `launchpad/pump_pumpup_ai` | `launchpad/pump_pumpup_ai` | Aucune | | `launchpad.PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd.pump_pumpup_ai.V0_1_0.from_solscan.json` | `launchpad/pump_pumpup_ai` | `launchpad/pump_pumpup_ai` | Aucune |
| `launchpad.T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint.printr.V1_0_0.from_solscan.json` | `launchpad/printr` | `launchpad/printr` | Aucune | | `launchpad.T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint.printr.V1_0_0.from_solscan.json` | `launchpad/printr` | `launchpad/printr` | Aucune |
| `launchpad.boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4.boop_fun.V0_3_0.from_solscan.json` | `launchpad/boop_fun` | `launchpad/boop_fun` | Aucune | | `launchpad.boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4.boop_fun.V0_3_0.from_solscan.json` | `launchpad/boop_fun` | `launchpad/boop_fun` | Aucune |
| `launchpad.dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.meteora_dbc.V0_1_10.from_solscan.json` | `launchpad/meteora_dbc` | `launchpad/meteora_dbc` | Aucune | | `launchpad.dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.meteora_dbc.V0_1_10.from_solscan.json` | `launchpad/meteora_dbc` | `launchpad/meteora_dbc` | Aucune |
| `launchpad.moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM.metadao_ico.V0_7_0.from_solscan.json` | `launchpad/metadao_ico` | `launchpad/metadao_ico` | Aucune | | `launchpad.moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM.metadao_ico.V0_7_0.from_solscan.json` | `launchpad/metadao_ico` | `launchpad/metadao_ico` | Aucune |
| `launchpad.waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF.orca_wavebreak.V1_1_5.from_solscan.json` | `launchpad/orca_wavebreak` | `launchpad/orca_wavebreak` | Aucune | | `launchpad.waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF.orca_wavebreak.V1_1_5.from_solscan.json` | `launchpad/orca_wavebreak` | `launchpad/orca_wavebreak` | Aucune |
| `lending.C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr.clone.V0_1_0.from_solscan.json` | `lending/clone` | `lending/clone` | Aucune | | `lending.C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr.clone.V0_1_0.from_solscan.json` | `lending/clone` | `lending/clone` | Aucune |
| `lending.KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD.kamino.V1_23_0.from_solscan.json` | `lending/kamino` | `lending/kamino` | Aucune | | `lending.KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD.kamino.V1_23_0.from_solscan.json` | `lending/kamino` | `lending/kamino` | Aucune |
| `lending.MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA.marginfi_v2.V0_1_8.from_solscan.json` | `lending/marginfi_v2` | `lending/marginfi_v2` | Aucune | | `lending.MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA.marginfi_v2.V0_1_8.from_solscan.json` | `lending/marginfi_v2` | `lending/marginfi_v2` | Aucune |
| `lock.LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE.raydium_lp.V0_1_0.from_solscan.json` | `lock/raydium_lp` | `lock/raydium_lp` | Aucune | | `lock.LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE.raydium_lp.V0_1_0.from_solscan.json` | `lock/raydium_lp` | `lock/raydium_lp` | Aucune |
| `metadata.ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S.solana_program_metadata.V0_0_0.from_github_solana_program.json` | `metadata/solana_program_metadata` | `metadata/solana_program_metadata` | Modèles wire et décodeurs de comptes présents ; implémenter les instructions, la matérialisation et lexécuteur | | `metadata.ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S.solana_program_metadata.V0_0_0.from_github_solana_program.json` | `metadata/solana_program_metadata` | `metadata/solana_program_metadata` | Modèles wire, décodeurs de comptes et neuf instructions stables présents ; implémenter la matérialisation et lexécuteur |
| `metadata.metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s.metaplex_token_metadata.V1_14_0.from_solscan.json` | `metadata/metaplex_token_metadata` | `metadata/metaplex_token_metadata` | Aucune | | `metadata.metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s.metaplex_token_metadata.V1_14_0.from_solscan.json` | `metadata/metaplex_token_metadata` | `metadata/metaplex_token_metadata` | Aucune |
| `nft.BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY.metaplex_bubblegum.V0_12_0.from_solscan.json` | `nft/metaplex_bubblegum` | `nft/metaplex_bubblegum` | Aucune | | `nft.BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY.metaplex_bubblegum.V0_12_0.from_solscan.json` | `nft/metaplex_bubblegum` | `nft/metaplex_bubblegum` | Aucune |
| `nft.TCMPhJdwDryooaGtiocG1u3xcYbRpiJzb283XfCZsDp.tensor_cnft.V2_0_1.from_solscan.json` | `—` | `nft/tensor_cnft` | Créer `nft/tensor_cnft` | | `nft.TCMPhJdwDryooaGtiocG1u3xcYbRpiJzb283XfCZsDp.tensor_cnft.V2_0_1.from_solscan.json` | `—` | `nft/tensor_cnft` | Créer `nft/tensor_cnft` |
| `orderbook.j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X.jupiter_limit_order_v2.V0_1_0.from_solscan.json` | `orderbook/jupiter_limit_order_v2` | `orderbook/jupiter_limit_order_v2` | Aucune | | `orderbook.j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X.jupiter_limit_order_v2.V0_1_0.from_solscan.json` | `orderbook/jupiter_limit_order_v2` | `orderbook/jupiter_limit_order_v2` | Aucune |
| `orderbook.jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu.jupiter_limit_order.V0_1_0.from_solscan.json` | `orderbook/jupiter_limit_order` | `orderbook/jupiter_limit_order` | Aucune | | `orderbook.jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu.jupiter_limit_order.V0_1_0.from_solscan.json` | `orderbook/jupiter_limit_order` | `orderbook/jupiter_limit_order` | Aucune |
| `orderbook.opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb.openbook_v2.V0_1_0.from_solscan.json` | `orderbook/openbook_v2` | `orderbook/openbook_v2` | Aucune | | `orderbook.opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb.openbook_v2.V0_1_0.from_solscan.json` | `orderbook/openbook_v2` | `orderbook/openbook_v2` | Aucune |
| `perpetuals.EtrnLzgbS7nMMy5fbD42kXiUzGg8XQzJ972Xtk1cjWih.phoenix_eternal.V0_2_0.from_solscan.json` | `—` | `perpetuals/phoenix_eternal` | Créer `perpetuals/phoenix_eternal` | | `perpetuals.EtrnLzgbS7nMMy5fbD42kXiUzGg8XQzJ972Xtk1cjWih.phoenix_eternal.V0_2_0.from_solscan.json` | `—` | `perpetuals/phoenix_eternal` | Créer `perpetuals/phoenix_eternal` |
| `perpetuals.PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu.jupiter.V0_1_0.from_solscan.json` | `perpetuals/jupiter` | `perpetuals/jupiter` | Aucune | | `perpetuals.PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu.jupiter.V0_1_0.from_solscan.json` | `perpetuals/jupiter` | `perpetuals/jupiter` | Aucune |
| `perpetuals.ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD.zeta.V0_1_0.from_solscan.json` | `perpetuals/zeta` | `perpetuals/zeta` | Aucune | | `perpetuals.ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD.zeta.V0_1_0.from_solscan.json` | `perpetuals/zeta` | `perpetuals/zeta` | Aucune |
| `perpetuals.dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH.drift_v2.V2_150_0.from_solscan.json` | `perpetuals/drift_v2` | `perpetuals/drift_v2` | Aucune | | `perpetuals.dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH.drift_v2.V2_150_0.from_solscan.json` | `perpetuals/drift_v2` | `perpetuals/drift_v2` | Aucune |
| `router.6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma.okx_labs_v1.V0_1_0.from_solscan.json` | `router/okx_labs_v1` | `router/okx_labs_v1` | Aucune | | `router.6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma.okx_labs_v1.V0_1_0.from_solscan.json` | `router/okx_labs_v1` | `router/okx_labs_v1` | Aucune |
| `router.DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH.dflow_aggregator_v4.V0_1_0.from_solscan.json` | `router/dflow_aggregator_v4` | `router/dflow_aggregator_v4` | Aucune | | `router.DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH.dflow_aggregator_v4.V0_1_0.from_solscan.json` | `router/dflow_aggregator_v4` | `router/dflow_aggregator_v4` | Aucune |
| `router.JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB.jupiter_aggregator_v4.V0_1_0.from_solscan.json` | `router/jupiter_aggregator_v4` | `router/jupiter_aggregator_v4` | Aucune | | `router.JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB.jupiter_aggregator_v4.V0_1_0.from_solscan.json` | `router/jupiter_aggregator_v4` | `router/jupiter_aggregator_v4` | Aucune |
| `router.JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4.jupiter_aggregator_v6.V0_1_0.from_solscan.json` | `router/jupiter_aggregator_v6` | `router/jupiter_aggregator_v6` | Aucune | | `router.JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4.jupiter_aggregator_v6.V0_1_0.from_solscan.json` | `router/jupiter_aggregator_v6` | `router/jupiter_aggregator_v6` | Aucune |
| `router.proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u.okx_labs_v2.V0_1_0.from_solscan.json` | `router/okx_labs_v2` | `router/okx_labs_v2` | Aucune | | `router.proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u.okx_labs_v2.V0_1_0.from_solscan.json` | `router/okx_labs_v2` | `router/okx_labs_v2` | Aucune |
| `rwa.XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm.ondo_global_markets.V0_1_0.from_solscan.json` | `rwa/ondo_global_markets` | `rwa/ondo_global_markets` | Aucune | | `rwa.XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm.ondo_global_markets.V0_1_0.from_solscan.json` | `rwa/ondo_global_markets` | `rwa/ondo_global_markets` | Aucune |
| `solana.11111111111111111111111111111111.core.system.V0_0_1.from_github_solana_program.json` | `solana/core/system` | `solana/core/system` | Aucune | | `solana.11111111111111111111111111111111.core.system.V0_0_1.from_github_solana_program.json` | `solana/core/system` | `solana/core/system` | Aucune |
| `solana.AddressLookupTab1e1111111111111111111111111.core.address_lookup_table.V0_0_1.from_github_solana_program.json` | `solana/core/address_lookup_table` | `solana/core/address_lookup_table` | Aucune | | `solana.AddressLookupTab1e1111111111111111111111111.core.address_lookup_table.V0_0_1.from_github_solana_program.json` | `solana/core/address_lookup_table` | `solana/core/address_lookup_table` | Aucune |
| `solana.BPFLoaderUpgradeab1e11111111111111111111111.core.loader_v3.V0_0_0.from_github_solana_program.json` | `solana/core/loader_v3` | `solana/core/loader_v3` | Aucune | | `solana.BPFLoaderUpgradeab1e11111111111111111111111.core.loader_v3.V0_0_0.from_github_solana_program.json` | `solana/core/loader_v3` | `solana/core/loader_v3` | Aucune |
| `solana.ComputeBudget111111111111111111111111111111.core.compute_budget.V0_0_1.from_github_solana_program.json` | `solana/core/compute_budget` | `solana/core/compute_budget` | Aucune | | `solana.ComputeBudget111111111111111111111111111111.core.compute_budget.V0_0_1.from_github_solana_program.json` | `solana/core/compute_budget` | `solana/core/compute_budget` | Aucune |
| `solana.Config1111111111111111111111111111111111111.core.config.V0_0_1.from_github_solana_program.json` | `solana/core/config` | `solana/core/config` | Aucune | | `solana.Config1111111111111111111111111111111111111.core.config.V0_0_1.from_github_solana_program.json` | `solana/core/config` | `solana/core/config` | Aucune |
| `solana.Feature111111111111111111111111111111111111.core.feature.V0_0_1.from_github_solana_program.json` | `solana/core/feature` | `solana/core/feature` | Aucune | | `solana.Feature111111111111111111111111111111111111.core.feature.V0_0_1.from_github_solana_program.json` | `solana/core/feature` | `solana/core/feature` | Aucune |
| `solana.LoaderV411111111111111111111111111111111111.core.loader_v4.V0_0_0.from_github_solana_program.json` | `solana/core/loader_v4` | `solana/core/loader_v4` | Aucune | | `solana.LoaderV411111111111111111111111111111111111.core.loader_v4.V0_0_0.from_github_solana_program.json` | `solana/core/loader_v4` | `solana/core/loader_v4` | Aucune |
| `solana.Stake11111111111111111111111111111111111111.core.stake.V4_3_1.from_github_solana_program.json` | `solana/core/stake` | `solana/core/stake` | Aucune | | `solana.Stake11111111111111111111111111111111111111.core.stake.V4_3_1.from_github_solana_program.json` | `solana/core/stake` | `solana/core/stake` | Aucune |
| `spl.MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr.memo.v3.V3_0_1.from_github_solana_program.json` | `spl/memo/v3` | `spl/memo/v3` | Aucune | | `spl.MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr.memo.v3.V3_0_1.from_github_solana_program.json` | `spl/memo/v3` | `spl/memo/v3` | Aucune |
| `spl.TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.token.V3_3_0.from_github_solana_program.json` | `spl/token` | `spl/token` | Aucune | | `spl.TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.token.V3_3_0.from_github_solana_program.json` | `spl/token` | `spl/token` | Aucune |
| `spl.TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb.token_2022.V3_0_1.from_github_solana_program.json` | `spl/token_2022` | `spl/token_2022` | Aucune | | `spl.TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb.token_2022.V3_0_1.from_github_solana_program.json` | `spl/token_2022` | `spl/token_2022` | Aucune |
| `stable.HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn.swap_hylo_exchange.V0_1_4.from_solscan.json` | `stable/swap_hylo_exchange` | `stable/swap_hylo_exchange` | Aucune | | `stable.HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn.swap_hylo_exchange.V0_1_4.from_solscan.json` | `stable/swap_hylo_exchange` | `stable/swap_hylo_exchange` | Aucune |
| `stable.JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr.swap_jupiter_stable.V0_1_0.from_solscan.json` | `stable/swap_jupiter_stable` | `stable/swap_jupiter_stable` | Aucune | | `stable.JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr.swap_jupiter_stable.V0_1_0.from_solscan.json` | `stable/swap_jupiter_stable` | `stable/swap_jupiter_stable` | Aucune |
| `stable.NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P.swap_numeraire.V0_1_0.from_solscan.json` | `stable/swap_numeraire` | `stable/swap_numeraire` | Aucune | | `stable.NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P.swap_numeraire.V0_1_0.from_solscan.json` | `stable/swap_numeraire` | `stable/swap_numeraire` | Aucune |
| `stable.swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ.swap_stabble.V1_5_0.from_solscan.json` | `stable/swap_stabble` | `stable/swap_stabble` | Aucune | | `stable.swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ.swap_stabble.V1_5_0.from_solscan.json` | `stable/swap_stabble` | `stable/swap_stabble` | Aucune |
| `staking.4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7.jito_tip_distribution.V0_1_5.from_solscan.json` | `—` | `staking/jito_tip_distribution` | Créer `staking/jito_tip_distribution` | | `staking.4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7.jito_tip_distribution.V0_1_5.from_solscan.json` | `—` | `staking/jito_tip_distribution` | Créer `staking/jito_tip_distribution` |
| `staking.FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr.kamino_farm.V1_6_5.from_solscan.json` | `staking/kamino_farm` | `staking/kamino_farm` | Aucune | | `staking.FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr.kamino_farm.V1_6_5.from_solscan.json` | `staking/kamino_farm` | `staking/kamino_farm` | Aucune |
| `staking.MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD.marinade_finance.V0_1_0.from_solscan.json` | `staking/marinade_finance` | `staking/marinade_finance` | Aucune | | `staking.MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD.marinade_finance.V0_1_0.from_solscan.json` | `staking/marinade_finance` | `staking/marinade_finance` | Aucune |
| `storage.recr1L3PCGKLbckBqMNcJhuuyU1zgo8nBhfLVsJNwr5.solana_record.V0_4_0.from_github_solana_program.json` | `—` | `storage/solana_record` | Créer `storage/solana_record` | | `storage.recr1L3PCGKLbckBqMNcJhuuyU1zgo8nBhfLVsJNwr5.solana_record.V0_4_0.from_github_solana_program.json` | `—` | `storage/solana_record` | Créer `storage/solana_record` |
| `strategy.DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M.jupiter_dca.V0_1_0.from_solscan.json` | `strategy/jupiter_dca` | `strategy/jupiter_dca` | Déplacer `strategy/jupiter_dca``strategy/jupiter_dca` | | `strategy.DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M.jupiter_dca.V0_1_0.from_solscan.json` | `strategy/jupiter_dca` | `strategy/jupiter_dca` | Déplacer `strategy/jupiter_dca``strategy/jupiter_dca` |
| `treasury.treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5.helium_treasury_management.V0_2_3.from_solscan.json` | `treasury/helium_treasury_management` | `treasury/helium_treasury_management` | Aucune | | `treasury.treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5.helium_treasury_management.V0_2_3.from_solscan.json` | `treasury/helium_treasury_management` | `treasury/helium_treasury_management` | Aucune |
| `vault.24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi.meteora.V0_7_2.from_solscan.json` | `vault/meteora` | `vault/meteora` | Aucune | | `vault.24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi.meteora.V0_7_2.from_solscan.json` | `vault/meteora` | `vault/meteora` | Aucune |
| `vault.6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc.kamino_yvaults.V0_1_0.from_solscan.json` | `vault/kamino_yvaults` | `vault/kamino_yvaults` | Aucune | | `vault.6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc.kamino_yvaults.V0_1_0.from_solscan.json` | `vault/kamino_yvaults` | `vault/kamino_yvaults` | Aucune |
| `vault.CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s.carrot_defi.V0_1_0.from_solscan.json` | `vault/carrot_defi` | `vault/carrot_defi` | Aucune | | `vault.CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s.carrot_defi.V0_1_0.from_solscan.json` | `vault/carrot_defi` | `vault/carrot_defi` | Aucune |
| `vault.HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ.hylo_stability_pool.V0_1_4.from_solscan.json` | `vault/hylo_stability_pool` | `vault/hylo_stability_pool` | Aucune | | `vault.HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ.hylo_stability_pool.V0_1_4.from_solscan.json` | `vault/hylo_stability_pool` | `vault/hylo_stability_pool` | Aucune |
| `vault.KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd.kamino_v2.V2_1_1.from_solscan.json` | `vault/kamino_v2` | `vault/kamino_v2` | Aucune | | `vault.KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd.kamino_v2.V2_1_1.from_solscan.json` | `vault/kamino_v2` | `vault/kamino_v2` | Aucune |
| `vault.kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr.kamino.V0_1_0.from_solscan.json` | `vault/kamino` | `vault/kamino` | Aucune | | `vault.kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr.kamino.V0_1_0.from_solscan.json` | `vault/kamino` | `vault/kamino` | Aucune |
| `vesting.LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn.jupiter_lock.V0_4_0.from_solscan.json` | `admin/jupiter_lock` | `vesting/jupiter_lock` | Déplacer `admin/jupiter_lock``vesting/jupiter_lock` | | `vesting.LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn.jupiter_lock.V0_4_0.from_solscan.json` | `admin/jupiter_lock` | `vesting/jupiter_lock` | Déplacer `admin/jupiter_lock``vesting/jupiter_lock` |
| `vesting.strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m.streamflow.V0_1_0.from_solscan.json` | `vesting/streamflow` | `vesting/streamflow` | Aucune | | `vesting.strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m.streamflow.V0_1_0.from_solscan.json` | `vesting/streamflow` | `vesting/streamflow` | Aucune |
| `wallet.JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw.jupiter_apepro_smart_wallet.V0_1_0.from_solscan.json` | `wallet/jupiter_apepro_smart_wallet` | `wallet/jupiter_apepro_smart_wallet` | Aucune | | `wallet.JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw.jupiter_apepro_smart_wallet.V0_1_0.from_solscan.json` | `wallet/jupiter_apepro_smart_wallet` | `wallet/jupiter_apepro_smart_wallet` | Aucune |
| `weighted.swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.swap_stabble.V1_5_0.from_solscan.json` | `weighted/swap_stabble` | `weighted/swap_stabble` | Aucune | | `weighted.swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.swap_stabble.V1_5_0.from_solscan.json` | `weighted/swap_stabble` | `weighted/swap_stabble` | Aucune |

View File

@@ -1,5 +1,5 @@
<!-- file: docs/README.md --> <!-- file: docs/README.md -->
<!-- version: 15 --> <!-- version: 16 -->
# Documentation active de Khadhroony Bot3 # Documentation active de Khadhroony Bot3
@@ -94,6 +94,11 @@ Les onze crates possèdent désormais `README.md`, `TODO.md`, `USAGE.md` et `CHA
- [`validation/WEBSOCKET_MAINNET_RESEARCH_VALIDATION_REPORT.md`](validation/WEBSOCKET_MAINNET_RESEARCH_VALIDATION_REPORT.md) ; - [`validation/WEBSOCKET_MAINNET_RESEARCH_VALIDATION_REPORT.md`](validation/WEBSOCKET_MAINNET_RESEARCH_VALIDATION_REPORT.md) ;
- [`validation/MAINNET_RESEARCH_BACKFILL_VALIDATION_SCENARIO.md`](validation/MAINNET_RESEARCH_BACKFILL_VALIDATION_SCENARIO.md) ; - [`validation/MAINNET_RESEARCH_BACKFILL_VALIDATION_SCENARIO.md`](validation/MAINNET_RESEARCH_BACKFILL_VALIDATION_SCENARIO.md) ;
## Audits actifs
- [`Audit contractuel 0.4.8-pre.002 — metadata`](audits/V0_4_8_PRE_002_METADATA_CONTRACT_AUDIT.md) ;
- [`Audit 0.4.8-pre.005 — instructions et historique Solana Program Metadata`](audits/V0_4_8_PRE_005_SOLANA_PROGRAM_METADATA_INSTRUCTION_HISTORY_AUDIT.md).
## Plans de version actifs ## Plans de version actifs
- [`Plan 0.4.8 — Solana Program Metadata et complétude Token-2022`](plans/V0_4_8_SOLANA_PROGRAM_METADATA_AND_TOKEN_2022_COMPLETENESS_PLAN.md). - [`Plan 0.4.8 — Solana Program Metadata et complétude Token-2022`](plans/V0_4_8_SOLANA_PROGRAM_METADATA_AND_TOKEN_2022_COMPLETENESS_PLAN.md).

View File

@@ -0,0 +1,152 @@
<!-- file: docs/audits/V0_4_8_PRE_005_SOLANA_PROGRAM_METADATA_INSTRUCTION_HISTORY_AUDIT.md -->
<!-- version: 1 -->
# Audit `0.4.8-pre.005` — instructions et historique de Solana Program Metadata
## 1. Objet
Cet audit détermine la surface exacte du décodeur dinstructions du programme :
```text
ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S
```
Il vérifie séparément :
- linventaire stable actuel ;
- les écarts entre lIDL Codama, les clients générés et le processeur on-chain ;
- lexistence éventuelle dinstructions supprimées, remplacées ou obsolètes ;
- la politique de couverture à appliquer dans `kb-lib`.
Laudit ne porte ni sur Metaplex Token Metadata, ni sur les metadata incorporées à Token-2022, ni sur la résolution off-chain des URL.
## 2. Sources de vérité
Les sources officielles retenues sont :
- les tags `program@v1.0.0` et `program@v1.0.1` du dépôt `solana-program/program-metadata` ;
- `program/src/instruction.rs` et lentrypoint du programme ;
- les neuf processeurs sous `program/src/processor/` au tag `program@v1.0.1` ;
- lIDL Codama officielle conservée brute sous `idls/` ;
- les clients Codama générés, utilisés pour distinguer le contrat SDK canonique des formes supplémentaires acceptées par le runtime ;
- lhistorique Git antérieur à la première release stable, utilisé uniquement comme provenance.
Le processeur `program@v1.0.1` est la source de vérité pour les formes réellement acceptées par le runtime actuel. LIDL reste la source de vérité du contrat SDK publié.
## 3. Inventaire stable
Les deux releases stables auditées exposent le même inventaire de neuf instructions :
| Tag | Code Khadhroony | Instruction officielle | Statut |
|----:|-----------------|------------------------|--------|
| `0` | `write` | `Write` | stable |
| `1` | `initialize` | `Initialize` | stable |
| `2` | `set_authority` | `SetAuthority` | stable |
| `3` | `set_data` | `SetData` | stable |
| `4` | `set_immutable` | `SetImmutable` | stable |
| `5` | `trim` | `Trim` | stable |
| `6` | `close` | `Close` | stable |
| `7` | `allocate` | `Allocate` | stable |
| `8` | `extend` | `Extend` | stable |
Aucun discriminant stable supplémentaire na été trouvé. Aucun de ces neuf discriminants nest marqué obsolète dans les releases stables auditées.
## 4. Historique antérieur à la première release stable
### 4.1 Tag `5`
Un commit de travail du 10 janvier 2025 a introduit une instruction nommée `WithdrawExcessLamports` au tag `5`. Le 19 février 2025, avant `program@v1.0.0`, ce même tag a été remplacé par `Trim`.
Cette évolution ne crée pas une dixième instruction à couvrir :
- le discriminant reste `5` ;
- le contrat stable publié est `Trim` ;
- aucune release stable auditée nexpose `WithdrawExcessLamports` comme entrée distincte ;
- le comportement de `Trim` comprend désormais le redimensionnement du compte et le retrait de lexcédent de lamports.
Décision : le décodeur publie uniquement `trim` pour le tag `5`. Le nom pré-stable est conservé dans la provenance de lobservation et dans la matrice, sans entrée de couverture historique distincte.
### 4.2 Autres formes de travail
Lhistorique antérieur à `program@v1.0.0` contient plusieurs changements de wire, de comptes optionnels et de builders. Ils appartiennent à une phase explicitement marquée WIP dans le dépôt.
Aucune compatibilité réseau historique nest déclarée pour ces formes tant quune preuve de déploiement et une transaction de cluster ne sont pas identifiées. Le décodeur ne doit pas inventer des entrées historiques uniquement à partir de commits de développement.
## 5. Écarts runtime / IDL à conserver
### 5.1 `Write`
Le runtime exige un offset `u32` puis sélectionne exactement une source :
- octets restants dans linstruction ;
- ou compte `source_buffer` lorsque le reliquat est vide.
Les deux sources simultanées et labsence des deux sources échouent.
### 5.2 `Initialize`
Le header darguments fixe mesure 20 octets. Le reliquat peut être vide uniquement lorsque le compte metadata est déjà un `Buffer` préalloué ; sinon des données inline sont requises.
Le décodeur peut établir lintention wire, mais la validité de cette condition dépend de létat du compte et sera vérifiée par les lectures stateful futures.
### 5.3 `SetAuthority`
Le SDK encode une option canonique `0` ou `1`. Le runtime traite néanmoins tout flag non nul comme une nouvelle autorité et exige alors exactement 32 octets.
Pour le flag `0`, les octets suffixes sont ignorés sur le chemin `Metadata`. La suppression dautorité reste interdite pour un `Buffer` et cette distinction nécessite létat du compte.
### 5.4 `SetData`
LIDL encode `encoding`, `compression`, `format`, `data_source` puis un reliquat optionnel. Le processeur accepte aussi une forme de trois octets contenant uniquement les trois premiers champs ; cette forme modifie le header sans remplacer les données existantes.
Lorsque `data_source` est présent :
- un reliquat non vide fournit les données inline et impose le placeholder pour `buffer` ;
- un reliquat vide impose un véritable compte `buffer` ;
- les deux sources ou aucune source sont rejetées.
### 5.5 Instructions sans arguments SDK
`SetImmutable`, `Trim` et `Close` ne reçoivent pas leur reliquat depuis lentrypoint. Le runtime ignore donc les octets suivant leur tag, même si le client SDK canonique nen produit aucun.
Le décodeur conserve leur longueur et leur préfixe comme suffixe ignoré ; il ne les interprète pas comme de nouveaux arguments.
### 5.6 Comptes supplémentaires
Le runtime accepte des comptes restants pour `Write`, `Initialize`, `SetData`, `Allocate` et `Extend`. Il exige une longueur exacte pour `SetAuthority`, `SetImmutable`, `Trim` et `Close`.
La matrice contractuelle encode explicitement cette différence.
## 6. Décision de décodage
Le décodeur `DcMetadataSolanaProgramMetadataDecoder` :
- reconnaît uniquement le Program ID officiel ;
- déclare exactement neuf entrées de couverture non historiques ;
- borne la taille de linstruction et le nombre de comptes contextualisés ;
- valide les discriminateurs, longueurs, enums, flags, ordre des comptes et contrats de sources ;
- conserve les variantes runtime actuelles qui dépassent le contrat SDK ;
- conserve les suffixes runtime ignorés sans leur attribuer de sémantique ;
- produit une intention non committée pour une transaction échouée ;
- ne télécharge aucune URL et ne lit aucun compte externe implicitement ;
- ne déclare aucune forme pré-stable comme compatible réseau sans preuve de cluster.
## 7. Artefacts liés
- `test-fixtures/contract-matrices/SOLANA_PROGRAM_METADATA_INSTRUCTION_MATRIX.json` ;
- `kb-lib/src/decoder/metadata/solana_program_metadata/instruction.rs` ;
- `kb-lib/tests/external_solana_program_metadata_instruction_api.rs` ;
- `docs/IDL_AUDIT.md` ;
- `docs/IDL_TO_KB_LIB_NOMENCLATURE.md`.
## 8. Statut de validation
| Niveau | Statut |
|-------------------------------------------------|---------------------------------------------|
| audit de lIDL | validé |
| audit des sources `program@v1.0.1` | validé |
| comparaison `program@v1.0.0` / `program@v1.0.1` | validée, inventaire inchangé |
| audit historique pré-stable | documenté, sans revendication réseau |
| tests synthétiques Rust | à exécuter dans le workspace utilisateur |
| replay de transactions réelles | planifié dans les phases pipeline et Devnet |
| validation Devnet | non encore exécutée |

View File

@@ -1,11 +1,11 @@
<!-- file: docs/plans/V0_4_8_SOLANA_PROGRAM_METADATA_AND_TOKEN_2022_COMPLETENESS_PLAN.md --> <!-- file: docs/plans/V0_4_8_SOLANA_PROGRAM_METADATA_AND_TOKEN_2022_COMPLETENESS_PLAN.md -->
<!-- version: 4 --> <!-- version: 5 -->
# Plan `0.4.8` — Solana Program Metadata et complétude Token-2022 # Plan `0.4.8` — Solana Program Metadata et complétude Token-2022
## 1. Statut et rôle ## 1. Statut et rôle
Ce document est le livrable principal de `0.4.8-pre.001`, réconcilié après laudit contractuel de `0.4.8-pre.002`, les modèles de `pre.003` et les décodeurs de comptes de `pre.004`. Il constitue le plan vivant de la version et reste modifiable lorsque laudit du code, des interfaces officielles, de lIDL ou des validations Devnet impose un ajustement. Ce document est le livrable principal de `0.4.8-pre.001`, réconcilié après laudit contractuel de `0.4.8-pre.002`, les modèles de `pre.003`, les décodeurs de comptes de `pre.004` et le décodeur dinstructions de `pre.005`. Il constitue le plan vivant de la version et reste modifiable lorsque laudit du code, des interfaces officielles, de lIDL ou des validations Devnet impose un ajustement.
Il doit être maintenu pendant chaque prerelease, puis archivé pendant la dernière prerelease après transfert des décisions durables vers le ROADMAP, les matrices, les guides, les rapports, les TODO et les changelogs concernés. Il doit être maintenu pendant chaque prerelease, puis archivé pendant la dernière prerelease après transfert des décisions durables vers le ROADMAP, les matrices, les guides, les rapports, les TODO et les changelogs concernés.
@@ -15,13 +15,13 @@ Il doit être maintenu pendant chaque prerelease, puis archivé pendant la derni
### 2.1 Surfaces strictement distinctes ### 2.1 Surfaces strictement distinctes
| Surface | Program ID ou frontière | Rôle dans `0.4.8` | | Surface | Program ID ou frontière | Rôle dans `0.4.8` |
|---|---|---| |-----------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------------------------|
| Metaplex Token Metadata | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | surface clôturée en `0.4.7`, hors développement principal | | Metaplex Token Metadata | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | surface clôturée en `0.4.7`, hors développement principal |
| Token-2022 Token Metadata | programme Token-2022 `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | compléter le contrat déjà partiellement pris en charge | | Token-2022 Token Metadata | programme Token-2022 `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | compléter le contrat déjà partiellement pris en charge |
| `spl-token-metadata-interface` | interface sans Program ID autonome imposé | source contractuelle des instructions metadata implémentées par Token-2022 | | `spl-token-metadata-interface` | interface sans Program ID autonome imposé | source contractuelle des instructions metadata implémentées par Token-2022 |
| Solana Program Metadata | `ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S` | nouvelle surface on-chain à implémenter sous `metadata/solana_program_metadata` | | Solana Program Metadata | `ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S` | nouvelle surface on-chain à implémenter sous `metadata/solana_program_metadata` |
| contenu distant HTTP/IPFS/Arweave | transport off-chain indépendant | hors `0.4.8`, reporté à lhorizon `0.15+` | | contenu distant HTTP/IPFS/Arweave | transport off-chain indépendant | hors `0.4.8`, reporté à lhorizon `0.15+` |
Aucun décodeur Token-2022 existant nest un décodeur partiel de `ProgM6…`. Les deux contrats doivent conserver des namespaces, modèles, matrices, tests et scénarios distincts. Aucun décodeur Token-2022 existant nest un décodeur partiel de `ProgM6…`. Les deux contrats doivent conserver des namespaces, modèles, matrices, tests et scénarios distincts.
@@ -208,7 +208,7 @@ Validation définitive reçue le 5 août 2026 :
- `python3 scripts/audit_rust_workspace_rules.py` : propre ; - `python3 scripts/audit_rust_workspace_rules.py` : propre ;
- `cargo test -p kb-lib` : 647 tests unitaires, cinq tests dintégration et les doc-tests réussis. - `cargo test -p kb-lib` : 647 tests unitaires, cinq tests dintégration et les doc-tests réussis.
### `0.4.8-pre.004` — décodeur de comptes Solana Program Metadata — terminé côté delta ### `0.4.8-pre.004` — décodeur de comptes Solana Program Metadata — terminé
Résultat durable : `kb-lib` expose des snapshots et parseurs bornés pour `Buffer` et `Metadata`. Le propriétaire, les discriminateurs, les headers, les enums fermées, les longueurs logiques, les sources de données et les PDA metadata sont vérifiés. Les données après `data_length` restent une capacité allouée valide ; les données Buffer occupent tout le reliquat. Aucune URL ni référence externe nest résolue. Résultat durable : `kb-lib` expose des snapshots et parseurs bornés pour `Buffer` et `Metadata`. Le propriétaire, les discriminateurs, les headers, les enums fermées, les longueurs logiques, les sources de données et les PDA metadata sont vérifiés. Les données après `data_length` restent une capacité allouée valide ; les données Buffer occupent tout le reliquat. Aucune URL ni référence externe nest résolue.
@@ -219,12 +219,20 @@ Résultat durable : `kb-lib` expose des snapshots et parseurs bornés pour `Buff
- nomenclature IDL réconciliée avec le statut réel des comptes ; - nomenclature IDL réconciliée avec le statut réel des comptes ;
- test de façade publique pour les consommateurs externes. - test de façade publique pour les consommateurs externes.
Critère atteint côté delta : comptes exacts, erreurs fail-closed et politique de trailing bytes documentée ; compilation, Clippy et tests Rust restent à exécuter dans lenvironnement du projet avant validation définitive. Validation définitive reçue le 5 août 2026 : `cargo fmt --all`, `cargo check --workspace`, `cargo clippy --all-targets` et laudit workspace sont propres ; `cargo test -p kb-lib` réussit avec 653 tests unitaires, six tests dintégration et les doc-tests.
### `0.4.8-pre.005` — décodeur dinstructions Solana Program Metadata ### `0.4.8-pre.005` — décodeur dinstructions Solana Program Metadata — terminé côté delta
- neuf instructions confirmées ; Résultat durable : les releases stables `program@v1.0.0` et `program@v1.0.1` exposent exactement neuf discriminants `0..8`. Le tag `5`, nommé `WithdrawExcessLamports` pendant une phase pré-stable, est couvert uniquement comme `Trim` et conserve cet ancien nom comme provenance. Les variantes runtime actuelles qui dépassent lIDL sont explicitement préservées.
- comptes, signataires, arguments, échecs et instructions internes/externes.
- neuf instructions stables confirmées et activées ;
- comptes, signataires, flags writable, arguments, échecs et instructions internes/externes ;
- sélection exclusive des sources inline ou Buffer ;
- distinction entre longueurs de comptes exactes et comptes restants acceptés par le runtime ;
- matrice contractuelle et audit historique dédiés ;
- tests synthétiques et test de façade publique.
Critère atteint côté delta : inventaire stable et historique fermé, décodeur fail-closed et frontières off-chain conservées ; compilation, Clippy et tests Rust restent à exécuter dans lenvironnement du projet avant validation définitive.
### `0.4.8-pre.006` — matérialisation Solana Program Metadata ### `0.4.8-pre.006` — matérialisation Solana Program Metadata

View File

@@ -1,8 +1,20 @@
<!-- file: kb-lib/CHANGELOG.md --> <!-- file: kb-lib/CHANGELOG.md -->
<!-- version: 19 --> <!-- version: 21 -->
# CHANGELOG — kb-lib # CHANGELOG — kb-lib
## 0.4.8-pre.005 — instructions Solana Program Metadata
- active `DcMetadataSolanaProgramMetadataDecoder` pour les neuf discriminants stables `0..8` ;
- décode les arguments, comptes positionnels, signers, flags writable et sources inline ou Buffer avec des bornes explicites ;
- conserve les formes runtime actuelles non produites par le SDK, notamment `SetData` sur trois octets et les suffixes ignorés de `SetImmutable`, `Trim` et `Close` ;
- distingue comptes restants acceptés par le runtime et longueurs de comptes exactes ;
- documente le nom pré-stable `WithdrawExcessLamports` du tag `5` sans créer une entrée historique distincte de `Trim` ;
- ajoute la matrice dinstructions, laudit historique, les tests positifs/négatifs et le test de façade publique ;
- retire le décodeur Solana Program Metadata de linventaire des décodeurs réservés.
- aligne la structure du composant sur les règles du workspace : façade limitée aux sous-modules et réexports, implémentation déplacée dans `decoder.rs`, constantes centralisées dans `constants.rs` et accès internes via `crate::`.
- corrige les vecteurs négatifs `Initialize` afin de placer explicitement les valeurs invalides après les 16 octets du seed et de vérifier séparément `Encoding`, `Compression`, `Format` et `DataSource`.
## 0.4.8-pre.004 — comptes Solana Program Metadata ## 0.4.8-pre.004 — comptes Solana Program Metadata
- ajoute les décodeurs publics bornés des comptes `Buffer` et `Metadata` ainsi que leur sélection par discriminateur ; - ajoute les décodeurs publics bornés des comptes `Buffer` et `Metadata` ainsi que leur sélection par discriminateur ;

View File

@@ -1,5 +1,5 @@
<!-- file: kb-lib/README.md --> <!-- file: kb-lib/README.md -->
<!-- version: 21 --> <!-- version: 22 -->
# kb-lib # kb-lib
@@ -7,7 +7,7 @@
## Périmètre ## Périmètre
La crate couvre actuellement Solana Core, SPL Memo, SPL Token classique, SPL Associated Token Account, Token-2022, le registre SPL ElGamal et Metaplex Token Metadata. Elle expose également les modèles wire bornés et les décodeurs de comptes `Buffer` et `Metadata` de Solana Program Metadata ; le décodeur dinstructions reste réservé jusquà la phase suivante. La crate couvre actuellement Solana Core, SPL Memo, SPL Token classique, SPL Associated Token Account, Token-2022, le registre SPL ElGamal et Metaplex Token Metadata. Elle expose également les modèles wire bornés, les décodeurs de comptes `Buffer` et `Metadata` et le décodeur contextualisé des neuf instructions stables de Solana Program Metadata.
Pour Solana Program Metadata, la surface publique fondatrice comprend : Pour Solana Program Metadata, la surface publique fondatrice comprend :
@@ -17,7 +17,10 @@ Pour Solana Program Metadata, la surface publique fondatrice comprend :
- les données directes, URL et références vers un autre compte sans résolution off-chain ; - les données directes, URL et références vers un autre compte sans résolution off-chain ;
- les cinq erreurs custom officielles et les erreurs de conversion fail-closed ; - les cinq erreurs custom officielles et les erreurs de conversion fail-closed ;
- les snapshots bornés `Buffer` et `Metadata`, avec validation du propriétaire, des PDA metadata, des longueurs logiques et des trois sources de données ; - les snapshots bornés `Buffer` et `Metadata`, avec validation du propriétaire, des PDA metadata, des longueurs logiques et des trois sources de données ;
- une politique explicite où les octets situés après `data_length` sont conservés comme capacité allouée et jamais assimilés au contenu logique. - une politique explicite où les octets situés après `data_length` sont conservés comme capacité allouée et jamais assimilés au contenu logique ;
- les neuf instructions stables `Write`, `Initialize`, `SetAuthority`, `SetData`, `SetImmutable`, `Trim`, `Close`, `Allocate` et `Extend` ;
- les formes runtime actuelles non produites par le SDK, notamment `SetData` sans remplacement de données et les suffixes ignorés de `SetImmutable`, `Trim` et `Close` ;
- une frontière historique où lancien nom pré-stable `WithdrawExcessLamports` du tag `5` reste une provenance de `Trim`, sans dixième entrée de couverture.
Pour Metaplex Token Metadata, elle fournit : Pour Metaplex Token Metadata, elle fournit :
@@ -50,7 +53,7 @@ Pour Metaplex Token Metadata, elle fournit :
- contrats `MtApi*` et matérialisateurs concrets ; - contrats `MtApi*` et matérialisateurs concrets ;
- contrats `ExApi*`, politiques de sécurité et exécuteurs `Ex*Executor` ; - contrats `ExApi*`, politiques de sécurité et exécuteurs `Ex*Executor` ;
- `ExMetadataMetaplexTokenMetadataExecutor`, `ExMetaplexTokenMetadataExecutionIntent` et `ExMetaplexTokenMetadataOperation` ; - `ExMetadataMetaplexTokenMetadataExecutor`, `ExMetaplexTokenMetadataExecutionIntent` et `ExMetaplexTokenMetadataOperation` ;
- modèles `DcMetadataSpm*`, constantes `DC_METADATA_SPM_*` et fonctions `decoder_metadata_solana_program_metadata_decode_*_account` pour le contrat Solana Program Metadata ; - `DcMetadataSolanaProgramMetadataDecoder`, modèles `DcMetadataSpm*`, constantes `DC_METADATA_SPM_*` et fonctions `decoder_metadata_solana_program_metadata_decode_*_account` pour le contrat Solana Program Metadata ;
- modèles canoniques `Md*` réexportés par la façade. - modèles canoniques `Md*` réexportés par la façade.
Les exemples dappel et invariants sont documentés dans [USAGE.md](USAGE.md). Les exemples dappel et invariants sont documentés dans [USAGE.md](USAGE.md).
@@ -65,7 +68,7 @@ Les exemples dappel et invariants sont documentés dans [USAGE.md](USAGE.md).
La surface fonctionnelle Metaplex de la crate est achevée. Les campagnes Devnet restantes relèvent de `kb-pipeline-demo-scenarios` et de `kb-app-demo-desktop`, non dun manque de builder dans `kb-lib`. La surface fonctionnelle Metaplex de la crate est achevée. Les campagnes Devnet restantes relèvent de `kb-pipeline-demo-scenarios` et de `kb-app-demo-desktop`, non dun manque de builder dans `kb-lib`.
Pour Solana Program Metadata, les modèles wire et les décodeurs bornés de comptes sont actifs. `Buffer` accepte tout reliquat comme données allouées sans inventer de PDA stable après changement dautorité ; `Metadata` valide la dérivation canonical ou non-canonical et distingue le contenu logique de la capacité ajoutée par `Extend`. Le décodeur de protocole reste volontairement réservé jusquà limplémentation des neuf instructions. Pour Solana Program Metadata, les modèles wire, les décodeurs bornés de comptes et le décodeur contextualisé des neuf instructions stables sont actifs. `Buffer` accepte tout reliquat comme données allouées sans inventer de PDA stable après changement dautorité ; `Metadata` valide la dérivation canonical ou non-canonical et distingue le contenu logique de la capacité ajoutée par `Extend`. Les variantes qui dépendent de létat du compte restent des intentions wire jusquaux lectures stateful prévues, et aucune forme pré-stable nest déclarée compatible réseau sans preuve de cluster.
Le registre ElGamal nest pas déclaré validé réellement sur réseau. Le registre ElGamal nest pas déclaré validé réellement sur réseau.
@@ -76,3 +79,5 @@ Le registre ElGamal nest pas déclaré validé réellement sur réseau.
- [Historique des changements](CHANGELOG.md) - [Historique des changements](CHANGELOG.md)
- [Matrice contractuelle Metaplex](../test-fixtures/contract-matrices/METAPLEX_TOKEN_METADATA_MATRIX.json) - [Matrice contractuelle Metaplex](../test-fixtures/contract-matrices/METAPLEX_TOKEN_METADATA_MATRIX.json)
- [Matrice des comptes Solana Program Metadata](../test-fixtures/contract-matrices/SOLANA_PROGRAM_METADATA_ACCOUNT_MATRIX.json) - [Matrice des comptes Solana Program Metadata](../test-fixtures/contract-matrices/SOLANA_PROGRAM_METADATA_ACCOUNT_MATRIX.json)
- [Matrice des instructions Solana Program Metadata](../test-fixtures/contract-matrices/SOLANA_PROGRAM_METADATA_INSTRUCTION_MATRIX.json)
- [Audit de linventaire et de lhistorique des instructions](../docs/audits/V0_4_8_PRE_005_SOLANA_PROGRAM_METADATA_INSTRUCTION_HISTORY_AUDIT.md)

View File

@@ -1,5 +1,5 @@
<!-- file: kb-lib/USAGE.md --> <!-- file: kb-lib/USAGE.md -->
<!-- version: 10 --> <!-- version: 11 -->
# Utilisation de kb-lib # Utilisation de kb-lib
@@ -51,7 +51,8 @@ Décodeurs fonctionnels principaux :
- `DcSplAssociatedTokenAccountDecoder` ; - `DcSplAssociatedTokenAccountDecoder` ;
- `DcSplToken2022Decoder` ; - `DcSplToken2022Decoder` ;
- `DcSplElgamalRegistryDecoder` ; - `DcSplElgamalRegistryDecoder` ;
- `DcMetadataMetaplexTokenMetadataDecoder`. - `DcMetadataMetaplexTokenMetadataDecoder` ;
- `DcMetadataSolanaProgramMetadataDecoder`.
Les types réservés `Dc*Decoder` ne doivent pas être interprétés comme des décodeurs complets : ils publient une compatibilité conservatrice et aucune observation fonctionnelle. Les types réservés `Dc*Decoder` ne doivent pas être interprétés comme des décodeurs complets : ils publient une compatibilité conservatrice et aucune observation fonctionnelle.
@@ -82,7 +83,7 @@ println!("parsed registry state: {registry:#?}");
Les parseurs vérifient les bornes et formats quils annoncent. Ils ne reconstruisent pas un état historique depuis un RPC courant. Les parseurs vérifient les bornes et formats quils annoncent. Ils ne reconstruisent pas un état historique depuis un RPC courant.
## Modèles et comptes Solana Program Metadata ## Modèles, comptes et instructions Solana Program Metadata
Les modèles `DcMetadataSpm*` représentent uniquement le contrat on-chain du programme `ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S`. Ils ne téléchargent jamais les URL et ne lisent pas automatiquement les comptes référencés par `External`. Les modèles `DcMetadataSpm*` représentent uniquement le contrat on-chain du programme `ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S`. Ils ne téléchargent jamais les URL et ne lisent pas automatiquement les comptes référencés par `External`.
@@ -138,7 +139,19 @@ match snapshot {
Une URL est seulement décodée comme chaîne UTF-8 on-chain. Aucune requête HTTP, IPFS ou Arweave nest effectuée. Une référence `External` est seulement décodée en adresse, offset et longueur zeroable ; le compte référencé nest pas lu. Une URL est seulement décodée comme chaîne UTF-8 on-chain. Aucune requête HTTP, IPFS ou Arweave nest effectuée. Une référence `External` est seulement décodée en adresse, offset et longueur zeroable ; le compte référencé nest pas lu.
Le décodeur de protocole `DcMetadataSolanaProgramMetadataDecoder` reste réservé aux instructions. Les comptes constituent désormais un contrat public stable pour les futurs matérialisateurs, builders et parcours stateful. Le décodeur `DcMetadataSolanaProgramMetadataDecoder` reconnaît le Program ID `ProgM6…` et les neuf tags stables `0..8`. Il conserve les différences utiles entre le wire SDK et le runtime actuel, sans interpréter un suffixe ignoré comme un nouvel argument.
```rust
let decoder = kb_lib::DcMetadataSolanaProgramMetadataDecoder;
let recognition = kb_lib::DcApiInstructionDecoder::recognize(&decoder, &input);
if !recognition.compatible {
return std::result::Result::Err("instruction incompatible".to_string());
}
let result = kb_lib::DcApiInstructionDecoder::decode(&decoder, &input);
println!("status={:?}", result.status);
```
Le tag `5` est toujours publié comme `trim`. Son ancien nom pré-stable `withdraw_excess_lamports` est conservé uniquement comme provenance, car aucune release stable ne lexpose comme instruction distincte. Les URL et références externes restent des données on-chain ; le décodeur ne réalise aucun fetch.
## Comptes Metaplex Token Metadata ## Comptes Metaplex Token Metadata

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/decoder.rs // file: kb-lib/src/decoder.rs
// version: 14 // version: 16
//! Consolidated decoder modules. //! Consolidated decoder modules.
@@ -36,7 +36,6 @@ mod weighted;
/// Reserved `kb-lib.decoder.adapter.saber_decimal_wrapper` decoder. /// Reserved `kb-lib.decoder.adapter.saber_decimal_wrapper` decoder.
pub use self::adapter::DcAdapterSaberDecimalWrapperDecoder; pub use self::adapter::DcAdapterSaberDecimalWrapperDecoder;
/// Approve Collection Authority discriminator.
/// Reserved `kb-lib.decoder.adapter.spl_token_wrap` decoder. /// Reserved `kb-lib.decoder.adapter.spl_token_wrap` decoder.
pub use self::adapter::DcAdapterSplTokenWrapDecoder; pub use self::adapter::DcAdapterSplTokenWrapDecoder;
/// Reserved `kb-lib.decoder.amm.aldrin_v1` decoder. /// Reserved `kb-lib.decoder.amm.aldrin_v1` decoder.
@@ -201,6 +200,7 @@ pub use self::lending::DcLendingKaminoDecoder;
pub use self::lending::DcLendingMarginfiV2Decoder; pub use self::lending::DcLendingMarginfiV2Decoder;
/// Reserved `kb-lib.decoder.lock.raydium_lp` decoder. /// Reserved `kb-lib.decoder.lock.raydium_lp` decoder.
pub use self::lock::DcLockRaydiumLpDecoder; pub use self::lock::DcLockRaydiumLpDecoder;
/// Approve Collection Authority discriminator.
pub(crate) use self::metadata::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR; pub(crate) use self::metadata::DC_METADATA_MTM_APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR;
/// Approve Use Authority discriminator. /// Approve Use Authority discriminator.
pub(crate) use self::metadata::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR; pub(crate) use self::metadata::DC_METADATA_MTM_APPROVE_USE_AUTHORITY_DISCRIMINATOR;
@@ -332,16 +332,50 @@ pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR;
pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_DISCRIMINATOR; pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_DISCRIMINATOR;
/// Verify Sized Collection Item discriminator. /// Verify Sized Collection Item discriminator.
pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; pub(crate) use self::metadata::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR;
/// Account contract for `Allocate`.
pub(crate) use self::metadata::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
/// Exact fixed byte length of one Buffer account header. /// Exact fixed byte length of one Buffer account header.
pub use self::metadata::DC_METADATA_SPM_BUFFER_HEADER_BYTES; pub use self::metadata::DC_METADATA_SPM_BUFFER_HEADER_BYTES;
/// Account contract for `Close`.
pub(crate) use self::metadata::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_DECODER_SURFACES;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) use self::metadata::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) use self::metadata::DC_METADATA_SPM_EVENT_VERSION;
/// Account contract for `Extend`.
pub(crate) use self::metadata::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Exact byte length of one external-account data reference. /// Exact byte length of one external-account data reference.
pub use self::metadata::DC_METADATA_SPM_EXTERNAL_DATA_BYTES; pub use self::metadata::DC_METADATA_SPM_EXTERNAL_DATA_BYTES;
/// Account contract for `Initialize`.
pub(crate) use self::metadata::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) use self::metadata::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum Solana account-data length accepted by bounded account decoders. /// Maximum Solana account-data length accepted by bounded account decoders.
pub use self::metadata::DC_METADATA_SPM_MAX_ACCOUNT_BYTES; pub use self::metadata::DC_METADATA_SPM_MAX_ACCOUNT_BYTES;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
/// Exact fixed byte length of one Metadata account header. /// Exact fixed byte length of one Metadata account header.
pub use self::metadata::DC_METADATA_SPM_METADATA_HEADER_BYTES; pub use self::metadata::DC_METADATA_SPM_METADATA_HEADER_BYTES;
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) use self::metadata::DC_METADATA_SPM_PROGRAM_IDS;
/// Exact byte length of one Solana Program Metadata seed. /// Exact byte length of one Solana Program Metadata seed.
pub use self::metadata::DC_METADATA_SPM_SEED_BYTES; pub use self::metadata::DC_METADATA_SPM_SEED_BYTES;
/// Account contract for `SetAuthority`.
pub(crate) use self::metadata::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
/// Account contract for `SetData`.
pub(crate) use self::metadata::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
pub(crate) use self::metadata::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) use self::metadata::DC_METADATA_SPM_SURFACE_CODE;
/// Account contract for `Trim`.
pub(crate) use self::metadata::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
/// Account contract for `Write`.
pub(crate) use self::metadata::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Exact decoder for the Metaplex Token Metadata program. /// Exact decoder for the Metaplex Token Metadata program.
pub use self::metadata::DcMetadataMetaplexTokenMetadataDecoder; pub use self::metadata::DcMetadataMetaplexTokenMetadataDecoder;
/// Canonical projection shared by Collection and Use Authority records. /// Canonical projection shared by Collection and Use Authority records.
@@ -414,6 +448,8 @@ pub use self::metadata::DcMetadataSpmEncoding;
pub use self::metadata::DcMetadataSpmExternalData; pub use self::metadata::DcMetadataSpmExternalData;
/// Format declared for Solana Program Metadata content. /// Format declared for Solana Program Metadata content.
pub use self::metadata::DcMetadataSpmFormat; pub use self::metadata::DcMetadataSpmFormat;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::metadata::DcMetadataSpmInstructionAccountContract;
/// Bounded projection of one initialized Solana Program Metadata account. /// Bounded projection of one initialized Solana Program Metadata account.
pub use self::metadata::DcMetadataSpmMetadataAccountSnapshot; pub use self::metadata::DcMetadataSpmMetadataAccountSnapshot;
/// Bounded Solana Program Metadata model conversion error. /// Bounded Solana Program Metadata model conversion error.
@@ -424,6 +460,8 @@ pub use self::metadata::DcMetadataSpmProgramError;
pub use self::metadata::DcMetadataSpmSeed; pub use self::metadata::DcMetadataSpmSeed;
/// Canonical tracing target for this crate. /// Canonical tracing target for this crate.
pub(crate) use self::metadata::TRACING_TARGET_DECODER_METADATA_METAPLEX_TOKEN_METADATA; pub(crate) use self::metadata::TRACING_TARGET_DECODER_METADATA_METAPLEX_TOKEN_METADATA;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::metadata::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Crate-root access to `decode` from `instruction`. /// Crate-root access to `decode` from `instruction`.
pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_decode; pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_decode;
/// Decodes one Collection Authority Record account. /// Decodes one Collection Authority Record account.
@@ -450,12 +488,18 @@ pub use self::metadata::decoder_metadata_metaplex_token_metadata_decode_use_auth
pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_entry_for_discriminator; pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_entry_for_discriminator;
/// Crate-root access to `payload_discriminator` from `instruction`. /// Crate-root access to `payload_discriminator` from `instruction`.
pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_payload_discriminator; pub(crate) use self::metadata::decoder_metadata_metaplex_token_metadata_payload_discriminator;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::metadata::decoder_metadata_solana_program_metadata_decode;
/// Decodes one supported Solana Program Metadata account by its discriminator. /// Decodes one supported Solana Program Metadata account by its discriminator.
pub use self::metadata::decoder_metadata_solana_program_metadata_decode_account; pub use self::metadata::decoder_metadata_solana_program_metadata_decode_account;
/// Decodes one Solana Program Metadata Buffer account. /// Decodes one Solana Program Metadata Buffer account.
pub use self::metadata::decoder_metadata_solana_program_metadata_decode_buffer_account; pub use self::metadata::decoder_metadata_solana_program_metadata_decode_buffer_account;
/// Decodes one initialized Solana Program Metadata account. /// Decodes one initialized Solana Program Metadata account.
pub use self::metadata::decoder_metadata_solana_program_metadata_decode_metadata_account; pub use self::metadata::decoder_metadata_solana_program_metadata_decode_metadata_account;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::metadata::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::metadata::decoder_metadata_solana_program_metadata_payload_discriminator;
/// Reserved `kb-lib.decoder.nft.metaplex_bubblegum` decoder. /// Reserved `kb-lib.decoder.nft.metaplex_bubblegum` decoder.
pub use self::nft::DcNftMetaplexBubblegumDecoder; pub use self::nft::DcNftMetaplexBubblegumDecoder;
/// Reserved `kb-lib.decoder.nft.tensor_cnft` decoder. /// Reserved `kb-lib.decoder.nft.tensor_cnft` decoder.
@@ -755,11 +799,10 @@ pub use self::weighted::DcWeightedSwapStabbleDecoder;
mod reserved_decoder_tests { mod reserved_decoder_tests {
#[test] #[test]
fn every_reserved_decoder_exposes_only_registered_program_ids() { fn every_reserved_decoder_exposes_only_registered_program_ids() {
let decoders: [&dyn crate::DcApiProtocolDecoder; 105] = [ let decoders: [&dyn crate::DcApiProtocolDecoder; 104] = [
&crate::DcAdapterSaberDecimalWrapperDecoder, &crate::DcAdapterSaberDecimalWrapperDecoder,
&crate::DcAdapterSplTokenWrapDecoder, &crate::DcAdapterSplTokenWrapDecoder,
&crate::DcGovernanceSquadsMultisigDecoder, &crate::DcGovernanceSquadsMultisigDecoder,
&crate::DcMetadataSolanaProgramMetadataDecoder,
&crate::DcNftTensorCnftDecoder, &crate::DcNftTensorCnftDecoder,
&crate::DcPerpetualsPhoenixEternalDecoder, &crate::DcPerpetualsPhoenixEternalDecoder,
&crate::DcStakingJitoTipDistributionDecoder, &crate::DcStakingJitoTipDistributionDecoder,
@@ -891,6 +934,6 @@ mod reserved_decoder_tests {
assert!(decode_result.is_ok_and(|events| return events.is_empty())); assert!(decode_result.is_ok_and(|events| return events.is_empty()));
} }
} }
assert_eq!(names.len(), 105); assert_eq!(names.len(), 104);
} }
} }

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/decoder/metadata.rs // file: kb-lib/src/decoder/metadata.rs
// version: 9 // version: 11
//! `metadata` decoder family. //! `metadata` decoder family.
@@ -87,7 +87,7 @@ pub use self::solana_program_metadata::DC_METADATA_SPM_MAX_ACCOUNT_BYTES;
pub use self::solana_program_metadata::DC_METADATA_SPM_METADATA_HEADER_BYTES; pub use self::solana_program_metadata::DC_METADATA_SPM_METADATA_HEADER_BYTES;
/// Exact byte length of one Solana Program Metadata seed. /// Exact byte length of one Solana Program Metadata seed.
pub use self::solana_program_metadata::DC_METADATA_SPM_SEED_BYTES; pub use self::solana_program_metadata::DC_METADATA_SPM_SEED_BYTES;
/// Solana Program Metadata instruction decoder; account decoders are active. /// Exact Solana Program Metadata instruction and account decoder.
pub use self::solana_program_metadata::DcMetadataSolanaProgramMetadataDecoder; pub use self::solana_program_metadata::DcMetadataSolanaProgramMetadataDecoder;
/// Error returned while decoding a Solana Program Metadata account. /// Error returned while decoding a Solana Program Metadata account.
pub use self::solana_program_metadata::DcMetadataSpmAccountDecodeError; pub use self::solana_program_metadata::DcMetadataSpmAccountDecodeError;
@@ -264,3 +264,47 @@ pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_me
pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_entry_for_discriminator; pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_entry_for_discriminator;
/// Crate-root access to `payload_discriminator` from `instruction`. /// Crate-root access to `payload_discriminator` from `instruction`.
pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_payload_discriminator; pub(crate) use self::metaplex_token_metadata::decoder_metadata_metaplex_token_metadata_payload_discriminator;
/// Account contract for `Allocate`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
/// Account contract for `Close`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_DECODER_SURFACES;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_EVENT_VERSION;
/// Account contract for `Extend`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Account contract for `Initialize`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_PROGRAM_IDS;
/// Account contract for `SetAuthority`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
/// Account contract for `SetData`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_SURFACE_CODE;
/// Account contract for `Trim`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
/// Account contract for `Write`.
pub(crate) use self::solana_program_metadata::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::solana_program_metadata::DcMetadataSpmInstructionAccountContract;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::solana_program_metadata::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::solana_program_metadata::decoder_metadata_solana_program_metadata_decode;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::solana_program_metadata::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::solana_program_metadata::decoder_metadata_solana_program_metadata_payload_discriminator;

View File

@@ -1,10 +1,12 @@
// file: kb-lib/src/decoder/metadata/solana_program_metadata.rs // file: kb-lib/src/decoder/metadata/solana_program_metadata.rs
// version: 3 // version: 5
//! Public Solana Program Metadata models, account decoders and reserved instruction decoder. //! Public Solana Program Metadata models and exact account and instruction decoders.
mod account; mod account;
mod constants; mod constants;
mod decoder;
mod instruction;
mod model; mod model;
/// Error returned while decoding a Solana Program Metadata account. /// Error returned while decoding a Solana Program Metadata account.
@@ -31,6 +33,8 @@ pub use self::constants::DC_METADATA_SPM_MAX_ACCOUNT_BYTES;
pub use self::constants::DC_METADATA_SPM_METADATA_HEADER_BYTES; pub use self::constants::DC_METADATA_SPM_METADATA_HEADER_BYTES;
/// Exact byte length of one Solana Program Metadata seed. /// Exact byte length of one Solana Program Metadata seed.
pub use self::constants::DC_METADATA_SPM_SEED_BYTES; pub use self::constants::DC_METADATA_SPM_SEED_BYTES;
/// Exact decoder for Solana Program Metadata instructions and account snapshots.
pub use self::decoder::DcMetadataSolanaProgramMetadataDecoder;
/// Solana Program Metadata account discriminator. /// Solana Program Metadata account discriminator.
pub use self::model::DcMetadataSpmAccountDiscriminator; pub use self::model::DcMetadataSpmAccountDiscriminator;
/// Compression declared for metadata content. /// Compression declared for metadata content.
@@ -52,37 +56,47 @@ pub use self::model::DcMetadataSpmProgramError;
/// Exact fixed-size metadata seed. /// Exact fixed-size metadata seed.
pub use self::model::DcMetadataSpmSeed; pub use self::model::DcMetadataSpmSeed;
/// Decoder reserved for Solana Program Metadata instructions; account decoding is exposed separately. /// Account contract for `Allocate`.
#[derive(Clone, Debug, Default)] pub(crate) use self::constants::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
pub struct DcMetadataSolanaProgramMetadataDecoder; /// Account contract for `Close`.
pub(crate) use self::constants::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
impl crate::DcApiProtocolDecoder for crate::DcMetadataSolanaProgramMetadataDecoder { /// Surfaces handled by the Solana Program Metadata decoder.
fn decoder_name(&self) -> &'static str { pub(crate) use self::constants::DC_METADATA_SPM_DECODER_SURFACES;
return "kb-lib.decoder.metadata.solana_program_metadata"; /// Maximum instruction prefix retained in hexadecimal diagnostics.
} pub(crate) use self::constants::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
fn decoder_version(&self) -> &'static str { pub(crate) use self::constants::DC_METADATA_SPM_EVENT_VERSION;
return env!("CARGO_PKG_VERSION"); /// Account contract for `Extend`.
} pub(crate) use self::constants::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Account contract for `Initialize`.
fn program_ids(&self) -> &'static [&'static str] { pub(crate) use self::constants::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
return &[kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID]; /// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
} pub(crate) use self::constants::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum instruction-account count accepted by the contextual decoder.
fn supports_observation( pub(crate) use self::constants::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
&self, /// Maximum retained instruction payload accepted by the contextual decoder.
observation: &crate::MdProgramObservation, pub(crate) use self::constants::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
) -> crate::DcApiDecoderSupport { /// Program ids handled by the Solana Program Metadata decoder.
if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) { pub(crate) use self::constants::DC_METADATA_SPM_PROGRAM_IDS;
return crate::DcApiDecoderSupport::Maybe; /// Account contract for `SetAuthority`.
} pub(crate) use self::constants::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
return crate::DcApiDecoderSupport::No; /// Account contract for `SetData`.
} pub(crate) use self::constants::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
fn decode_observation( pub(crate) use self::constants::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
&self, /// Stable Solana Program Metadata decoder surface code.
_observation: &crate::MdProgramObservation, pub(crate) use self::constants::DC_METADATA_SPM_SURFACE_CODE;
) -> kb_core::Result<std::vec::Vec<crate::MdDecodedProtocolEvent>> { /// Account contract for `Trim`.
return std::result::Result::Ok(std::vec::Vec::new()); pub(crate) use self::constants::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
} /// Account contract for `Write`.
} pub(crate) use self::constants::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::constants::DcMetadataSpmInstructionAccountContract;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::constants::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::instruction::decoder_metadata_solana_program_metadata_decode;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::instruction::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::instruction::decoder_metadata_solana_program_metadata_payload_discriminator;

View File

@@ -1,7 +1,16 @@
// file: kb-lib/src/decoder/metadata/solana_program_metadata/constants.rs // file: kb-lib/src/decoder/metadata/solana_program_metadata/constants.rs
// version: 2 // version: 4
//! Bounded Solana Program Metadata wire constants. //! Bounded Solana Program Metadata wire and decoder constants.
/// Expected account role and privileges for one instruction position.
#[derive(Clone, Copy, Debug)]
pub(crate) struct DcMetadataSpmInstructionAccountContract {
pub(crate) role: &'static str,
pub(crate) signer: bool,
pub(crate) writable: bool,
pub(crate) optional: bool,
}
/// Exact byte length of one Solana Program Metadata seed. /// Exact byte length of one Solana Program Metadata seed.
pub const DC_METADATA_SPM_SEED_BYTES: usize = 16; pub const DC_METADATA_SPM_SEED_BYTES: usize = 16;
@@ -13,3 +22,320 @@ pub const DC_METADATA_SPM_METADATA_HEADER_BYTES: usize = 96;
pub const DC_METADATA_SPM_EXTERNAL_DATA_BYTES: usize = 40; pub const DC_METADATA_SPM_EXTERNAL_DATA_BYTES: usize = 40;
/// Maximum Solana account-data length accepted by bounded account decoders. /// Maximum Solana account-data length accepted by bounded account decoders.
pub const DC_METADATA_SPM_MAX_ACCOUNT_BYTES: usize = 10_485_760; pub const DC_METADATA_SPM_MAX_ACCOUNT_BYTES: usize = 10_485_760;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) const DC_METADATA_SPM_MAX_INSTRUCTION_BYTES: usize = 16_384;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) const DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS: usize = 16;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) const DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES: usize = 64;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) const DC_METADATA_SPM_SURFACE_CODE: &str = "metadata.solana_program_metadata";
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) const DC_METADATA_SPM_EVENT_VERSION: u16 = 1;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) const DC_METADATA_SPM_INSTRUCTION_ENTRIES: &[(u8, &str)] = &[
(0, "write"),
(1, "initialize"),
(2, "set_authority"),
(3, "set_data"),
(4, "set_immutable"),
(5, "trim"),
(6, "close"),
(7, "allocate"),
(8, "extend"),
];
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) const DC_METADATA_SPM_PROGRAM_IDS: &[&str] =
&[kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID];
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) const DC_METADATA_SPM_DECODER_SURFACES: &[crate::DcApiDecoderSurface] =
&[crate::DcApiDecoderSurface {
program_id: kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID,
surface_code: crate::DC_METADATA_SPM_SURFACE_CODE,
priority: 100,
}];
/// Account contract for `Write`.
pub(crate) const DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "buffer",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "source_buffer",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `Initialize`.
pub(crate) const DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "metadata",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "system_program",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `SetAuthority`.
pub(crate) const DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `SetData`.
pub(crate) const DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "metadata",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "buffer",
signer: false,
writable: true,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `SetImmutable`.
pub(crate) const DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "metadata",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `Trim`.
pub(crate) const DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "destination",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "rent_sysvar",
signer: false,
writable: false,
optional: false,
},
];
/// Account contract for `Close`.
pub(crate) const DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "destination",
signer: false,
writable: true,
optional: false,
},
];
/// Account contract for `Allocate`.
pub(crate) const DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "buffer",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "system_program",
signer: false,
writable: false,
optional: true,
},
];
/// Account contract for `Extend`.
pub(crate) const DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS:
&[crate::DcMetadataSpmInstructionAccountContract] = &[
crate::DcMetadataSpmInstructionAccountContract {
role: "account",
signer: false,
writable: true,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "authority",
signer: true,
writable: false,
optional: false,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program",
signer: false,
writable: false,
optional: true,
},
crate::DcMetadataSpmInstructionAccountContract {
role: "program_data",
signer: false,
writable: false,
optional: true,
},
];
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) const TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA: &str =
"kb-lib.decoder.metadata.solana_program_metadata";

View File

@@ -0,0 +1,134 @@
// file: kb-lib/src/decoder/metadata/solana_program_metadata/decoder.rs
// version: 1
//! Exact contextual dispatch for Solana Program Metadata.
/// Exact decoder for Solana Program Metadata instructions and account snapshots.
#[derive(Clone, Debug, Default)]
pub struct DcMetadataSolanaProgramMetadataDecoder;
impl crate::DcApiProtocolDecoder for crate::DcMetadataSolanaProgramMetadataDecoder {
fn decoder_name(&self) -> &'static str {
return "kb-lib.decoder.metadata.solana_program_metadata";
}
fn decoder_version(&self) -> &'static str {
return env!("CARGO_PKG_VERSION");
}
fn program_ids(&self) -> &'static [&'static str] {
return crate::DC_METADATA_SPM_PROGRAM_IDS;
}
fn supports_observation(
&self,
observation: &crate::MdProgramObservation,
) -> crate::DcApiDecoderSupport {
return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) {
crate::DcApiDecoderSupport::Yes
} else {
crate::DcApiDecoderSupport::No
};
}
fn decode_observation(
&self,
_observation: &crate::MdProgramObservation,
) -> kb_core::Result<std::vec::Vec<crate::MdDecodedProtocolEvent>> {
return std::result::Result::Ok(std::vec::Vec::new());
}
}
impl crate::DcApiInstructionDecoder for crate::DcMetadataSolanaProgramMetadataDecoder {
fn identity(&self) -> crate::DcApiDecoderIdentity {
return crate::DcApiDecoderIdentity {
name: crate::DC_METADATA_SPM_SURFACE_CODE.to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
};
}
fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] {
return crate::DC_METADATA_SPM_DECODER_SURFACES;
}
fn coverage(&self) -> std::vec::Vec<crate::DcApiDecoderCoverageDeclaration> {
return crate::DC_METADATA_SPM_INSTRUCTION_ENTRIES
.iter()
.map(|(tag, code)| {
return crate::DcApiDecoderCoverageDeclaration {
program_id: kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID
.to_string(),
surface_code: std::option::Option::Some(
crate::DC_METADATA_SPM_SURFACE_CODE.to_string(),
),
entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction,
entry_code: (*code).to_string(),
discriminator_hex: std::option::Option::Some(format!("{tag:02x}")),
historical: false,
};
})
.collect();
}
fn recognize(
&self,
input: &crate::MdCoreInstructionReplayInput,
) -> crate::DcApiDecoderRecognition {
if input.program_id != kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID {
return crate::DcApiDecoderRecognition::incompatible();
}
let discriminator =
crate::decoder_metadata_solana_program_metadata_payload_discriminator(input);
let entry = discriminator
.and_then(crate::decoder_metadata_solana_program_metadata_entry_for_discriminator);
return crate::DcApiDecoderRecognition::compatible(
entry.is_some(),
100,
std::option::Option::Some(crate::DC_METADATA_SPM_SURFACE_CODE.to_string()),
entry.map(|(_, code)| return code.to_string()),
discriminator.map(|value| return format!("{value:02x}")),
);
}
fn decode(
&self,
input: &crate::MdCoreInstructionReplayInput,
) -> crate::DcApiDecoderExecutionResult {
if input.program_id != kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID {
return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None);
}
let result = crate::decoder_metadata_solana_program_metadata_decode(input);
if matches!(
result.status,
crate::DcApiDecoderOutcomeStatus::Failed
| crate::DcApiDecoderOutcomeStatus::Unsupported
) {
tracing::error!(
target: crate::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA,
action = "decode_failure",
signature = %input.signature,
slot = input.slot,
instruction_path = %input.instruction_path,
program_id = %input.program_id,
processor_name = crate::DC_METADATA_SPM_SURFACE_CODE,
processor_version = env!("CARGO_PKG_VERSION"),
input_key = %input.replay_input_key,
transaction_failed = input.transaction_failed,
result_status = ?result.status,
diagnostics = ?result.diagnostics,
"Solana Program Metadata instruction was not decoded successfully"
);
}
tracing::debug!(
target: crate::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA,
action = "decode",
signature = %input.signature,
instruction_path = %input.instruction_path,
transaction_failed = input.transaction_failed,
result_status = ?result.status,
observation_count = result.observations.len(),
"Solana Program Metadata instruction decode completed"
);
return result;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/lib.rs // file: kb-lib/src/lib.rs
// version: 31 // version: 32
//! Consolidated decoder, executor, materializer and shared model library. //! Consolidated decoder, executor, materializer and shared model library.
#![warn(missing_docs)] #![warn(missing_docs)]
@@ -29,7 +29,6 @@ pub use self::decoder::DC_METADATA_SPM_SEED_BYTES;
pub use self::decoder::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN; pub use self::decoder::DC_SPL_ELGAMAL_REGISTRY_ACCOUNT_LEN;
/// Reserved `kb-lib.decoder.adapter.saber_decimal_wrapper` decoder. /// Reserved `kb-lib.decoder.adapter.saber_decimal_wrapper` decoder.
pub use self::decoder::DcAdapterSaberDecimalWrapperDecoder; pub use self::decoder::DcAdapterSaberDecimalWrapperDecoder;
/// Approve Collection Authority discriminator.
/// Exposes the reserved `DcAdapterSplTokenWrapDecoder` implementation. /// Exposes the reserved `DcAdapterSplTokenWrapDecoder` implementation.
pub use self::decoder::DcAdapterSplTokenWrapDecoder; pub use self::decoder::DcAdapterSplTokenWrapDecoder;
/// Reserved `kb-lib.decoder.amm.aldrin_v1` decoder. /// Reserved `kb-lib.decoder.amm.aldrin_v1` decoder.
@@ -1641,6 +1640,40 @@ pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_COLLECTION_DISCRIMINATOR;
pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_DISCRIMINATOR; pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_DISCRIMINATOR;
/// Verify Sized Collection Item discriminator. /// Verify Sized Collection Item discriminator.
pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR; pub(crate) use self::decoder::DC_METADATA_MTM_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR;
/// Account contract for `Allocate`.
pub(crate) use self::decoder::DC_METADATA_SPM_ALLOCATE_ACCOUNT_CONTRACTS;
/// Account contract for `Close`.
pub(crate) use self::decoder::DC_METADATA_SPM_CLOSE_ACCOUNT_CONTRACTS;
/// Surfaces handled by the Solana Program Metadata decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_DECODER_SURFACES;
/// Maximum instruction prefix retained in hexadecimal diagnostics.
pub(crate) use self::decoder::DC_METADATA_SPM_DIAGNOSTIC_PREFIX_BYTES;
/// Stable event schema version for decoded Solana Program Metadata instructions.
pub(crate) use self::decoder::DC_METADATA_SPM_EVENT_VERSION;
/// Account contract for `Extend`.
pub(crate) use self::decoder::DC_METADATA_SPM_EXTEND_ACCOUNT_CONTRACTS;
/// Account contract for `Initialize`.
pub(crate) use self::decoder::DC_METADATA_SPM_INITIALIZE_ACCOUNT_CONTRACTS;
/// Current stable instruction inventory for program releases 1.0.0 and 1.0.1.
pub(crate) use self::decoder::DC_METADATA_SPM_INSTRUCTION_ENTRIES;
/// Maximum instruction-account count accepted by the contextual decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_MAX_INSTRUCTION_ACCOUNTS;
/// Maximum retained instruction payload accepted by the contextual decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_MAX_INSTRUCTION_BYTES;
/// Program ids handled by the Solana Program Metadata decoder.
pub(crate) use self::decoder::DC_METADATA_SPM_PROGRAM_IDS;
/// Account contract for `SetAuthority`.
pub(crate) use self::decoder::DC_METADATA_SPM_SET_AUTHORITY_ACCOUNT_CONTRACTS;
/// Account contract for `SetData`.
pub(crate) use self::decoder::DC_METADATA_SPM_SET_DATA_ACCOUNT_CONTRACTS;
/// Account contract for `SetImmutable`.
pub(crate) use self::decoder::DC_METADATA_SPM_SET_IMMUTABLE_ACCOUNT_CONTRACTS;
/// Stable Solana Program Metadata decoder surface code.
pub(crate) use self::decoder::DC_METADATA_SPM_SURFACE_CODE;
/// Account contract for `Trim`.
pub(crate) use self::decoder::DC_METADATA_SPM_TRIM_ACCOUNT_CONTRACTS;
/// Account contract for `Write`.
pub(crate) use self::decoder::DC_METADATA_SPM_WRITE_ACCOUNT_CONTRACTS;
/// Stable Address Lookup Table surface code. /// Stable Address Lookup Table surface code.
pub(crate) use self::decoder::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE; pub(crate) use self::decoder::DC_SOLANA_CORE_ADDRESS_LOOKUP_TABLE_SURFACE_CODE;
/// Stable deprecated immutable BPF Loader surface code. /// Stable deprecated immutable BPF Loader surface code.
@@ -1765,6 +1798,8 @@ pub(crate) use self::decoder::DC_SPL_TOKEN_MAX_BATCH_INSTRUCTIONS;
pub(crate) use self::decoder::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES; pub(crate) use self::decoder::DC_SPL_TOKEN_MAX_INSTRUCTION_BYTES;
/// Stable protocol and surface code for the classic SPL Token program. /// Stable protocol and surface code for the classic SPL Token program.
pub(crate) use self::decoder::DC_SPL_TOKEN_SURFACE_CODE; pub(crate) use self::decoder::DC_SPL_TOKEN_SURFACE_CODE;
/// Expected account role and privileges for one instruction position.
pub(crate) use self::decoder::DcMetadataSpmInstructionAccountContract;
/// Expected role and privileges for one positional instruction account. /// Expected role and privileges for one positional instruction account.
pub(crate) use self::decoder::DcSolanaCoreAccountRole; pub(crate) use self::decoder::DcSolanaCoreAccountRole;
/// One resolved outer instruction payload and its provenance relative to the target instruction. /// One resolved outer instruction payload and its provenance relative to the target instruction.
@@ -1773,6 +1808,8 @@ pub(crate) use self::decoder::DcSolanaCoreResolvedInstructionPayload;
pub(crate) use self::decoder::DcSplElGamalRegistryParsedRegistryInstruction; pub(crate) use self::decoder::DcSplElGamalRegistryParsedRegistryInstruction;
/// Canonical tracing target for this crate. /// Canonical tracing target for this crate.
pub(crate) use self::decoder::TRACING_TARGET_DECODER_METADATA_METAPLEX_TOKEN_METADATA; pub(crate) use self::decoder::TRACING_TARGET_DECODER_METADATA_METAPLEX_TOKEN_METADATA;
/// Canonical tracing target for the Solana Program Metadata decoder.
pub(crate) use self::decoder::TRACING_TARGET_DECODER_METADATA_SOLANA_PROGRAM_METADATA;
/// Canonical tracing target for this crate. /// Canonical tracing target for this crate.
pub(crate) use self::decoder::TRACING_TARGET_DECODER_SOLANA_CORE; pub(crate) use self::decoder::TRACING_TARGET_DECODER_SOLANA_CORE;
/// Canonical tracing target for the Associated Token Account decoder. /// Canonical tracing target for the Associated Token Account decoder.
@@ -1791,6 +1828,12 @@ pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_decode;
pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_entry_for_discriminator; pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_entry_for_discriminator;
/// Crate-root access to `payload_discriminator` from `instruction`. /// Crate-root access to `payload_discriminator` from `instruction`.
pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_payload_discriminator; pub(crate) use self::decoder::decoder_metadata_metaplex_token_metadata_payload_discriminator;
/// Decodes one bounded Solana Program Metadata instruction.
pub(crate) use self::decoder::decoder_metadata_solana_program_metadata_decode;
/// Returns the stable entry matching one Solana Program Metadata discriminator.
pub(crate) use self::decoder::decoder_metadata_solana_program_metadata_entry_for_discriminator;
/// Returns the first byte of one retained Solana Program Metadata payload.
pub(crate) use self::decoder::decoder_metadata_solana_program_metadata_payload_discriminator;
/// Returns declared Address Lookup Table instruction coverage. /// Returns declared Address Lookup Table instruction coverage.
pub(crate) use self::decoder::decoder_solana_core_address_lookup_table_coverage; pub(crate) use self::decoder::decoder_solana_core_address_lookup_table_coverage;
/// Decodes one Address Lookup Table instruction. /// Decodes one Address Lookup Table instruction.

View File

@@ -0,0 +1,81 @@
// file: kb-lib/tests/external_solana_program_metadata_instruction_api.rs
// version: 1
//! Downstream-style compilation contract for the Solana Program Metadata instruction decoder.
#[test]
fn external_consumers_decode_instructions_only_through_crate_root_exports() {
let account = solana_pubkey::Pubkey::new_from_array([31_u8; 32]).to_string();
let authority = solana_pubkey::Pubkey::new_from_array([32_u8; 32]).to_string();
let placeholder = kb_program_ids::METADATA_SOLANA_PROGRAM_METADATA_PROGRAM_ID;
let account_keys = serde_json::json!([
{
"accountIndex": 0,
"accountKey": account,
"source": "static",
"signer": false,
"writable": true
},
{
"accountIndex": 1,
"accountKey": authority,
"source": "static",
"signer": true,
"writable": false
},
{
"accountIndex": 2,
"accountKey": placeholder,
"source": "static",
"signer": false,
"writable": false
},
{
"accountIndex": 3,
"accountKey": placeholder,
"source": "static",
"signer": false,
"writable": false
}
]);
let instruction_accounts = serde_json::json!([
{"accountIndex": 0, "accountKey": account},
{"accountIndex": 1, "accountKey": authority},
{"accountIndex": 2, "accountKey": placeholder},
{"accountIndex": 3, "accountKey": placeholder}
]);
let input_result = kb_lib::MdCoreInstructionReplayInput::new(
"spm:external:extend",
"signature",
42,
"0",
placeholder,
false,
std::option::Option::None,
account_keys,
instruction_accounts,
std::option::Option::Some(serde_json::json!({"dataBase64": "CAEA"})),
std::option::Option::None,
serde_json::json!([]),
serde_json::json!([]),
serde_json::json!([]),
serde_json::json!([]),
);
assert!(input_result.is_ok());
let input: kb_lib::MdCoreInstructionReplayInput;
if let std::result::Result::Ok(value) = input_result {
input = value;
} else {
return;
}
let decoder = kb_lib::DcMetadataSolanaProgramMetadataDecoder;
let recognition = kb_lib::DcApiInstructionDecoder::recognize(&decoder, &input);
assert!(recognition.compatible);
assert!(recognition.exact);
assert_eq!(recognition.entry_code.as_deref(), std::option::Option::Some("extend"));
let result = kb_lib::DcApiInstructionDecoder::decode(&decoder, &input);
assert_eq!(result.status, kb_lib::DcApiDecoderOutcomeStatus::Decoded);
assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some("extend"));
assert_eq!(result.observations.len(), 1);
assert_eq!(result.observations[0].payload_json["parameters"]["length"], 1);
}

View File

@@ -0,0 +1,111 @@
{
"schemaVersion": 1,
"surface": "metadata.solana_program_metadata",
"programId": "ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S",
"stableProgramReleases": [
"program@v1.0.0",
"program@v1.0.1"
],
"sourceOfTruth": {
"runtime": "solana-program/program-metadata program@v1.0.1 processor sources",
"sdkContract": "Codama IDL version 0.0.0 and generated client",
"localIdl": "idls/metadata.ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S.solana_program_metadata.V0_0_0.from_github_solana_program.json"
},
"instructions": [
{
"tag": 0,
"code": "write",
"stable": true,
"body": "u32 offset followed by optional remainder bytes",
"positionalAccounts": 3,
"remainingAccountsAcceptedByRuntime": true,
"runtimeCompatibility": "exactly one source: inline remainder bytes or source-buffer account"
},
{
"tag": 1,
"code": "initialize",
"stable": true,
"body": "16-byte seed, encoding, compression, format, data-source, optional remainder bytes",
"positionalAccounts": 5,
"remainingAccountsAcceptedByRuntime": true,
"runtimeCompatibility": "empty remainder is valid only when the metadata PDA is a preallocated Buffer"
},
{
"tag": 2,
"code": "set_authority",
"stable": true,
"body": "u8 option flag followed by zero or 32 public-key bytes",
"positionalAccounts": 4,
"remainingAccountsAcceptedByRuntime": false,
"runtimeCompatibility": "flag zero removes a canonical Metadata authority and ignores suffix bytes; Buffer authority removal fails at runtime"
},
{
"tag": 3,
"code": "set_data",
"stable": true,
"body": "encoding, compression, format, optional data-source and optional remainder bytes",
"positionalAccounts": 5,
"remainingAccountsAcceptedByRuntime": true,
"runtimeCompatibility": "three-byte processor form preserves existing data; otherwise exactly one source is selected between inline bytes and Buffer"
},
{
"tag": 4,
"code": "set_immutable",
"stable": true,
"body": "no SDK arguments",
"positionalAccounts": 4,
"remainingAccountsAcceptedByRuntime": false,
"runtimeCompatibility": "processor ignores instruction suffix bytes"
},
{
"tag": 5,
"code": "trim",
"stable": true,
"body": "no SDK arguments",
"positionalAccounts": 6,
"remainingAccountsAcceptedByRuntime": false,
"runtimeCompatibility": "processor ignores instruction suffix bytes"
},
{
"tag": 6,
"code": "close",
"stable": true,
"body": "no SDK arguments",
"positionalAccounts": 5,
"remainingAccountsAcceptedByRuntime": false,
"runtimeCompatibility": "processor ignores instruction suffix bytes"
},
{
"tag": 7,
"code": "allocate",
"stable": true,
"body": "empty for a keypair Buffer or exactly one 16-byte PDA seed",
"positionalAccounts": 5,
"remainingAccountsAcceptedByRuntime": true,
"runtimeCompatibility": "keypair form requires Buffer and authority to be the same account; PDA form requires distinct accounts"
},
{
"tag": 8,
"code": "extend",
"stable": true,
"body": "u16 little-endian length",
"positionalAccounts": 4,
"remainingAccountsAcceptedByRuntime": true,
"runtimeCompatibility": "current runtime contract"
}
],
"historyAudit": {
"obsoleteUniqueDiscriminators": 0,
"renamedTag5PreStable": "withdraw_excess_lamports",
"renamedTag5Current": "trim",
"tag5Discriminator": 5,
"duplicateHistoricalCoverageEntry": false,
"preStableWipWireLayouts": "not_declared_without_cluster_evidence",
"decision": "decode tag 5 as the stable Trim contract and retain the pre-stable name only as provenance"
},
"surfaceBoundaries": {
"metaplexTokenMetadata": "separate program and decoder",
"token2022TokenMetadata": "separate Token-2022 interface implementation",
"offchainResolution": false
}
}