0.4.7-pre.002
This commit is contained in:
@@ -1,8 +1,16 @@
|
||||
<!-- file: kb-lib/CHANGELOG.md -->
|
||||
<!-- version: 6 -->
|
||||
<!-- version: 7 -->
|
||||
|
||||
# CHANGELOG — kb-lib
|
||||
|
||||
## 0.4.7-pre.002 — contrat Metaplex fermé
|
||||
|
||||
- classification exhaustive des 58 discriminants Metaplex Token Metadata ;
|
||||
- comptes positionnels et signers importés de l’IDL archivée `V1_14_0` ;
|
||||
- propriété unique des faits metadata, admin, lifecycle et risk/compliance ;
|
||||
- exposition directe des créateurs, collection, uses, token standard et programmable config dans le snapshot metadata autoritatif ;
|
||||
- tests contractuels d’exhaustivité, d’unicité et de séparation avec Token-2022.
|
||||
|
||||
## 0.4.6
|
||||
|
||||
- alignement de la crate sur la version fonctionnelle bot3 `0.4.6` ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: kb-lib/README.md -->
|
||||
<!-- version: 14 -->
|
||||
<!-- version: 15 -->
|
||||
|
||||
# kb-lib
|
||||
|
||||
@@ -56,7 +56,7 @@ Les matrices actives sont maintenues sous [`../test-fixtures/contract-matrices/`
|
||||
|
||||
## Statut et limites
|
||||
|
||||
La migration des surfaces historiques jusqu’à un périmètre proche de bot2 `0.4.6` est largement réalisée. Le décodeur et les matérialisations Metaplex Token Metadata sont présents, mais l’exécuteur et la clôture fonctionnelle de cette surface restent à réaliser. Le registre ElGamal n’est pas déclaré validé sur Devnet ou Mainnet.
|
||||
La migration des surfaces historiques jusqu’à un périmètre proche de bot2 `0.4.6` est largement réalisée. Le décodeur Metaplex Token Metadata couvre les 58 discriminants et les matérialisations possèdent désormais un contrat fermé de propriété des faits. L’exécuteur et la clôture fonctionnelle de cette surface restent à réaliser entre `0.4.7-pre.003` et `pre.006`. Le registre ElGamal n’est pas déclaré validé sur Devnet ou Mainnet.
|
||||
|
||||
## Documents
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<!-- file: kb-lib/TODO.md -->
|
||||
<!-- version: 3 -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# TODO — kb-lib
|
||||
|
||||
## Entre `0.4.6` et `0.4.7` — Metaplex Token Metadata
|
||||
|
||||
- [ ] Matérialisation - vérifier la couverture exacte migrée depuis bot2.
|
||||
- [ ] Matérialisation - compléter uniquement les projections réellement manquantes.
|
||||
- [x] Matérialisation - vérifier la couverture exacte migrée depuis bot2.
|
||||
- [x] Matérialisation - compléter uniquement les projections réellement manquantes et fermer leur propriété unique.
|
||||
- [ ] Exécution - implémenter l’exécuteur à partir des contrats officiels vérifiés.
|
||||
- [ ] Tests - ajouter les tests unitaires et contractuels de l’exécuteur.
|
||||
- [ ] Intégration - préparer les contrats nécessaires au pipeline et aux démonstrations.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-lib/src/decoder/metadata/metaplex_token_metadata/decoder.rs
|
||||
// version: 30
|
||||
// version: 31
|
||||
|
||||
//! Exact contextual dispatch for Metaplex Token Metadata.
|
||||
|
||||
@@ -3051,6 +3051,80 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_contract_closes_all_instruction_statuses_and_idl_accounts() {
|
||||
let matrix: serde_json::Value = match serde_json::from_str(AUDIT_MATRIX_JSON) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => panic!("matrix parse failed: {error}"),
|
||||
};
|
||||
let entries = match matrix
|
||||
.get("instruction_execution_contract")
|
||||
.and_then(serde_json::Value::as_array)
|
||||
{
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("instruction_execution_contract missing"),
|
||||
};
|
||||
assert_eq!(entries.len(), 58);
|
||||
let mut discriminators = std::collections::BTreeSet::new();
|
||||
for entry in entries {
|
||||
let discriminator = match entry
|
||||
.get("discriminator")
|
||||
.and_then(serde_json::Value::as_u64)
|
||||
{
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("instruction discriminator missing"),
|
||||
};
|
||||
assert!(discriminators.insert(discriminator));
|
||||
assert!(entry.get("accounts").is_some_and(serde_json::Value::is_array));
|
||||
assert!(entry.get("signers").is_some_and(serde_json::Value::is_array));
|
||||
assert!(entry
|
||||
.get("coverage_status")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.is_some_and(|value| return value != "pending" && !value.is_empty()));
|
||||
assert!(entry
|
||||
.get("execute")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.is_some_and(|value| return value != "pending" && !value.is_empty()));
|
||||
}
|
||||
assert_eq!(discriminators, (0u64..58u64).collect());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_002_fact_ownership_is_unique_and_keeps_metadata_domains_separate() {
|
||||
let matrix: serde_json::Value = match serde_json::from_str(AUDIT_MATRIX_JSON) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => panic!("matrix parse failed: {error}"),
|
||||
};
|
||||
let facts = match matrix
|
||||
.get("fact_ownership_contract")
|
||||
.and_then(serde_json::Value::as_array)
|
||||
{
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("fact_ownership_contract missing"),
|
||||
};
|
||||
let mut names = std::collections::BTreeSet::new();
|
||||
for entry in facts {
|
||||
let fact = match entry.get("fact").and_then(serde_json::Value::as_str) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("fact name missing"),
|
||||
};
|
||||
assert!(names.insert(fact));
|
||||
assert!(entry
|
||||
.get("owner")
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.is_some_and(|value| return !value.is_empty()));
|
||||
}
|
||||
let forbidden = match matrix
|
||||
.pointer("/fact_ownership_proof/cross_domain_merge_forbidden")
|
||||
.and_then(serde_json::Value::as_array)
|
||||
{
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("cross-domain proof missing"),
|
||||
};
|
||||
assert!(forbidden.contains(&serde_json::json!("metaplex_token_metadata")));
|
||||
assert!(forbidden.contains(&serde_json::json!("spl_token_2022_embedded_metadata")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn omitted_historical_discriminators_reject_invalid_wires() {
|
||||
let decoder = crate::DcMetadataMetaplexTokenMetadataDecoder;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-lib/src/materializer/metadata/core.rs
|
||||
// version: 5
|
||||
// version: 6
|
||||
|
||||
//! Stable Token-2022 and Metaplex metadata snapshot materializer.
|
||||
|
||||
@@ -134,6 +134,11 @@ pub fn materializer_metadata_materialize_metaplex_metadata_snapshot(
|
||||
"symbol": metadata.symbol,
|
||||
"uri": metadata.uri,
|
||||
"sellerFeeBasisPoints": metadata.seller_fee_basis_points,
|
||||
"creators": metadata.payload_json.get("creators").cloned().unwrap_or(serde_json::Value::Null),
|
||||
"collection": metadata.payload_json.get("collection").cloned().unwrap_or(serde_json::Value::Null),
|
||||
"uses": metadata.payload_json.get("uses").cloned().unwrap_or(serde_json::Value::Null),
|
||||
"tokenStandard": metadata.payload_json.get("tokenStandard").cloned().unwrap_or(serde_json::Value::Null),
|
||||
"programmableConfig": metadata.payload_json.get("programmableConfig").cloned().unwrap_or(serde_json::Value::Null),
|
||||
"primarySaleHappened": metadata.primary_sale_happened,
|
||||
"isMutable": metadata.is_mutable,
|
||||
"layout": snapshot.identity.layout,
|
||||
@@ -218,6 +223,18 @@ mod tests_metaplex_metadata_state {
|
||||
first.as_ref().map(|value| return value.payload_json["metadataSource"].clone()),
|
||||
std::result::Result::Ok(serde_json::json!("metaplex_owned_account"))
|
||||
);
|
||||
assert_eq!(
|
||||
first.as_ref().map(|value| return value.payload_json["creators"].clone()),
|
||||
std::result::Result::Ok(
|
||||
serde_json::json!([{"address":"creator111","verified":true,"share":100}])
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
first
|
||||
.as_ref()
|
||||
.map(|value| return value.payload_json["programmableConfig"].clone()),
|
||||
std::result::Result::Ok(serde_json::json!({"ruleSet":"rules111"}))
|
||||
);
|
||||
assert_eq!(
|
||||
first
|
||||
.as_ref()
|
||||
|
||||
Reference in New Issue
Block a user