v0.1.0-pre.009

This commit is contained in:
2026-07-23 21:19:45 +02:00
parent 12b42a31b8
commit 51ed3d11cf
22 changed files with 9580 additions and 86 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: README.md -->
<!-- version: 5 -->
<!-- version: 6 -->
# Khadhroony Bot3
@@ -56,3 +56,5 @@ cargo clippy --workspace --all-targets
`0.1.0-pre.004` porte le décodeur Solana Core dans `kb-lib`. `0.1.0-pre.005` ajoute SPL Memo v1, v3 et v4. `0.1.0-pre.006` ajoute le décodeur SPL Token classique avec ses 28 tags publiés, son wire borné, ses formes dautorité et son `Batch` structuré. `0.1.0-pre.007` ajoute le programme SPL Associated Token Account avec ses trois instructions, sa forme historique `Create` vide et la validation canonique des PDA pour SPL Token classique et Token2022.
`0.1.0-pre.008` porte le décodeur Token2022 maximal, son parseur détats Mint/Account/Multisig et de TLV, ainsi que le programme indépendant du registre ElGamal. Les deux composants gardent des frontières et des targets de tracing distincts. Tous les décodeurs migrés utilisent les mêmes contrats contextualisés, la même façade publique et aucune dépendance inverse vers `kb-store`.
`0.1.0-pre.009` porte le décodeur indépendant Metaplex Token Metadata. Il couvre les 58 discriminateurs dinstructions publiés `0..=57`, les 15 variantes de comptes `Key 0..=14`, les PDA officiels et les layouts courants, expérimentaux et historiques. Les metadata externes Metaplex restent séparées des metadata incorporées de Token2022, de Metaplex Core et de Bubblegum.

View File

@@ -1,5 +1,5 @@
<!-- file: ROADMAP.md -->
<!-- version: 6 -->
<!-- version: 7 -->
# ROADMAP — khadhroony-bot3
@@ -96,5 +96,19 @@
- [x] Déplacer `ProgramIdEntry` et les fonctions du registre dans `kb-program-ids/src/programs.rs`, avec `lib.rs` limité aux réexports.
- [x] Porter les targets de tracing vers `kb-lib.decoder.spl.token_2022` et `kb-lib.decoder.spl.elgamal_registry`.
- [x] Conserver les 55 tests Token2022/ElGamal et leurs matrices machine-readable.
- [ ] Valider `kb-program-ids`, les 251 tests de `kb-lib`, Clippy et le workspace avec Cargo sur la machine de développement.
- [ ] Poursuivre avec le décodeur Metaplex Token Metadata après validation.
- [x] Valider `kb-program-ids`, les 251 tests de `kb-lib`, Clippy et le workspace avec Cargo sur la machine de développement.
- [x] Poursuivre avec le décodeur Metaplex Token Metadata après validation.
### 0.1.0-pre.009 — Décodeur Metaplex Token Metadata dans `kb-lib`
- [x] Remplacer le scaffold `kb-lib::decoder::metadata::metaplex_token_metadata` par le décodeur maximal validé de bot2.
- [x] Conserver linventaire exhaustif des 58 discriminateurs dinstructions `0..=57`, y compris les variantes historiques.
- [x] Conserver linventaire exhaustif des 15 variantes de comptes `Key 0..=14`, avec rejet explicite de `Uninitialized`.
- [x] Porter les parseurs bornés de Metadata, Edition, Master Edition, Edition Marker, Token Record, records dautorité et de délégation, escrow et Reservation List.
- [x] Préserver les validations downer, de PDA, de bump, de longueur, de suffixe, de comptes ordonnés et de provenance.
- [x] Maintenir les layouts historiques matérialisables avec lifecycle explicite mais définitivement non exécutables.
- [x] Ajouter le Program ID Metaplex Token Metadata à `kb-program-ids` sans le classer comme surface native.
- [x] Porter le target de tracing vers `kb-lib.decoder.metadata.metaplex_token_metadata`.
- [x] Conserver les 69 tests Metaplex et la matrice machine-readable exhaustive.
- [ ] Valider `kb-program-ids`, les 320 tests de `kb-lib`, Clippy et le workspace avec Cargo sur la machine de développement.
- [ ] Poursuivre avec les matérialisateurs et exécuteurs après validation du port des décodeurs prioritaires.

View File

@@ -22,7 +22,7 @@
"ansi": true,
"targets": [
"kb_app_demo",
"kb_decoder_metadata_metaplex_token_metadata",
"kb-lib.decoder.metadata.metaplex_token_metadata",
"kb-lib.decoder.solana.core",
"kb-lib.decoder.spl.associated_token_account",
"kb-lib.decoder.spl.elgamal_registry",
@@ -1161,42 +1161,42 @@
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_debug",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_debug",
"enabled": true,
"sink": "file",
"level": "debug",
"path": "logs/devnet/kb_decoder_metadata_metaplex_token_metadata/debug.log",
"path": "logs/devnet/kb-lib/decoder/metadata/metaplex_token_metadata/debug.log",
"rotation": "daily",
"format": "human",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_info",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_info",
"enabled": true,
"sink": "file",
"level": "info",
"path": "logs/devnet/kb_decoder_metadata_metaplex_token_metadata/info.log",
"path": "logs/devnet/kb-lib/decoder/metadata/metaplex_token_metadata/info.log",
"rotation": "daily",
"format": "human",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_error",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_error",
"enabled": true,
"sink": "file",
"level": "error",
"path": "logs/devnet/kb_decoder_metadata_metaplex_token_metadata/error.jsonl",
"path": "logs/devnet/kb-lib/decoder/metadata/metaplex_token_metadata/error.jsonl",
"rotation": "daily",
"format": "json",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
@@ -1624,7 +1624,7 @@
"ansi": true,
"targets": [
"kb_app_demo",
"kb_decoder_metadata_metaplex_token_metadata",
"kb-lib.decoder.metadata.metaplex_token_metadata",
"kb-lib.decoder.solana.core",
"kb-lib.decoder.spl.associated_token_account",
"kb-lib.decoder.spl.elgamal_registry",
@@ -2763,42 +2763,42 @@
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_debug",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_debug",
"enabled": true,
"sink": "file",
"level": "debug",
"path": "logs/mainnet_research/kb_decoder_metadata_metaplex_token_metadata/debug.log",
"path": "logs/mainnet_research/kb-lib/decoder/metadata/metaplex_token_metadata/debug.log",
"rotation": "daily",
"format": "human",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_info",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_info",
"enabled": true,
"sink": "file",
"level": "info",
"path": "logs/mainnet_research/kb_decoder_metadata_metaplex_token_metadata/info.log",
"path": "logs/mainnet_research/kb-lib/decoder/metadata/metaplex_token_metadata/info.log",
"rotation": "daily",
"format": "human",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_error",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_error",
"enabled": true,
"sink": "file",
"level": "error",
"path": "logs/mainnet_research/kb_decoder_metadata_metaplex_token_metadata/error.jsonl",
"path": "logs/mainnet_research/kb-lib/decoder/metadata/metaplex_token_metadata/error.jsonl",
"rotation": "daily",
"format": "json",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
@@ -3426,7 +3426,7 @@
"ansi": true,
"targets": [
"kb_app_demo",
"kb_decoder_metadata_metaplex_token_metadata",
"kb-lib.decoder.metadata.metaplex_token_metadata",
"kb-lib.decoder.solana.core",
"kb-lib.decoder.spl.associated_token_account",
"kb-lib.decoder.spl.elgamal_registry",
@@ -4565,42 +4565,42 @@
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_debug",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_debug",
"enabled": true,
"sink": "file",
"level": "debug",
"path": "logs/mainnet/kb_decoder_metadata_metaplex_token_metadata/debug.log",
"path": "logs/mainnet/kb-lib/decoder/metadata/metaplex_token_metadata/debug.log",
"rotation": "daily",
"format": "human",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_info",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_info",
"enabled": true,
"sink": "file",
"level": "info",
"path": "logs/mainnet/kb_decoder_metadata_metaplex_token_metadata/info.log",
"path": "logs/mainnet/kb-lib/decoder/metadata/metaplex_token_metadata/info.log",
"rotation": "daily",
"format": "human",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{
"name": "file_kb_decoder_metadata_metaplex_token_metadata_error",
"name": "file_kb_lib_decoder_metadata_metaplex_token_metadata_error",
"enabled": true,
"sink": "file",
"level": "error",
"path": "logs/mainnet/kb_decoder_metadata_metaplex_token_metadata/error.jsonl",
"path": "logs/mainnet/kb-lib/decoder/metadata/metaplex_token_metadata/error.jsonl",
"rotation": "daily",
"format": "json",
"ansi": false,
"targets": [
"kb_decoder_metadata_metaplex_token_metadata"
"kb-lib.decoder.metadata.metaplex_token_metadata"
]
},
{

View File

@@ -1,11 +1,11 @@
{
"schema_version": 2,
"milestone": "0.4.7-pre.025",
"milestone": "0.1.0-pre.009",
"surface_code": "metadata_metaplex_token_metadata",
"program_id": "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s",
"program_family": "independent_metaplex_foundation_program",
"decode_status": "instruction_inventory_exhaustive_0_through_57_and_account_key_inventory_exhaustive_0_through_14",
"runtime_registration": "not_enabled_in_pre_008",
"runtime_registration": "enabled_in_kb_lib_pre_009",
"official_sources": [
{
"kind": "repository",
@@ -356,7 +356,7 @@
}
],
"wire": "official_borsh_mpl_token_metadata_5_1_1",
"runtime_registration": "pending_full_group_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.003",
@@ -392,7 +392,7 @@
],
"wire": "single_u8_discriminator_official_mpl_token_metadata_5_1_1",
"account_contract": "ordered_required_accounts_plus_optional_collection_authority_record_and_bounded_remaining_accounts",
"runtime_registration": "pending_broader_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.004",
@@ -428,7 +428,7 @@
],
"wire": "single_u8_discriminator_official_mpl_token_metadata_5_1_1",
"account_contract": "ordered_required_accounts_plus_optional_collection_authority_record; collection metadata is writable and collection authority is readonly signer",
"runtime_registration": "pending_broader_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.005",
@@ -597,7 +597,7 @@
"wire": "u8 discriminator + historical DataV2 + bool is_mutable using Borsh 0.10",
"account_contract": "metadata, mint, mint_authority signer, payer writable signer, update_authority, system_program, optional rent",
"provenance": "historical Metaplex Token Metadata instruction surface; current SDK DataV2 type reused only for exact compatible wire fields",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.010",
@@ -624,7 +624,7 @@
],
"wire": "u8 discriminator + historical Data/Option<Data> fields using Borsh 0.10",
"provenance": "historical generated Metaplex Token Metadata surface",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.011",
@@ -651,7 +651,7 @@
],
"wire": "CreateMasterEditionV3: u8 discriminator + Option<u64> max_supply; conversion: u8 discriminator only",
"account_contract": "exact generated Rust SDK account order and signer/writable flags; optional rent accepted for CreateMasterEditionV3",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.012",
@@ -679,7 +679,7 @@
"wire": "u8 discriminator + MintNewEditionFromMasterEditionViaTokenArgs { edition: u64 }",
"account_contract": "exact generated Rust SDK account order and signer/writable flags; optional rent accepted after the required program accounts",
"edition_marker_contract": "edition marker PDA is writable and corresponds to floor(edition / EDITION_MARKER_BIT_SIZE); PDA derivation validation remains planned with account decoding",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.013",
@@ -707,7 +707,7 @@
"wire": "u8 discriminator + SetCollectionSizeArgs { size: u64 }",
"account_contract": "exact generated Rust SDK account order and signer/writable flags; optional collection authority record accepted",
"provenance_boundary": "BubblegumSetCollectionSize is decoded as a Token Metadata bridge instruction and does not claim complete Bubblegum coverage",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.014",
@@ -734,7 +734,7 @@
],
"wire": "u8 discriminator + DelegateArgs or RevokeArgs Borsh enum; DelegateArgs may contain optional AuthorizationData",
"account_contract": "14 positional accounts with Metaplex program placeholders for absent optional accounts; exact signer/writable invariants on authority, payer, metadata and optional writable records",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.015",
@@ -788,7 +788,7 @@
],
"wire": "Borsh enums TransferArgs/LockArgs/UnlockArgs/BurnArgs; CloseAccounts discriminator only",
"account_contract": "exact generated Rust SDK positional accounts and signer/writable invariants; Metaplex program placeholders accepted for absent optional programmable accounts",
"runtime_registration": "pending_full_decoder_and_account_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.016",
@@ -816,7 +816,7 @@
"wire": "u8 discriminator only",
"account_contract": "delegate writable signer, token account writable, edition/mint/token program readonly",
"inventory_audit": "official generated Rust SDK instruction module index audited; remaining modules are tracked before account-state decoding",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.017",
@@ -852,7 +852,7 @@
],
"wire": "u8 discriminator only",
"account_contract": "exact generated Rust SDK positional signer/writable contracts; BurnNft collection metadata, deprecated printing-token reservation list are optional trailing accounts",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.018",
@@ -897,7 +897,7 @@
],
"wire": "Create/Close/Collect discriminator only; TransferOutOfEscrow discriminator + amount u64",
"account_contract": "exact generated Rust SDK signer/writable contracts with optional trailing authority on create and transfer",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.019",
@@ -915,7 +915,7 @@
],
"wire": "u8 discriminator + CreateArgs enum",
"account_contract": "nine positional accounts with Metaplex placeholders for optional master edition and SPL Token Program",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.020",
@@ -933,7 +933,7 @@
],
"wire": "u8 discriminator + MintArgs::V1 { amount: u64, authorization_data: Option<AuthorizationData> }",
"account_contract": "fifteen positional accounts with Metaplex placeholders for optional token owner, master edition, token record, delegate record and authorization-rule accounts",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.021",
@@ -955,7 +955,7 @@
],
"wire": "u8 discriminator + PrintArgs::{V1,V2} { edition: u64 }",
"account_contract": "eighteen positional accounts with a Metaplex placeholder or writable Token Record at position 6",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.022",
@@ -984,7 +984,7 @@
],
"wire": "u8 discriminator + UpdateArgs enum",
"account_contract": "eleven positional accounts with Metaplex placeholders for optional delegate record, token, edition and authorization-rule accounts",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.023",
@@ -1031,7 +1031,7 @@
],
"wire": "u8 discriminator + UseArgs or VerificationArgs enum",
"account_contract": "twelve positional accounts for Use; eight positional accounts for Verify/Unverify, with Metaplex placeholders for optional accounts",
"runtime_registration": "pending_full_decoder_validation"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"pre_release": "0.4.7-pre.024",
@@ -1112,7 +1112,7 @@
],
"wire": "u8 discriminator only",
"account_contract": "exact IDL/generated positional signer and writable flags",
"runtime_registration": "pending_full_decoder_validation",
"runtime_registration": "enabled_in_kb_lib_pre_009",
"inventory_proof": {
"covered_discriminators": [
0,
@@ -1198,7 +1198,7 @@
"uri_bytes": 200,
"creators": 5
},
"runtime_registration": "not_enabled"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"group": "edition_and_master_edition_accounts",
@@ -1261,7 +1261,7 @@
"bit_order": "most_significant_bit_first"
}
},
"runtime_registration": "not_enabled"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"group": "token_record_account",
@@ -1300,7 +1300,7 @@
"LockedTransfer",
"Migration"
],
"runtime_registration": "not_enabled"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"group": "delegate_and_authority_records",
@@ -1363,7 +1363,7 @@
"holder_delegate_role_seeds": [
"print_delegate"
],
"runtime_registration": "not_enabled"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"group": "token_owned_escrow_account",
@@ -1405,7 +1405,7 @@
"Migrate": "may create or update related programmable records; correlation pending",
"Resize": "changes allocated account bytes without changing canonical identity"
},
"runtime_registration": "not_enabled"
"runtime_registration": "enabled_in_kb_lib_pre_009"
},
{
"group": "historical_reservation_lists",

View File

@@ -1,5 +1,5 @@
<!-- file: docs/PROGRAM_REGISTRY_CONTROL.md -->
<!-- version: 4 -->
<!-- version: 5 -->
# Contrôle du registre des programmes
@@ -250,7 +250,7 @@ Ces identifiants sont détaillés dans `docs/CORE_PROGRAM_IDS.md`. Ils sont couv
| `lock_raydium_lp` | `LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE` | `raydium_lock_lp` | `raydium_lock_lp` | `-` | `kb_decoder_lock_raydium_lp` | `reserved_missing` |
| `admin_jupiter_lock` | `LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn` | `jupiter_lock` | `jupiter_lock` | `-` | `kb_decoder_admin_jupiter_lock` | `reserved_missing` |
| `admin_pump_fees` | `pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ` | `pump_fees` | `pump_fees` | `kb_decoder_pump_fees` | `kb_decoder_admin_pump_fees` | `current_alias` |
| `metadata_metaplex_token_metadata` | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | `metaplex_token_metadata` | `metaplex_token_metadata` | `-` | `kb_decoder_metadata_metaplex_token_metadata` | `reserved_missing` |
| `metadata_metaplex_token_metadata` | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | `metaplex_token_metadata` | `metaplex_token_metadata` | `-` | `kb_lib::decoder::metadata::metaplex_token_metadata` | `current_migrated` |
| `metadata_name_service` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `name_service` | `name_service` | `-` | `kb_decoder_metadata_spl_name_service` | `reserved_missing` |
| `nft_metaplex_bubblegum` | `BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY` | `bubblegum` | `bubblegum` | `-` | `kb_decoder_nft_metaplex_bubblegum` | `reserved_missing` |
| `nft_metaplex_mpl_core` | `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d` | `mpl_core` | `mpl_core` | `-` | `kb_decoder_nft_metaplex_mpl_core` | `reserved_missing` |

View File

@@ -1,5 +1,5 @@
<!-- file: docs/SOLANA_INTERFACE_DEPENDENCIES.md -->
<!-- version: 30 -->
<!-- version: 31 -->
# Dépendances dinterfaces Solana et SPL
@@ -281,10 +281,23 @@ Pour chaque nouvelle interface :
6. tester les payloads tronqués, inconnus, suffixés et les comptes invalides ;
7. documenter toute divergence entre linterface et le runtime.
### Metaplex Token Metadata — audit et premier décodage `0.4.7-pre.002`
### Metaplex Token Metadata — port maximal `0.1.0-pre.009`
Le catalogue workspace déclare `mpl-token-metadata ^5.1` avec la seule feature `serde`. La publication officielle résolue reste `5.1.1`; elle fournit les modules générés `accounts`, `instructions`, `types` et `errors` issus de lIDL Metaplex, sans introduire Anchor. La crate officielle utilise Borsh `< 1.0`; le décodeur référence donc explicitement `borsh 0.10` sous lalias workspace `borsh_0_10`, distinct de Borsh 1.x utilisé par dautres interfaces du workspace.
Le dépôt officiel `metaplex-foundation/mpl-token-metadata` confirme le Program ID `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`. LIDL officiel audité porte la version `1.14.0` et le blob `5df4a24f62c2743125be096cc174680790c92c18`; linventaire Rust généré des instructions porte le blob `3c42eec629f82e44ba690a7c4bd2177cc78f1d49`.
`kb_decoder_metadata_metaplex_token_metadata` implémente désormais `InstructionDecoder` pour `CreateMetadataAccountV3` et `UpdateMetadataAccountV2`. Les arguments sont lus avec les types Borsh officiels et projetés avec la feature `serde`; les payloads, chaînes, créateurs, frais, comptes et suffixes sont bornés. Lenregistrement dans le registre runtime reste différé jusquà validation de ce premier groupe. Les metadata Token-2022 incorporées, Metaplex Core, Bubblegum et le JSON externe restent des provenances ou composants distincts.
`kb_lib::decoder::metadata::metaplex_token_metadata` implémente désormais la couverture exhaustive des
58 discriminateurs `0..=57`. Les arguments sont lus avec les types Borsh officiels lorsque le SDK
les expose, ou avec un miroir local borné du wire publié pour les variantes historiques. Les
payloads, chaînes, créateurs, frais, comptes et suffixes sont bornés.
Le même composant inventorie les 15 variantes `Key 0..=14` et décode les quatorze layouts
représentant un compte réel. Les parseurs utilisent `solana-pubkey ^4.2` pour vérifier owner,
PDA et bump, puis les comptes historiques reçoivent une politique de matérialisation historique
distincte de leur interdiction dexécution. `Uninitialized` reste une sentinelle explicitement
refusée et toute variante future absente de linventaire fait échouer les tests.
Les metadata Token2022 incorporées, Metaplex Core, Bubblegum et le JSON externe restent des
provenances ou composants distincts. Aucun fetch HTTP, IPFS ou Arweave nappartient au replay
canonique de cette tranche.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/TRACING_CONTRACT.md -->
<!-- version: 17 -->
<!-- version: 18 -->
# Contrat de tracing par crate et composant
@@ -57,6 +57,7 @@ Les targets déjà migrés vers les noms canoniques bot3 sont :
```text
kb-lib.decoder.solana.core
kb-lib.decoder.metadata.metaplex_token_metadata
kb-lib.decoder.spl.associated_token_account
kb-lib.decoder.spl.elgamal_registry
kb-lib.decoder.spl.memo

View File

@@ -1,5 +1,5 @@
# file: kb-lib/Cargo.toml
# version: 7
# version: 8
[package]
name = "kb-lib"
@@ -11,15 +11,18 @@ publish.workspace = true
[dependencies]
base64.workspace = true
borsh.workspace = true
borsh_0_10.workspace = true
bs58.workspace = true
kb-core = { path = "../kb-core" }
kb-program-ids = { path = "../kb-program-ids" }
mpl-token-metadata.workspace = true
serde.workspace = true
serde_json.workspace = true
sha2.workspace = true
solana-address-lookup-table-interface.workspace = true
solana-compute-budget-interface.workspace = true
solana-loader-v3-interface.workspace = true
solana-pubkey.workspace = true
solana-sdk-ids.workspace = true
solana-stake-interface.workspace = true
solana-system-interface.workspace = true

View File

@@ -1,5 +1,5 @@
<!-- file: kb-lib/README.md -->
<!-- version: 5 -->
<!-- version: 6 -->
# kb-lib
@@ -80,6 +80,24 @@ est `docs/SPL_TOKEN_2022_MATRIX.json`.
clé publique ElGamal et le wire complet. La matrice normative est
`docs/SPL_ELGAMAL_REGISTRY_MATRIX.json`.
## Décodeur Metaplex Token Metadata
`MetadataMetaplexTokenMetadataDecoder` couvre exclusivement
`metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`. Il inventorie exactement les 58
discriminateurs `0..=57`, conserve les arguments Borsh, les comptes positionnels,
les placeholders optionnels, les chemins outer/CPI et les transactions échouées
comme intentions non commitées.
Le module public
`kb_lib::decoder::metadata::metaplex_token_metadata` expose aussi les parseurs
bornés des 15 variantes `Key 0..=14` : Metadata, Edition et Master Edition,
Edition Marker V1/V2, Token Record, records de délégation et dautorité, Token
Owned Escrow et Reservation List historiques. Chaque parseur vérifie lowner,
le PDA, le bump, la longueur et les suffixes avant projection. Les comptes
historiques gardent une provenance et un lifecycle matérialisables, mais une
politique dexécution définitivement interdite. La matrice normative est
`docs/METAPLEX_TOKEN_METADATA_MATRIX.json`.
## API publique utile
- `SolanaCoreDecoder` : décodeur concret natif ;
@@ -89,6 +107,8 @@ clé publique ElGamal et le wire complet. La matrice normative est
- `SplToken2022Decoder` : décodeur exact des instructions Token2022 ;
- `Token2022State`, `Token2022StateKind`, `Token2022TlvEntry` et `parse_token_2022_state()` : API publique de lecture détat Token2022 ;
- `SplElgamalRegistryDecoder`, `ElGamalRegistryState` et `parse_elgamal_registry_state()` : API publique du registre ElGamal ;
- `MetadataMetaplexTokenMetadataDecoder` : décodeur exact du programme Metaplex Token Metadata ;
- `kb_lib::decoder::metadata::metaplex_token_metadata` : parseurs et snapshots publics des comptes Metaplex ;
- `InstructionDecoder` : contrat de reconnaissance, couverture et décodage contextualisé ;
- `ProtocolDecoder` : contrat de compatibilité avec les observations historiques ;
- `CoreInstructionReplayInput` : input source-neutral produit par lextraction core ;

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/decoder.rs
// version: 5
// version: 6
//! Consolidated decoder modules.
@@ -138,6 +138,8 @@ pub(crate) use self::spl::spl_token_entry_for_tag;
/// Returns the first byte of one retained classic SPL Token payload.
pub(crate) use self::spl::spl_token_payload_tag;
/// Exact decoder for the Metaplex Token Metadata program.
pub use self::metadata::MetadataMetaplexTokenMetadataDecoder;
/// Exact byte length of one SPL ElGamal registry account.
pub use self::spl::ELGAMAL_REGISTRY_ACCOUNT_LEN;
/// Parsed SPL ElGamal public-key registry account.

View File

@@ -1,7 +1,10 @@
// file: kb-lib/src/decoder/metadata.rs
// version: 1
// version: 2
//! `metadata` decoder family.
pub mod metaplex_token_metadata;
pub mod spl_name_service;
/// Exact decoder for the Metaplex Token Metadata program.
pub use self::metaplex_token_metadata::MetadataMetaplexTokenMetadataDecoder;

View File

@@ -1,10 +1,223 @@
// file: kb-lib/src/decoder/metadata/metaplex_token_metadata.rs
// version: 1
// version: 2
//! Migration boundary for legacy crate `kb_decoder_metadata_metaplex_token_metadata`.
//! Contextual instruction and bounded account decoder for Metaplex Token Metadata.
/// Legacy crate name retained for migration and compatibility tracking.
pub const LEGACY_CRATE: &str = "kb_decoder_metadata_metaplex_token_metadata";
mod account;
mod canonical;
mod constants;
mod decoder;
mod instruction;
/// Current porting status.
pub const MIGRATION_STATUS: &str = "source-preserved-pending-port";
/// Approve Collection Authority discriminator.
pub(crate) use self::constants::APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR;
/// Approve Use Authority discriminator.
pub(crate) use self::constants::APPROVE_USE_AUTHORITY_DISCRIMINATOR;
/// Bubblegum Set Collection Size discriminator.
pub(crate) use self::constants::BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR;
/// Burn discriminator.
pub(crate) use self::constants::BURN_DISCRIMINATOR;
/// Historical Burn Edition NFT discriminator.
pub(crate) use self::constants::BURN_EDITION_NFT_DISCRIMINATOR;
/// Historical Burn NFT discriminator.
pub(crate) use self::constants::BURN_NFT_DISCRIMINATOR;
/// Close Accounts discriminator.
pub(crate) use self::constants::CLOSE_ACCOUNTS_DISCRIMINATOR;
/// Close Escrow Account discriminator.
pub(crate) use self::constants::CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR;
/// Collect discriminator.
pub(crate) use self::constants::COLLECT_DISCRIMINATOR;
/// Convert Master Edition V1 to V2 discriminator.
pub(crate) use self::constants::CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR;
/// Modern Create discriminator.
pub(crate) use self::constants::CREATE_DISCRIMINATOR;
/// Create Escrow Account discriminator.
pub(crate) use self::constants::CREATE_ESCROW_ACCOUNT_DISCRIMINATOR;
/// Historical Create Master Edition discriminator.
pub(crate) use self::constants::CREATE_MASTER_EDITION_DISCRIMINATOR;
/// Create Master Edition V3 discriminator.
pub(crate) use self::constants::CREATE_MASTER_EDITION_V3_DISCRIMINATOR;
/// Historical Create Metadata Account discriminator.
pub(crate) use self::constants::CREATE_METADATA_ACCOUNT_DISCRIMINATOR;
/// Historical Create Metadata Account V2 discriminator.
pub(crate) use self::constants::CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR;
/// Create Metadata Account V3 discriminator.
pub(crate) use self::constants::CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR;
/// Delegate discriminator.
pub(crate) use self::constants::DELEGATE_DISCRIMINATOR;
/// Deprecated Create Master Edition discriminator.
pub(crate) use self::constants::DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR;
/// Deprecated Create Reservation List discriminator.
pub(crate) use self::constants::DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR;
/// Deprecated printing-token mint-new-edition discriminator.
pub(crate) use self::constants::DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR;
/// Deprecated Mint Printing Tokens discriminator.
pub(crate) use self::constants::DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR;
/// Deprecated Mint Printing Tokens Via Token discriminator.
pub(crate) use self::constants::DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR;
/// Deprecated Set Reservation List discriminator.
pub(crate) use self::constants::DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR;
/// Number of bytes retained in malformed-wire diagnostics.
pub(crate) use self::constants::DIAGNOSTIC_PREFIX_BYTES;
/// Stable event payload contract version.
pub(crate) use self::constants::EVENT_VERSION;
/// Freeze Delegated Account discriminator.
pub(crate) use self::constants::FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR;
/// Current pre-release instruction inventory.
pub(crate) use self::constants::INSTRUCTION_ENTRIES;
/// Lock discriminator.
pub(crate) use self::constants::LOCK_DISCRIMINATOR;
/// Maximum encoded base64 instruction payload size.
pub(crate) use self::constants::MAX_BASE64_BYTES;
/// Maximum number of instruction accounts accepted by this decoder.
pub(crate) use self::constants::MAX_INSTRUCTION_ACCOUNTS;
/// Tracing target for this decoder.
/// Maximum retained instruction payload size.
pub(crate) use self::constants::MAX_INSTRUCTION_BYTES;
/// Migrate discriminator.
pub(crate) use self::constants::MIGRATE_DISCRIMINATOR;
/// Modern Mint discriminator.
pub(crate) use self::constants::MINT_DISCRIMINATOR;
/// Mint New Edition From Master Edition Via Token discriminator.
pub(crate) use self::constants::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR;
/// Mint New Edition From Master Edition Via Vault Proxy discriminator.
pub(crate) use self::constants::MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR;
/// Modern Print discriminator.
pub(crate) use self::constants::PRINT_DISCRIMINATOR;
/// Puff Metadata discriminator.
pub(crate) use self::constants::PUFF_METADATA_DISCRIMINATOR;
/// Remove Creator Verification discriminator.
pub(crate) use self::constants::REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR;
/// Resize discriminator.
pub(crate) use self::constants::RESIZE_DISCRIMINATOR;
/// Revoke Collection Authority discriminator.
pub(crate) use self::constants::REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR;
/// Revoke discriminator.
pub(crate) use self::constants::REVOKE_DISCRIMINATOR;
/// Revoke Use Authority discriminator.
pub(crate) use self::constants::REVOKE_USE_AUTHORITY_DISCRIMINATOR;
/// Set And Verify Collection discriminator.
pub(crate) use self::constants::SET_AND_VERIFY_COLLECTION_DISCRIMINATOR;
/// Set And Verify Sized Collection Item discriminator.
pub(crate) use self::constants::SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR;
/// Set Collection Size discriminator.
pub(crate) use self::constants::SET_COLLECTION_SIZE_DISCRIMINATOR;
/// Set Token Standard discriminator.
pub(crate) use self::constants::SET_TOKEN_STANDARD_DISCRIMINATOR;
/// Sign Metadata discriminator.
pub(crate) use self::constants::SIGN_METADATA_DISCRIMINATOR;
/// Stable decoder surface code.
pub(crate) use self::constants::SURFACE_CODE;
/// Thaw Delegated Account discriminator.
pub(crate) use self::constants::THAW_DELEGATED_ACCOUNT_DISCRIMINATOR;
/// Canonical tracing target for this crate.
pub(crate) use self::constants::TRACING_TARGET;
/// Transfer discriminator.
pub(crate) use self::constants::TRANSFER_DISCRIMINATOR;
/// Transfer Out Of Escrow discriminator.
pub(crate) use self::constants::TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR;
/// Unlock discriminator.
pub(crate) use self::constants::UNLOCK_DISCRIMINATOR;
/// Unverify Collection discriminator.
pub(crate) use self::constants::UNVERIFY_COLLECTION_DISCRIMINATOR;
/// Modern Unverify discriminator.
pub(crate) use self::constants::UNVERIFY_DISCRIMINATOR;
/// Unverify Sized Collection Item discriminator.
pub(crate) use self::constants::UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR;
/// Modern Update discriminator.
pub(crate) use self::constants::UPDATE_DISCRIMINATOR;
/// Historical Update Metadata Account discriminator.
pub(crate) use self::constants::UPDATE_METADATA_ACCOUNT_DISCRIMINATOR;
/// Update Metadata Account V2 discriminator.
pub(crate) use self::constants::UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR;
/// Update Primary Sale Happened Via Token discriminator.
pub(crate) use self::constants::UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR;
/// Modern Use discriminator.
pub(crate) use self::constants::USE_DISCRIMINATOR;
/// Utilize discriminator.
pub(crate) use self::constants::UTILIZE_DISCRIMINATOR;
/// Verify Collection discriminator.
pub(crate) use self::constants::VERIFY_COLLECTION_DISCRIMINATOR;
/// Modern Verify discriminator.
pub(crate) use self::constants::VERIFY_DISCRIMINATOR;
/// Verify Sized Collection Item discriminator.
pub(crate) use self::constants::VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR;
/// Crate-root access to `ParsedInstruction` from `instruction`.
pub(crate) use self::instruction::ParsedInstruction;
/// Crate-root access to `decode` from `instruction`.
pub(crate) use self::instruction::decode;
/// Crate-root access to `entry_for_discriminator` from `instruction`.
pub(crate) use self::instruction::entry_for_discriminator;
/// Crate-root access to `payload_discriminator` from `instruction`.
pub(crate) use self::instruction::payload_discriminator;
/// Canonical projection shared by Collection and Use Authority records.
pub use self::account::AuthorityRecordAccountSnapshot;
/// Canonical projection shared by Metadata and Holder delegate records.
pub use self::account::DelegateRecordAccountSnapshot;
/// Supported edition account layout.
pub use self::account::EditionAccountKind;
/// Canonical bounded projection of one edition or master-edition account.
pub use self::account::EditionAccountSnapshot;
/// Supported Edition Marker account layout.
pub use self::account::EditionMarkerAccountKind;
/// Canonical bounded projection of one Edition Marker account.
pub use self::account::EditionMarkerAccountSnapshot;
/// Exhaustive published Metaplex account-key inventory.
pub use self::account::METADATA_ACCOUNT_LAYOUT_AUDIT;
/// Bounded error returned while decoding a Metadata account.
pub use self::account::MetadataAccountDecodeError;
/// One entry in the exhaustive published account-key audit.
pub use self::account::MetadataAccountLayoutAuditEntry;
/// Canonical bounded projection of one Metadata account.
pub use self::account::MetadataAccountSnapshot;
/// One bounded historical reservation entry.
pub use self::account::ReservationEntrySnapshot;
/// Historical Reservation List account generation.
pub use self::account::ReservationListAccountKind;
/// Canonical decode-only projection of a historical Reservation List account.
pub use self::account::ReservationListAccountSnapshot;
/// Canonical projection of one Token Owned Escrow account.
pub use self::account::TokenOwnedEscrowAccountSnapshot;
/// Authority form used by one Token Owned Escrow account.
pub use self::account::TokenOwnedEscrowAuthorityKind;
/// Canonical bounded projection of one programmable Token Record account.
pub use self::account::TokenRecordAccountSnapshot;
/// Decodes one Collection Authority Record account.
pub use self::account::decode_collection_authority_record_account;
/// Decodes and validates one edition or master-edition account snapshot.
pub use self::account::decode_edition_account;
/// Decodes and validates one Edition Marker account snapshot.
pub use self::account::decode_edition_marker_account;
/// Decodes one Holder Delegate Record account.
pub use self::account::decode_holder_delegate_record_account;
/// Decodes and validates one canonical Metadata account snapshot.
pub use self::account::decode_metadata_account;
/// Decodes one Metadata Delegate Record account.
pub use self::account::decode_metadata_delegate_record_account;
/// Decodes one historical Reservation List V1 or V2 account.
pub use self::account::decode_reservation_list_account;
/// Decodes one Token Owned Escrow account.
pub use self::account::decode_token_owned_escrow_account;
/// Decodes and validates one programmable Token Record account snapshot.
pub use self::account::decode_token_record_account;
/// Decodes one Use Authority Record account.
pub use self::account::decode_use_authority_record_account;
/// Stable identity and policy of one canonical account snapshot.
pub use self::canonical::CanonicalAccountIdentity;
/// Lifecycle class of one canonical account layout.
pub use self::canonical::CanonicalAccountLifecycle;
/// Provenance retained for one canonical account observation.
pub use self::canonical::CanonicalAccountProvenance;
/// Execution policy separated from historical materialization.
pub use self::canonical::CanonicalExecutionPolicy;
/// Materialization policy for active or historical state.
pub use self::canonical::CanonicalMaterializationPolicy;
/// Canonical account envelope used by materializers and replay.
pub use self::canonical::CanonicalMetadataAccountSnapshot;
/// Typed canonical Metaplex account state.
pub use self::canonical::CanonicalMetadataAccountState;
/// Origin of one canonical account observation.
pub use self::canonical::CanonicalObservationSource;
/// Exact Metaplex Token Metadata decoder.
pub use self::decoder::MetadataMetaplexTokenMetadataDecoder;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,425 @@
// file: kb-lib/src/decoder/metadata/metaplex_token_metadata/canonical.rs
// version: 2
//! Canonical Metaplex account identities, provenance and materialization policy.
/// Lifecycle class of one decoded Metaplex account layout.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalAccountLifecycle {
/// Current account layout used by supported runtime flows.
Active,
/// Published account layout whose runtime surface is still experimental.
ActiveExperimental,
/// Historical account layout retained for ledger replay and backfill.
Historical,
}
/// Materialization policy attached to one canonical account snapshot.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalMaterializationPolicy {
/// Materialize the latest committed state of an active account.
ActiveState,
/// Materialize historical state with explicit lifecycle provenance.
HistoricalState,
}
/// Execution policy attached to one canonical account layout.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalExecutionPolicy {
/// The layout belongs to current operations that may later be executable.
CurrentCandidate,
/// The layout belongs to an experimental operation requiring explicit activation.
ExperimentalCandidate,
/// Historical state must never be exposed by an executor.
NeverHistorical,
}
/// Origin of one canonical account observation.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalObservationSource {
/// Account observed from a live subscription or direct live read.
Live,
/// Account reconstructed while replaying already stored transactions.
Replay,
/// Account discovered while backfilling historical ledger data.
Backfill,
/// Account read to repair a detected ingestion gap.
Repair,
/// Synthetic account used only by bounded validation tests.
Synthetic,
}
/// Provenance retained for one canonical account observation.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CanonicalAccountProvenance {
/// Observation source.
pub source: CanonicalObservationSource,
/// Slot associated with the account state when known.
pub slot: std::option::Option<u64>,
/// Provider write version when available.
pub write_version: std::option::Option<u64>,
/// Transaction signature responsible for the state when known.
pub signature: std::option::Option<String>,
/// Instruction index associated with the mutation when known.
pub instruction_index: std::option::Option<u32>,
/// Inner-instruction index associated with the mutation when known.
pub inner_instruction_index: std::option::Option<u32>,
/// Whether the source state is committed according to the caller's boundary.
pub committed: bool,
}
/// Stable identity and policy of one canonical Metaplex account snapshot.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct CanonicalAccountIdentity {
/// Stable identity formed from program id and canonical account address.
pub stable_id: String,
/// Canonical Metaplex Token Metadata program id.
pub program_id: String,
/// Canonical account address.
pub account: String,
/// Published layout name.
pub layout: String,
/// Exact published `Key` discriminant.
pub discriminant: u8,
/// Internal canonical-model version.
pub canonical_version: u16,
/// Published lifecycle class.
pub lifecycle: CanonicalAccountLifecycle,
/// Materialization policy, including historical backfill state.
pub materialization: CanonicalMaterializationPolicy,
/// Execution policy separated from materialization.
pub execution: CanonicalExecutionPolicy,
}
/// Typed state carried by one canonical Metaplex account snapshot.
#[derive(Clone, Debug, PartialEq)]
pub enum CanonicalMetadataAccountState {
/// Metadata account state.
Metadata(crate::decoder::metadata::metaplex_token_metadata::MetadataAccountSnapshot),
/// Master Edition or printed Edition state.
Edition(crate::decoder::metadata::metaplex_token_metadata::EditionAccountSnapshot),
/// Edition Marker state.
EditionMarker(crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountSnapshot),
/// Programmable Token Record state.
TokenRecord(crate::decoder::metadata::metaplex_token_metadata::TokenRecordAccountSnapshot),
/// Metadata or holder delegate state.
DelegateRecord(
crate::decoder::metadata::metaplex_token_metadata::DelegateRecordAccountSnapshot,
),
/// Collection or use authority state.
AuthorityRecord(
crate::decoder::metadata::metaplex_token_metadata::AuthorityRecordAccountSnapshot,
),
/// Token-owned escrow state.
TokenOwnedEscrow(
crate::decoder::metadata::metaplex_token_metadata::TokenOwnedEscrowAccountSnapshot,
),
/// Historical Reservation List state.
ReservationList(
crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountSnapshot,
),
}
/// Canonical envelope used by future materializers and stateful replay.
#[derive(Clone, Debug, PartialEq)]
pub struct CanonicalMetadataAccountSnapshot {
/// Stable identity and lifecycle policy.
pub identity: CanonicalAccountIdentity,
/// Observation provenance.
pub provenance: CanonicalAccountProvenance,
/// Typed bounded state.
pub state: CanonicalMetadataAccountState,
}
fn canonical_identity(
account: &str,
layout: &str,
discriminant: u8,
lifecycle: CanonicalAccountLifecycle,
) -> CanonicalAccountIdentity {
let program_id = kb_program_ids::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID.to_string();
let materialization = match lifecycle {
CanonicalAccountLifecycle::Historical => CanonicalMaterializationPolicy::HistoricalState,
CanonicalAccountLifecycle::Active | CanonicalAccountLifecycle::ActiveExperimental => {
CanonicalMaterializationPolicy::ActiveState
},
};
let execution = match lifecycle {
CanonicalAccountLifecycle::Historical => CanonicalExecutionPolicy::NeverHistorical,
CanonicalAccountLifecycle::Active => CanonicalExecutionPolicy::CurrentCandidate,
CanonicalAccountLifecycle::ActiveExperimental => {
CanonicalExecutionPolicy::ExperimentalCandidate
},
};
return CanonicalAccountIdentity {
stable_id: format!("{program_id}:{account}"),
program_id,
account: account.to_string(),
layout: layout.to_string(),
discriminant,
canonical_version: 1,
lifecycle,
materialization,
execution,
};
}
impl CanonicalMetadataAccountSnapshot {
/// Wraps one Metadata account snapshot with stable identity and provenance.
pub fn from_metadata(
snapshot: crate::decoder::metadata::metaplex_token_metadata::MetadataAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let identity = canonical_identity(
&snapshot.account,
"MetadataV1",
mpl_token_metadata::types::Key::MetadataV1 as u8,
CanonicalAccountLifecycle::Active,
);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::Metadata(snapshot),
};
}
/// Wraps one Edition or Master Edition snapshot with exact lifecycle policy.
pub fn from_edition(
snapshot: crate::decoder::metadata::metaplex_token_metadata::EditionAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let (layout, discriminant, lifecycle) = match snapshot.kind {
crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::MasterEditionV1 => (
"MasterEditionV1",
mpl_token_metadata::types::Key::MasterEditionV1 as u8,
CanonicalAccountLifecycle::Historical,
),
crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::MasterEditionV2 => (
"MasterEditionV2",
mpl_token_metadata::types::Key::MasterEditionV2 as u8,
CanonicalAccountLifecycle::Active,
),
crate::decoder::metadata::metaplex_token_metadata::EditionAccountKind::EditionV1 => (
"EditionV1",
mpl_token_metadata::types::Key::EditionV1 as u8,
CanonicalAccountLifecycle::Active,
),
};
let identity = canonical_identity(&snapshot.account, layout, discriminant, lifecycle);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::Edition(snapshot),
};
}
/// Wraps one Edition Marker snapshot with exact lifecycle policy.
pub fn from_edition_marker(
snapshot: crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let (layout, discriminant, lifecycle) = match snapshot.kind {
crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountKind::EditionMarkerV1 => (
"EditionMarker",
mpl_token_metadata::types::Key::EditionMarker as u8,
CanonicalAccountLifecycle::Active,
),
crate::decoder::metadata::metaplex_token_metadata::EditionMarkerAccountKind::EditionMarkerV2 => (
"EditionMarkerV2",
mpl_token_metadata::types::Key::EditionMarkerV2 as u8,
CanonicalAccountLifecycle::ActiveExperimental,
),
};
let identity = canonical_identity(&snapshot.account, layout, discriminant, lifecycle);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::EditionMarker(snapshot),
};
}
/// Wraps one Token Record snapshot.
pub fn from_token_record(
snapshot: crate::decoder::metadata::metaplex_token_metadata::TokenRecordAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let identity = canonical_identity(
&snapshot.account,
"TokenRecord",
mpl_token_metadata::types::Key::TokenRecord as u8,
CanonicalAccountLifecycle::Active,
);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::TokenRecord(snapshot),
};
}
/// Wraps one Metadata or Holder Delegate snapshot.
pub fn from_delegate_record(
snapshot: crate::decoder::metadata::metaplex_token_metadata::DelegateRecordAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let (layout, discriminant) = if snapshot.kind == "MetadataDelegateRecord" {
("MetadataDelegate", mpl_token_metadata::types::Key::MetadataDelegate as u8)
} else {
("HolderDelegate", mpl_token_metadata::types::Key::HolderDelegate as u8)
};
let identity = canonical_identity(
&snapshot.account,
layout,
discriminant,
CanonicalAccountLifecycle::Active,
);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::DelegateRecord(snapshot),
};
}
/// Wraps one Collection or Use Authority snapshot.
pub fn from_authority_record(
snapshot: crate::decoder::metadata::metaplex_token_metadata::AuthorityRecordAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let (layout, discriminant) = if snapshot.kind == "CollectionAuthorityRecord" {
(
"CollectionAuthorityRecord",
mpl_token_metadata::types::Key::CollectionAuthorityRecord as u8,
)
} else {
("UseAuthorityRecord", mpl_token_metadata::types::Key::UseAuthorityRecord as u8)
};
let identity = canonical_identity(
&snapshot.account,
layout,
discriminant,
CanonicalAccountLifecycle::Active,
);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::AuthorityRecord(snapshot),
};
}
/// Wraps one Token Owned Escrow snapshot.
pub fn from_token_owned_escrow(
snapshot: crate::decoder::metadata::metaplex_token_metadata::TokenOwnedEscrowAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let identity = canonical_identity(
&snapshot.account,
"TokenOwnedEscrow",
mpl_token_metadata::types::Key::TokenOwnedEscrow as u8,
CanonicalAccountLifecycle::Active,
);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::TokenOwnedEscrow(snapshot),
};
}
/// Wraps one historical Reservation List snapshot as materializable historical state.
pub fn from_reservation_list(
snapshot: crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountSnapshot,
provenance: CanonicalAccountProvenance,
) -> Self {
let (layout, discriminant) = match snapshot.kind {
crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V1 => {
("ReservationListV1", mpl_token_metadata::types::Key::ReservationListV1 as u8)
},
crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V2 => {
("ReservationListV2", mpl_token_metadata::types::Key::ReservationListV2 as u8)
},
};
let identity = canonical_identity(
&snapshot.account,
layout,
discriminant,
CanonicalAccountLifecycle::Historical,
);
return Self {
identity,
provenance,
state: CanonicalMetadataAccountState::ReservationList(snapshot),
};
}
}
#[cfg(test)]
mod tests {
#[test]
fn historical_state_is_materializable_but_never_executable() {
let snapshot = crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountSnapshot {
account: "reservation-account".to_string(),
bump: 1,
kind: crate::decoder::metadata::metaplex_token_metadata::ReservationListAccountKind::V1,
master_edition: "master-edition".to_string(),
resource: "resource".to_string(),
supply_snapshot: std::option::Option::Some(7),
reservations: std::vec::Vec::new(),
total_reservation_spots: 0,
current_reservation_spots: 0,
payload_json: serde_json::json!({}),
};
let provenance = super::CanonicalAccountProvenance {
source: super::CanonicalObservationSource::Backfill,
slot: std::option::Option::Some(42),
write_version: std::option::Option::None,
signature: std::option::Option::Some("historical-signature".to_string()),
instruction_index: std::option::Option::Some(3),
inner_instruction_index: std::option::Option::None,
committed: true,
};
let canonical =
super::CanonicalMetadataAccountSnapshot::from_reservation_list(snapshot, provenance);
assert_eq!(canonical.identity.lifecycle, super::CanonicalAccountLifecycle::Historical);
assert_eq!(
canonical.identity.materialization,
super::CanonicalMaterializationPolicy::HistoricalState
);
assert_eq!(canonical.identity.execution, super::CanonicalExecutionPolicy::NeverHistorical);
assert_eq!(canonical.provenance.source, super::CanonicalObservationSource::Backfill);
assert!(canonical.identity.stable_id.ends_with(":reservation-account"));
}
#[test]
fn active_and_experimental_layouts_keep_distinct_policies() {
let metadata = crate::decoder::metadata::metaplex_token_metadata::MetadataAccountSnapshot {
account: "metadata-account".to_string(),
bump: 1,
mint: "mint".to_string(),
update_authority: "authority".to_string(),
name: "name".to_string(),
symbol: "symbol".to_string(),
uri: "uri".to_string(),
seller_fee_basis_points: 0,
primary_sale_happened: false,
is_mutable: true,
payload_json: serde_json::json!({}),
};
let provenance = super::CanonicalAccountProvenance {
source: super::CanonicalObservationSource::Live,
slot: std::option::Option::Some(1),
write_version: std::option::Option::Some(2),
signature: std::option::Option::None,
instruction_index: std::option::Option::None,
inner_instruction_index: std::option::Option::None,
committed: true,
};
let canonical =
super::CanonicalMetadataAccountSnapshot::from_metadata(metadata, provenance);
assert_eq!(canonical.identity.lifecycle, super::CanonicalAccountLifecycle::Active);
assert_eq!(
canonical.identity.materialization,
super::CanonicalMaterializationPolicy::ActiveState
);
assert_eq!(canonical.identity.execution, super::CanonicalExecutionPolicy::CurrentCandidate);
assert_eq!(canonical.identity.discriminant, 4);
assert_eq!(canonical.identity.canonical_version, 1);
}
}

View File

@@ -0,0 +1,257 @@
// file: kb-lib/src/decoder/metadata/metaplex_token_metadata/constants.rs
// version: 29
//! Internal constants for Metaplex Token Metadata decoding.
/// Stable decoder surface code.
pub(crate) const SURFACE_CODE: &str = "metadata_metaplex_token_metadata";
/// Maximum retained instruction payload size.
pub(crate) const MAX_INSTRUCTION_BYTES: usize = 16_384;
/// Maximum encoded base64 instruction payload size.
pub(crate) const MAX_BASE64_BYTES: usize = 21_852;
/// Maximum number of instruction accounts accepted by this decoder.
pub(crate) const MAX_INSTRUCTION_ACCOUNTS: usize = 64;
/// Number of bytes retained in malformed-wire diagnostics.
pub(crate) const DIAGNOSTIC_PREFIX_BYTES: usize = 32;
/// Stable event payload contract version.
pub(crate) const EVENT_VERSION: u32 = 1;
/// Deprecated Create Master Edition discriminator.
pub(crate) const DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR: u8 = 2;
/// Deprecated Set Reservation List discriminator.
pub(crate) const DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR: u8 = 5;
/// Deprecated Create Reservation List discriminator.
pub(crate) const DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR: u8 = 6;
/// Deprecated Mint Printing Tokens Via Token discriminator.
pub(crate) const DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR: u8 = 8;
/// Deprecated Mint Printing Tokens discriminator.
pub(crate) const DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR: u8 = 9;
/// Historical Create Master Edition discriminator.
pub(crate) const CREATE_MASTER_EDITION_DISCRIMINATOR: u8 = 10;
/// Deprecated printing-token mint-new-edition discriminator.
pub(crate) const DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR: u8 = 3;
/// Historical Create Metadata Account discriminator.
pub(crate) const CREATE_METADATA_ACCOUNT_DISCRIMINATOR: u8 = 0;
/// Historical Update Metadata Account discriminator.
pub(crate) const UPDATE_METADATA_ACCOUNT_DISCRIMINATOR: u8 = 1;
/// Historical Create Metadata Account V2 discriminator.
pub(crate) const CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR: u8 = 16;
/// Create Metadata Account V3 discriminator.
pub(crate) const CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR: u8 = 33;
/// Update Metadata Account V2 discriminator.
pub(crate) const UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR: u8 = 15;
/// Verify Collection discriminator.
pub(crate) const VERIFY_COLLECTION_DISCRIMINATOR: u8 = 18;
/// Unverify Collection discriminator.
pub(crate) const UNVERIFY_COLLECTION_DISCRIMINATOR: u8 = 22;
/// Set And Verify Collection discriminator.
pub(crate) const SET_AND_VERIFY_COLLECTION_DISCRIMINATOR: u8 = 25;
/// Approve Collection Authority discriminator.
pub(crate) const APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR: u8 = 23;
/// Revoke Collection Authority discriminator.
pub(crate) const REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR: u8 = 24;
/// Verify Sized Collection Item discriminator.
pub(crate) const VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 30;
/// Unverify Sized Collection Item discriminator.
pub(crate) const UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 31;
/// Set And Verify Sized Collection Item discriminator.
pub(crate) const SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR: u8 = 32;
/// Sign Metadata discriminator.
pub(crate) const SIGN_METADATA_DISCRIMINATOR: u8 = 7;
/// Update Primary Sale Happened Via Token discriminator.
pub(crate) const UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR: u8 = 4;
/// Utilize discriminator.
pub(crate) const UTILIZE_DISCRIMINATOR: u8 = 19;
/// Approve Use Authority discriminator.
pub(crate) const APPROVE_USE_AUTHORITY_DISCRIMINATOR: u8 = 20;
/// Revoke Use Authority discriminator.
pub(crate) const REVOKE_USE_AUTHORITY_DISCRIMINATOR: u8 = 21;
/// Puff Metadata discriminator.
pub(crate) const PUFF_METADATA_DISCRIMINATOR: u8 = 14;
/// Freeze Delegated Account discriminator.
pub(crate) const FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR: u8 = 26;
/// Thaw Delegated Account discriminator.
pub(crate) const THAW_DELEGATED_ACCOUNT_DISCRIMINATOR: u8 = 27;
/// Remove Creator Verification discriminator.
pub(crate) const REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR: u8 = 28;
/// Set Token Standard discriminator.
pub(crate) const SET_TOKEN_STANDARD_DISCRIMINATOR: u8 = 35;
/// Mint New Edition From Master Edition Via Token discriminator.
pub(crate) const MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR: u8 = 11;
/// Mint New Edition From Master Edition Via Vault Proxy discriminator.
pub(crate) const MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR: u8 = 13;
/// Convert Master Edition V1 to V2 discriminator.
pub(crate) const CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR: u8 = 12;
/// Create Master Edition V3 discriminator.
pub(crate) const CREATE_MASTER_EDITION_V3_DISCRIMINATOR: u8 = 17;
/// Set Collection Size discriminator.
pub(crate) const SET_COLLECTION_SIZE_DISCRIMINATOR: u8 = 34;
/// Bubblegum Set Collection Size discriminator.
pub(crate) const BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR: u8 = 36;
/// Create Escrow Account discriminator.
pub(crate) const CREATE_ESCROW_ACCOUNT_DISCRIMINATOR: u8 = 38;
/// Close Escrow Account discriminator.
pub(crate) const CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR: u8 = 39;
/// Transfer Out Of Escrow discriminator.
pub(crate) const TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR: u8 = 40;
/// Collect discriminator.
pub(crate) const COLLECT_DISCRIMINATOR: u8 = 54;
/// Historical Burn NFT discriminator.
pub(crate) const BURN_NFT_DISCRIMINATOR: u8 = 29;
/// Historical Burn Edition NFT discriminator.
pub(crate) const BURN_EDITION_NFT_DISCRIMINATOR: u8 = 37;
/// Burn discriminator.
pub(crate) const BURN_DISCRIMINATOR: u8 = 41;
/// Lock discriminator.
pub(crate) const LOCK_DISCRIMINATOR: u8 = 46;
/// Unlock discriminator.
pub(crate) const UNLOCK_DISCRIMINATOR: u8 = 47;
/// Transfer discriminator.
pub(crate) const TRANSFER_DISCRIMINATOR: u8 = 49;
/// Close Accounts discriminator.
pub(crate) const CLOSE_ACCOUNTS_DISCRIMINATOR: u8 = 57;
/// Modern Create discriminator.
pub(crate) const CREATE_DISCRIMINATOR: u8 = 42;
/// Modern Mint discriminator.
pub(crate) const MINT_DISCRIMINATOR: u8 = 43;
/// Modern Print discriminator.
pub(crate) const PRINT_DISCRIMINATOR: u8 = 55;
/// Modern Update discriminator.
pub(crate) const UPDATE_DISCRIMINATOR: u8 = 50;
/// Modern Use discriminator.
pub(crate) const USE_DISCRIMINATOR: u8 = 51;
/// Modern Verify discriminator.
pub(crate) const VERIFY_DISCRIMINATOR: u8 = 52;
/// Modern Unverify discriminator.
pub(crate) const UNVERIFY_DISCRIMINATOR: u8 = 53;
/// Migrate discriminator.
pub(crate) const MIGRATE_DISCRIMINATOR: u8 = 48;
/// Resize discriminator.
pub(crate) const RESIZE_DISCRIMINATOR: u8 = 56;
/// Delegate discriminator.
pub(crate) const DELEGATE_DISCRIMINATOR: u8 = 44;
/// Revoke discriminator.
pub(crate) const REVOKE_DISCRIMINATOR: u8 = 45;
/// Current pre-release instruction inventory.
pub(crate) const INSTRUCTION_ENTRIES: &[(u8, &str, bool)] = &[
(CREATE_METADATA_ACCOUNT_DISCRIMINATOR, "create_metadata_account", true),
(
DEPRECATED_CREATE_MASTER_EDITION_DISCRIMINATOR,
"deprecated_create_master_edition",
true,
),
(
DEPRECATED_MINT_NEW_EDITION_VIA_PRINTING_TOKEN_DISCRIMINATOR,
"deprecated_mint_new_edition_from_master_edition_via_printing_token",
true,
),
(UPDATE_METADATA_ACCOUNT_DISCRIMINATOR, "update_metadata_account", true),
(
UPDATE_PRIMARY_SALE_HAPPENED_VIA_TOKEN_DISCRIMINATOR,
"update_primary_sale_happened_via_token",
false,
),
(
DEPRECATED_SET_RESERVATION_LIST_DISCRIMINATOR,
"deprecated_set_reservation_list",
true,
),
(
DEPRECATED_CREATE_RESERVATION_LIST_DISCRIMINATOR,
"deprecated_create_reservation_list",
true,
),
(SIGN_METADATA_DISCRIMINATOR, "sign_metadata", false),
(
DEPRECATED_MINT_PRINTING_TOKENS_VIA_TOKEN_DISCRIMINATOR,
"deprecated_mint_printing_tokens_via_token",
true,
),
(
DEPRECATED_MINT_PRINTING_TOKENS_DISCRIMINATOR,
"deprecated_mint_printing_tokens",
true,
),
(CREATE_MASTER_EDITION_DISCRIMINATOR, "create_master_edition", true),
(PUFF_METADATA_DISCRIMINATOR, "puff_metadata", false),
(
MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_TOKEN_DISCRIMINATOR,
"mint_new_edition_from_master_edition_via_token",
false,
),
(
MINT_NEW_EDITION_FROM_MASTER_EDITION_VIA_VAULT_PROXY_DISCRIMINATOR,
"mint_new_edition_from_master_edition_via_vault_proxy",
true,
),
(
CONVERT_MASTER_EDITION_V1_TO_V2_DISCRIMINATOR,
"convert_master_edition_v1_to_v2",
true,
),
(UPDATE_METADATA_ACCOUNT_V2_DISCRIMINATOR, "update_metadata_account_v2", false),
(CREATE_METADATA_ACCOUNT_V2_DISCRIMINATOR, "create_metadata_account_v2", true),
(CREATE_MASTER_EDITION_V3_DISCRIMINATOR, "create_master_edition_v3", false),
(CREATE_METADATA_ACCOUNT_V3_DISCRIMINATOR, "create_metadata_account_v3", false),
(VERIFY_COLLECTION_DISCRIMINATOR, "verify_collection", false),
(UNVERIFY_COLLECTION_DISCRIMINATOR, "unverify_collection", false),
(SET_AND_VERIFY_COLLECTION_DISCRIMINATOR, "set_and_verify_collection", false),
(
APPROVE_COLLECTION_AUTHORITY_DISCRIMINATOR,
"approve_collection_authority",
false,
),
(REVOKE_COLLECTION_AUTHORITY_DISCRIMINATOR, "revoke_collection_authority", false),
(
VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR,
"verify_sized_collection_item",
false,
),
(
UNVERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR,
"unverify_sized_collection_item",
false,
),
(
SET_AND_VERIFY_SIZED_COLLECTION_ITEM_DISCRIMINATOR,
"set_and_verify_sized_collection_item",
false,
),
(UTILIZE_DISCRIMINATOR, "utilize", false),
(APPROVE_USE_AUTHORITY_DISCRIMINATOR, "approve_use_authority", false),
(REVOKE_USE_AUTHORITY_DISCRIMINATOR, "revoke_use_authority", false),
(FREEZE_DELEGATED_ACCOUNT_DISCRIMINATOR, "freeze_delegated_account", true),
(THAW_DELEGATED_ACCOUNT_DISCRIMINATOR, "thaw_delegated_account", true),
(REMOVE_CREATOR_VERIFICATION_DISCRIMINATOR, "remove_creator_verification", false),
(SET_TOKEN_STANDARD_DISCRIMINATOR, "set_token_standard", false),
(SET_COLLECTION_SIZE_DISCRIMINATOR, "set_collection_size", false),
(
BUBBLEGUM_SET_COLLECTION_SIZE_DISCRIMINATOR,
"bubblegum_set_collection_size",
false,
),
(CREATE_ESCROW_ACCOUNT_DISCRIMINATOR, "create_escrow_account", false),
(CLOSE_ESCROW_ACCOUNT_DISCRIMINATOR, "close_escrow_account", false),
(TRANSFER_OUT_OF_ESCROW_DISCRIMINATOR, "transfer_out_of_escrow", false),
(BURN_NFT_DISCRIMINATOR, "burn_nft", true),
(BURN_EDITION_NFT_DISCRIMINATOR, "burn_edition_nft", true),
(BURN_DISCRIMINATOR, "burn", false),
(CREATE_DISCRIMINATOR, "create", false),
(MINT_DISCRIMINATOR, "mint", false),
(LOCK_DISCRIMINATOR, "lock", false),
(UNLOCK_DISCRIMINATOR, "unlock", false),
(TRANSFER_DISCRIMINATOR, "transfer", false),
(COLLECT_DISCRIMINATOR, "collect", false),
(PRINT_DISCRIMINATOR, "print", false),
(UPDATE_DISCRIMINATOR, "update", false),
(USE_DISCRIMINATOR, "use", false),
(VERIFY_DISCRIMINATOR, "verify", false),
(UNVERIFY_DISCRIMINATOR, "unverify", false),
(MIGRATE_DISCRIMINATOR, "migrate", false),
(RESIZE_DISCRIMINATOR, "resize", false),
(CLOSE_ACCOUNTS_DISCRIMINATOR, "close_accounts", false),
(DELEGATE_DISCRIMINATOR, "delegate", false),
(REVOKE_DISCRIMINATOR, "revoke", false),
];
/// Canonical tracing target for this decoder.
pub(crate) const TRACING_TARGET: &str = "kb-lib.decoder.metadata.metaplex_token_metadata";

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
// file: kb-lib/src/lib.rs
// version: 10
// version: 11
//! Consolidated decoder, executor, materializer and shared model library.
#![warn(missing_docs)]
@@ -291,6 +291,8 @@ pub(crate) use crate::decoder::spl_token_payload_tag;
pub use crate::decoder::ELGAMAL_REGISTRY_ACCOUNT_LEN;
/// Parsed SPL ElGamal public-key registry account.
pub use crate::decoder::ElGamalRegistryState;
/// Exact decoder for the Metaplex Token Metadata program.
pub use crate::decoder::MetadataMetaplexTokenMetadataDecoder;
/// Exact decoder for the SPL Associated Token Account program.
pub use crate::decoder::SplAssociatedTokenAccountDecoder;
/// Exact decoder for the SPL ElGamal registry program.

View File

@@ -1,11 +1,11 @@
<!-- file: kb-program-ids/README.md -->
<!-- version: 5 -->
<!-- version: 6 -->
# kb-program-ids
`kb-program-ids` est la source unique des identifiants de programmes Solana et des comptes natifs connus utilisés par le workspace.
La tranche `0.1.0-pre.004` expose les 18 surfaces exécutables nécessaires au décodeur Solana Core, les comptes natifs associés utilisés par leurs contrats et lidentifiant SPL Token classique employé par les tests de frontière. La tranche `0.1.0-pre.005` ajoute les trois identifiants SPL Memo v1, v3 et v4 sans les classer parmi les surfaces natives. `0.1.0-pre.006` active lidentifiant SPL Token classique dans un décodeur concret tout en le maintenant hors des surfaces natives. `0.1.0-pre.007` ajoute les identifiants SPL Associated Token Account et Token2022 nécessaires à la frontière ATA. `0.1.0-pre.008` ajoute le Program ID indépendant du registre ElGamal de Token2022, toujours hors des surfaces natives.
La tranche `0.1.0-pre.004` expose les 18 surfaces exécutables nécessaires au décodeur Solana Core, les comptes natifs associés utilisés par leurs contrats et lidentifiant SPL Token classique employé par les tests de frontière. La tranche `0.1.0-pre.005` ajoute les trois identifiants SPL Memo v1, v3 et v4 sans les classer parmi les surfaces natives. `0.1.0-pre.006` active lidentifiant SPL Token classique dans un décodeur concret tout en le maintenant hors des surfaces natives. `0.1.0-pre.007` ajoute les identifiants SPL Associated Token Account et Token2022 nécessaires à la frontière ATA. `0.1.0-pre.008` ajoute le Program ID indépendant du registre ElGamal de Token2022. `0.1.0-pre.009` ajoute le Program ID indépendant de Metaplex Token Metadata. Ces programmes restent hors des surfaces natives.
`constants.rs` reste lunique source des adresses et des tableaux statiques. `programs.rs` porte
`ProgramIdEntry`, ses méthodes et toutes les fonctions de consultation. `lib.rs` se limite aux

View File

@@ -1,5 +1,5 @@
// file: kb-program-ids/src/constants.rs
// version: 4
// version: 5
//! Canonical Solana program and well-known account identifiers.
@@ -27,6 +27,9 @@ pub const INCINERATOR_PROGRAM_ID: &str = "1nc1nerator111111111111111111111111111
pub const LOADER_V4_PROGRAM_ID: &str = "LoaderV411111111111111111111111111111111111";
/// Native Loader program identifier.
pub const NATIVE_LOADER_PROGRAM_ID: &str = "NativeLoader1111111111111111111111111111111";
/// Metaplex Token Metadata program identifier.
pub const METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID: &str =
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
/// Secp256k1 precompile program identifier.
pub const SECP256K1_PROGRAM_ID: &str = "KeccakSecp256k11111111111111111111111111111";
/// Secp256r1 precompile program identifier.
@@ -198,6 +201,10 @@ pub(crate) const PROGRAM_ID_ENTRIES: &[crate::ProgramIdEntry] = &[
name: "incinerator",
address: crate::INCINERATOR_PROGRAM_ID,
},
crate::ProgramIdEntry {
name: "metadata_metaplex_token_metadata",
address: crate::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID,
},
crate::ProgramIdEntry {
name: "loader_v4",
address: crate::LOADER_V4_PROGRAM_ID,

View File

@@ -1,5 +1,5 @@
// file: kb-program-ids/src/lib.rs
// version: 7
// version: 8
#![forbid(unsafe_code)]
#![deny(unreachable_pub)]
@@ -39,6 +39,8 @@ pub use constants::FEATURE_PROGRAM_ID;
pub use constants::INCINERATOR_PROGRAM_ID;
/// Loader version 4 program identifier.
pub use constants::LOADER_V4_PROGRAM_ID;
/// Metaplex Token Metadata program identifier.
pub use constants::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID;
/// Native Loader program identifier.
pub use constants::NATIVE_LOADER_PROGRAM_ID;
/// Secp256k1 precompile program identifier.

View File

@@ -1,5 +1,5 @@
// file: kb-program-ids/src/programs.rs
// version: 1
// version: 2
//! Enumerable canonical program registry.
@@ -65,7 +65,7 @@ mod tests {
assert!(codes.insert(entry.code()));
assert!(program_ids.insert(entry.program_id()));
}
assert_eq!(crate::registered_program_ids().len(), 32);
assert_eq!(crate::registered_program_ids().len(), 33);
}
#[test]
@@ -122,8 +122,8 @@ mod tests {
}
#[test]
fn spl_primitives_are_registered_without_joining_native_surfaces() {
let spl_program_ids = [
fn protocol_primitives_are_registered_without_joining_native_surfaces() {
let protocol_program_ids = [
crate::SPL_MEMO_V1_PROGRAM_ID,
crate::SPL_MEMO_V3_PROGRAM_ID,
crate::SPL_MEMO_V4_PROGRAM_ID,
@@ -131,8 +131,9 @@ mod tests {
crate::SPL_TOKEN_2022_PROGRAM_ID,
crate::SPL_TOKEN_2022_ELGAMAL_REGISTRY_PROGRAM_ID,
crate::ASSOCIATED_TOKEN_PROGRAM_ID,
crate::METADATA_METAPLEX_TOKEN_METADATA_PROGRAM_ID,
];
for program_id in spl_program_ids {
for program_id in protocol_program_ids {
assert!(crate::find_registered_program_id(program_id).is_some());
assert!(
!crate::native_program_ids()