v0.4.7-pre.014
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 20
|
# version: 21
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
@@ -18,7 +18,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.4.7-pre.13"
|
version = "0.4.7-pre.14"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3"
|
repository = "https://git.sasedev.com/Sasedev/khadhroony-bot3"
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<!-- file: docs/validation/V0_4_7_PRE_014_METAPLEX_COHERENT_DEVNET_JOURNEYS.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Validation `0.4.7-pre.014` — parcours Metaplex Devnet cohérents
|
||||||
|
|
||||||
|
## Objet
|
||||||
|
|
||||||
|
Cette prérelease étend le runner Metadata depuis le seul parcours NFT vers cinq parcours Devnet préparables : NFT, SFT, fungible, collection parent et pNFT sans rule set.
|
||||||
|
|
||||||
|
Chaque parcours expose d'abord un cycle borné et comparable :
|
||||||
|
|
||||||
|
1. création native d'un mint SPL classique par le workspace ;
|
||||||
|
2. préparation contextuelle de `Create` ;
|
||||||
|
3. simulation exacte ;
|
||||||
|
4. soumission et confirmation explicites ;
|
||||||
|
5. relecture et matérialisation optionnelle des comptes applicables ;
|
||||||
|
6. préparation de `UpdateAsUpdateAuthorityV2` depuis l'état créé ;
|
||||||
|
7. simulation, soumission, confirmation et postconditions.
|
||||||
|
|
||||||
|
## Familles et contrats Create
|
||||||
|
|
||||||
|
| Parcours | `token_standard` | Edition relue | Particularité |
|
||||||
|
|------------|---------------------------|--------------:|-----------------------------------------|
|
||||||
|
| NFT | `NonFungible` | oui | `print_supply = Zero` |
|
||||||
|
| SFT | `FungibleAsset` | non | `decimals = 0`, pas de master edition |
|
||||||
|
| Fungible | `Fungible` | non | `decimals = 0`, pas de master edition |
|
||||||
|
| Collection | `NonFungible` | oui | `collection_details = V1(size=0)` |
|
||||||
|
| pNFT | `ProgrammableNonFungible` | oui | aucun rule set pour ce premier parcours |
|
||||||
|
|
||||||
|
## Limite volontaire
|
||||||
|
|
||||||
|
Cette prérelease ne déclare pas encore validées les opérations spécialisées `mint`, `verify`, `unverify`, `delegate`, `lock`, `unlock`, `transfer`, `revoke`, `burn`, `resize` et apparentées. Elles doivent être ajoutées comme étapes dépendantes d'un contexte confirmé, pas comme modèles JSON isolés.
|
||||||
|
|
||||||
|
## Validation attendue
|
||||||
|
|
||||||
|
- `cargo fmt --all` ;
|
||||||
|
- `cargo check --workspace` ;
|
||||||
|
- `cargo clippy --all-targets` ;
|
||||||
|
- `python3 scripts/audit_rust_workspace_rules.py` ;
|
||||||
|
- `cargo test -p kb-pipeline-demo-scenarios` ;
|
||||||
|
- `cargo test -p kb-app-demo-desktop` ;
|
||||||
|
- pour chaque parcours : préparer `Create`, simuler, soumettre, confirmer, puis préparer et valider `Update`.
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
<!-- file: kb-app-demo-desktop/CHANGELOG.md -->
|
<!-- file: kb-app-demo-desktop/CHANGELOG.md -->
|
||||||
<!-- version: 21 -->
|
<!-- version: 22 -->
|
||||||
|
|
||||||
# CHANGELOG — kb-app-demo-desktop
|
# CHANGELOG — kb-app-demo-desktop
|
||||||
|
|
||||||
|
## 0.4.7-pre.014
|
||||||
|
|
||||||
|
- Afficher les cinq parcours Metaplex Devnet dans le runner Metadata.
|
||||||
|
- Adapter automatiquement le JSON `Create`, les lectures de postcondition et les cibles de matérialisation à la famille sélectionnée.
|
||||||
|
|
||||||
## 0.4.7-pre.013-fix-015
|
## 0.4.7-pre.013-fix-015
|
||||||
|
|
||||||
- aligne les tests desktop sur le nombre réel de scénarios synthétiques et Devnet exposés par les registres réutilisables ;
|
- aligne les tests desktop sur le nombre réel de scénarios synthétiques et Devnet exposés par les registres réutilisables ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-app-demo-desktop/src/demo_execution_metadata.rs
|
// file: kb-app-demo-desktop/src/demo_execution_metadata.rs
|
||||||
// version: 12
|
// version: 13
|
||||||
|
|
||||||
//! Thin desktop adapters for metadata execution demo scenarios.
|
//! Thin desktop adapters for metadata execution demo scenarios.
|
||||||
|
|
||||||
@@ -323,6 +323,84 @@ pub(crate) async fn demo_execution_metadata_prepare_create_fixture(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn adapt_create_operation_json(
|
||||||
|
operation_json: &str,
|
||||||
|
asset_family: kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily,
|
||||||
|
) -> std::result::Result<std::string::String, std::string::String> {
|
||||||
|
let mut value: serde_json::Value = match serde_json::from_str(operation_json) {
|
||||||
|
std::result::Result::Ok(parsed) => parsed,
|
||||||
|
std::result::Result::Err(error) => {
|
||||||
|
return std::result::Result::Err(format!(
|
||||||
|
"invalid generated Metaplex Create JSON: {error}"
|
||||||
|
));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if matches!(
|
||||||
|
asset_family,
|
||||||
|
kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Sft
|
||||||
|
| kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Fungible
|
||||||
|
) {
|
||||||
|
value["master_edition"] = serde_json::Value::Null;
|
||||||
|
}
|
||||||
|
let create = match value
|
||||||
|
.get_mut("create_args")
|
||||||
|
.and_then(|args| return args.get_mut("V1"))
|
||||||
|
.and_then(serde_json::Value::as_object_mut)
|
||||||
|
{
|
||||||
|
std::option::Option::Some(found) => found,
|
||||||
|
std::option::Option::None => {
|
||||||
|
return std::result::Result::Err(
|
||||||
|
"generated Metaplex Create JSON has no create_args.V1 object".to_string(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
match asset_family {
|
||||||
|
kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Nft => {
|
||||||
|
create.insert("name".to_string(), serde_json::json!("Khadhroony Devnet NFT"));
|
||||||
|
create.insert("symbol".to_string(), serde_json::json!("KHNFT"));
|
||||||
|
create.insert("token_standard".to_string(), serde_json::json!("NonFungible"));
|
||||||
|
create.insert("collection_details".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("decimals".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("print_supply".to_string(), serde_json::json!("Zero"));
|
||||||
|
},
|
||||||
|
kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Sft => {
|
||||||
|
create.insert("name".to_string(), serde_json::json!("Khadhroony Devnet SFT"));
|
||||||
|
create.insert("symbol".to_string(), serde_json::json!("KHSFT"));
|
||||||
|
create.insert("token_standard".to_string(), serde_json::json!("FungibleAsset"));
|
||||||
|
create.insert("collection_details".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("decimals".to_string(), serde_json::json!(0));
|
||||||
|
create.insert("print_supply".to_string(), serde_json::Value::Null);
|
||||||
|
},
|
||||||
|
kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Fungible => {
|
||||||
|
create.insert("name".to_string(), serde_json::json!("Khadhroony Devnet Fungible"));
|
||||||
|
create.insert("symbol".to_string(), serde_json::json!("KHFUN"));
|
||||||
|
create.insert("token_standard".to_string(), serde_json::json!("Fungible"));
|
||||||
|
create.insert("collection_details".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("decimals".to_string(), serde_json::json!(0));
|
||||||
|
create.insert("print_supply".to_string(), serde_json::Value::Null);
|
||||||
|
},
|
||||||
|
kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Collection => {
|
||||||
|
create.insert("name".to_string(), serde_json::json!("Khadhroony Devnet Collection"));
|
||||||
|
create.insert("symbol".to_string(), serde_json::json!("KHCOL"));
|
||||||
|
create.insert("token_standard".to_string(), serde_json::json!("NonFungible"));
|
||||||
|
create.insert("collection_details".to_string(), serde_json::json!({"V1": {"size": 0}}));
|
||||||
|
create.insert("decimals".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("print_supply".to_string(), serde_json::json!("Zero"));
|
||||||
|
},
|
||||||
|
kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::ProgrammableNft => {
|
||||||
|
create.insert("name".to_string(), serde_json::json!("Khadhroony Devnet pNFT"));
|
||||||
|
create.insert("symbol".to_string(), serde_json::json!("KHPNFT"));
|
||||||
|
create
|
||||||
|
.insert("token_standard".to_string(), serde_json::json!("ProgrammableNonFungible"));
|
||||||
|
create.insert("collection_details".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("rule_set".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("decimals".to_string(), serde_json::Value::Null);
|
||||||
|
create.insert("print_supply".to_string(), serde_json::json!("Zero"));
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return std::result::Result::Ok(crate::pretty_json(&value));
|
||||||
|
}
|
||||||
|
|
||||||
/// Prepares one coherent scenario step and all of its stateful reads.
|
/// Prepares one coherent scenario step and all of its stateful reads.
|
||||||
pub(crate) async fn demo_execution_metadata_prepare_step(
|
pub(crate) async fn demo_execution_metadata_prepare_step(
|
||||||
state: tauri::State<'_, crate::AppState>,
|
state: tauri::State<'_, crate::AppState>,
|
||||||
@@ -374,11 +452,18 @@ pub(crate) async fn demo_execution_metadata_prepare_step(
|
|||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
|
let operation_json = match adapt_create_operation_json(
|
||||||
|
fixture.operation_json.as_str(),
|
||||||
|
scenario.asset_family,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
(
|
(
|
||||||
fixture.mint,
|
fixture.mint,
|
||||||
fixture.metadata,
|
fixture.metadata,
|
||||||
fixture.master_edition,
|
fixture.master_edition,
|
||||||
fixture.operation_json,
|
operation_json,
|
||||||
if fixture.mint_created {
|
if fixture.mint_created {
|
||||||
"mint_prepared".to_string()
|
"mint_prepared".to_string()
|
||||||
} else {
|
} else {
|
||||||
@@ -480,7 +565,13 @@ pub(crate) async fn demo_execution_metadata_prepare_step(
|
|||||||
} else {
|
} else {
|
||||||
serde_json::json!([metadata_read.clone()])
|
serde_json::json!([metadata_read.clone()])
|
||||||
};
|
};
|
||||||
let postcondition_reads = if operation == "create" {
|
let create_reads_edition = matches!(
|
||||||
|
scenario.asset_family,
|
||||||
|
kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Nft
|
||||||
|
| kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::Collection
|
||||||
|
| kb_pipeline_demo_scenarios::MetaplexTokenMetadataAssetFamily::ProgrammableNft
|
||||||
|
);
|
||||||
|
let postcondition_reads = if operation == "create" && create_reads_edition {
|
||||||
serde_json::json!([metadata_read, edition_read])
|
serde_json::json!([metadata_read, edition_read])
|
||||||
} else {
|
} else {
|
||||||
serde_json::json!([metadata_read])
|
serde_json::json!([metadata_read])
|
||||||
@@ -675,7 +766,7 @@ mod tests {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|payload| return payload.mode == "network_simulation")
|
.filter(|payload| return payload.mode == "network_simulation")
|
||||||
.count(),
|
.count(),
|
||||||
1
|
5
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
<!-- file: kb-pipeline-demo-scenarios/CHANGELOG.md -->
|
<!-- file: kb-pipeline-demo-scenarios/CHANGELOG.md -->
|
||||||
<!-- version: 24 -->
|
<!-- version: 25 -->
|
||||||
|
|
||||||
# CHANGELOG — kb-pipeline-demo-scenarios
|
# CHANGELOG — kb-pipeline-demo-scenarios
|
||||||
|
|
||||||
|
## 0.4.7-pre.014
|
||||||
|
|
||||||
|
- Expose cinq parcours Metaplex Devnet préparables : NFT, SFT, fungible, collection parent et pNFT sans rule set.
|
||||||
|
- Conserver un cycle borné `Create -> UpdateAsUpdateAuthorityV2` pour chaque famille avant d'étendre les opérations spécialisées.
|
||||||
|
|
||||||
## 0.4.7-pre.013-fix-014
|
## 0.4.7-pre.013-fix-014
|
||||||
|
|
||||||
- crée un nouveau mint natif pour chaque nouvelle préparation `Create`, afin de ne jamais réutiliser un PDA metadata déjà créé ;
|
- crée un nouveau mint natif pour chaque nouvelle préparation `Create`, afin de ne jamais réutiliser un PDA metadata déjà créé ;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: kb-pipeline-demo-scenarios/src/solana_metaplex_token_metadata_scenarios.rs
|
// file: kb-pipeline-demo-scenarios/src/solana_metaplex_token_metadata_scenarios.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
//! Coherent Metaplex Token Metadata scenario journeys for tests and Devnet campaigns.
|
//! Coherent Metaplex Token Metadata scenario journeys for tests and Devnet campaigns.
|
||||||
|
|
||||||
@@ -224,23 +224,85 @@ pub fn metaplex_token_metadata_synthetic_scenarios()
|
|||||||
/// Returns the ordered Metaplex journeys intended for opt-in Devnet simulation.
|
/// Returns the ordered Metaplex journeys intended for opt-in Devnet simulation.
|
||||||
pub fn metaplex_token_metadata_devnet_scenarios()
|
pub fn metaplex_token_metadata_devnet_scenarios()
|
||||||
-> std::vec::Vec<crate::MetaplexTokenMetadataScenario> {
|
-> std::vec::Vec<crate::MetaplexTokenMetadataScenario> {
|
||||||
let mut scenario = scenario(
|
let definitions = [
|
||||||
"metaplex_nft_create_update_devnet",
|
(
|
||||||
"NFT classique : création confirmée puis mise à jour",
|
"metaplex_nft_create_update_devnet",
|
||||||
crate::MetaplexTokenMetadataAssetFamily::Nft,
|
"NFT classique : création confirmée puis mise à jour",
|
||||||
crate::MetaplexTokenMetadataFixtureKind::ClassicNftMint,
|
crate::MetaplexTokenMetadataAssetFamily::Nft,
|
||||||
crate::MetaplexTokenMetadataFixtureState::MintPrepared,
|
crate::MetaplexTokenMetadataFixtureKind::ClassicNftMint,
|
||||||
crate::MetaplexTokenMetadataFixtureState::MetadataCreated,
|
false,
|
||||||
vec![
|
false,
|
||||||
kb_lib::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION.to_string(),
|
&["metadata_state", "edition_state"][..],
|
||||||
kb_lib::EX_METAPLEX_TOKEN_METADATA_UPDATE_OPERATION.to_string(),
|
),
|
||||||
],
|
(
|
||||||
false,
|
"metaplex_sft_create_update_devnet",
|
||||||
false,
|
"SFT : création confirmée puis mise à jour",
|
||||||
&["metadata_state", "edition_state"],
|
crate::MetaplexTokenMetadataAssetFamily::Sft,
|
||||||
);
|
crate::MetaplexTokenMetadataFixtureKind::SemiFungibleMint,
|
||||||
scenario.mode = crate::MetaplexTokenMetadataScenarioMode::NetworkSimulation;
|
false,
|
||||||
return vec![scenario];
|
false,
|
||||||
|
&["metadata_state"][..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"metaplex_fungible_create_update_devnet",
|
||||||
|
"Fungible : création confirmée puis mise à jour",
|
||||||
|
crate::MetaplexTokenMetadataAssetFamily::Fungible,
|
||||||
|
crate::MetaplexTokenMetadataFixtureKind::FungibleMint,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
&["metadata_state"][..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"metaplex_collection_create_update_devnet",
|
||||||
|
"Collection parent : création confirmée puis mise à jour",
|
||||||
|
crate::MetaplexTokenMetadataAssetFamily::Collection,
|
||||||
|
crate::MetaplexTokenMetadataFixtureKind::CollectionParentAndMember,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&["metadata_state", "edition_state"][..],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"metaplex_pnft_create_update_devnet",
|
||||||
|
"pNFT sans rule set : création confirmée puis mise à jour",
|
||||||
|
crate::MetaplexTokenMetadataAssetFamily::ProgrammableNft,
|
||||||
|
crate::MetaplexTokenMetadataFixtureKind::ProgrammableNftTokenRecord,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
&["metadata_state", "edition_state"][..],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
return definitions
|
||||||
|
.into_iter()
|
||||||
|
.map(
|
||||||
|
|(
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
asset_family,
|
||||||
|
fixture_kind,
|
||||||
|
requires_collection,
|
||||||
|
requires_programmable_rules,
|
||||||
|
materialization_targets,
|
||||||
|
)| {
|
||||||
|
let mut value = scenario(
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
asset_family,
|
||||||
|
fixture_kind,
|
||||||
|
crate::MetaplexTokenMetadataFixtureState::MintPrepared,
|
||||||
|
crate::MetaplexTokenMetadataFixtureState::MetadataCreated,
|
||||||
|
vec![
|
||||||
|
kb_lib::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION.to_string(),
|
||||||
|
kb_lib::EX_METAPLEX_TOKEN_METADATA_UPDATE_OPERATION.to_string(),
|
||||||
|
],
|
||||||
|
requires_collection,
|
||||||
|
requires_programmable_rules,
|
||||||
|
materialization_targets,
|
||||||
|
);
|
||||||
|
value.mode = crate::MetaplexTokenMetadataScenarioMode::NetworkSimulation;
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -279,18 +341,23 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn devnet_inventory_exposes_only_fully_preparable_journeys() {
|
fn devnet_inventory_exposes_only_fully_preparable_journeys() {
|
||||||
let devnet = crate::metaplex_token_metadata_devnet_scenarios();
|
let devnet = crate::metaplex_token_metadata_devnet_scenarios();
|
||||||
assert_eq!(devnet.len(), 1);
|
assert_eq!(devnet.len(), 5);
|
||||||
let scenario = &devnet[0];
|
let families = devnet
|
||||||
assert_eq!(scenario.asset_family, crate::MetaplexTokenMetadataAssetFamily::Nft);
|
.iter()
|
||||||
assert_eq!(scenario.operation_codes.len(), 2);
|
.map(|scenario| return scenario.asset_family)
|
||||||
assert_eq!(
|
.collect::<std::collections::BTreeSet<_>>();
|
||||||
scenario.operation_codes[0],
|
assert_eq!(families.len(), 5);
|
||||||
kb_lib::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION
|
for scenario in devnet {
|
||||||
);
|
assert_eq!(scenario.operation_codes.len(), 2);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
scenario.operation_codes[1],
|
scenario.operation_codes[0],
|
||||||
kb_lib::EX_METAPLEX_TOKEN_METADATA_UPDATE_OPERATION
|
kb_lib::EX_METAPLEX_TOKEN_METADATA_CREATE_OPERATION
|
||||||
);
|
);
|
||||||
assert_eq!(scenario.mode, crate::MetaplexTokenMetadataScenarioMode::NetworkSimulation);
|
assert_eq!(
|
||||||
|
scenario.operation_codes[1],
|
||||||
|
kb_lib::EX_METAPLEX_TOKEN_METADATA_UPDATE_OPERATION
|
||||||
|
);
|
||||||
|
assert_eq!(scenario.mode, crate::MetaplexTokenMetadataScenarioMode::NetworkSimulation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user