390 lines
14 KiB
Markdown
390 lines
14 KiB
Markdown
<!-- file: kb-pipeline-demo-scenarios/USAGE.md -->
|
||
<!-- version: 10 -->
|
||
|
||
# Utilisation de kb-pipeline-demo-scenarios
|
||
|
||
## Objectif
|
||
|
||
La bibliothèque expose des scénarios Devnet contrôlés. Le binaire permet leur exécution hors de l’application desktop lorsque la commande correspondante est disponible.
|
||
|
||
## Initialiser l’environnement
|
||
|
||
```rust
|
||
fn initialize_environment() -> kb_core::Result<()> {
|
||
kb_pipeline_demo_scenarios::initialize_demo_scenario_environment()
|
||
}
|
||
```
|
||
|
||
`resolve_demo_devnet_profile` sélectionne un profil Devnet configuré et `prepare_demo_devnet_profile_store` vérifie ou initialise son stockage PostgreSQL.
|
||
|
||
## Observer une exécution
|
||
|
||
`NoopSolanaExecutionObserver` convient aux appels sans progression personnalisée.
|
||
|
||
```rust
|
||
fn observer() -> kb_pipeline_demo_scenarios::NoopSolanaExecutionObserver {
|
||
kb_pipeline_demo_scenarios::NoopSolanaExecutionObserver
|
||
}
|
||
```
|
||
|
||
Une application peut implémenter `SolanaExecutionObserver` pour recevoir les événements et demander une annulation coopérative.
|
||
|
||
## Préparer une simulation System Program
|
||
|
||
```rust
|
||
fn system_transfer_request(
|
||
recipient: kb_lib::MdPubkey,
|
||
) -> kb_pipeline_demo_scenarios::DevnetSystemTransferRequest {
|
||
kb_pipeline_demo_scenarios::DevnetSystemTransferRequest::new(
|
||
"system-transfer-001",
|
||
recipient,
|
||
1_000,
|
||
)
|
||
}
|
||
```
|
||
|
||
Le constructeur crée une requête conservative : `submit` et `operator_confirmed` restent à `false`.
|
||
|
||
## Préparer et exécuter un Memo v4
|
||
|
||
```rust
|
||
fn memo_request() -> kb_pipeline_demo_scenarios::DevnetMemoExecutionRequest {
|
||
kb_pipeline_demo_scenarios::DevnetMemoExecutionRequest::new(
|
||
"memo-001",
|
||
"khadhroony-bot3 Devnet validation",
|
||
)
|
||
}
|
||
```
|
||
|
||
```rust
|
||
async fn run_memo<S, O>(
|
||
store: &S,
|
||
observer: &O,
|
||
request: kb_pipeline_demo_scenarios::DevnetMemoExecutionRequest,
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::DevnetMemoExecutionSummary>
|
||
where
|
||
S: kb_store::Store + Sync,
|
||
O: kb_pipeline_demo_scenarios::SolanaExecutionObserver,
|
||
{
|
||
let result = kb_pipeline_demo_scenarios::execute_devnet_memo(
|
||
store,
|
||
observer,
|
||
request,
|
||
)
|
||
.await;
|
||
|
||
match result {
|
||
Ok(summary) => Ok(summary),
|
||
Err(error) => Err(error),
|
||
}
|
||
}
|
||
```
|
||
|
||
## Simuler Token-2022
|
||
|
||
```rust
|
||
async fn simulate_token_2022<O>(
|
||
request: kb_pipeline_demo_scenarios::DevnetSplToken2022ExecutionRequest,
|
||
observer: &O,
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::DevnetSplToken2022ExecutionSummary>
|
||
where
|
||
O: kb_pipeline_demo_scenarios::SolanaExecutionObserver,
|
||
{
|
||
let result =
|
||
kb_pipeline_demo_scenarios::simulate_devnet_spl_token_2022(request, observer).await;
|
||
|
||
match result {
|
||
Ok(summary) => Ok(summary),
|
||
Err(error) => Err(error),
|
||
}
|
||
}
|
||
```
|
||
|
||
## Charger la matrice de validation Token-2022
|
||
|
||
```rust
|
||
fn load_validation_matrix(
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::Token2022ValidationMatrix> {
|
||
let result = kb_pipeline_demo_scenarios::load_token_2022_validation_matrix();
|
||
|
||
match result {
|
||
Ok(matrix) => Ok(matrix),
|
||
Err(error) => Err(error),
|
||
}
|
||
}
|
||
```
|
||
|
||
La matrice provient de `test-fixtures/contract-matrices/SPL_TOKEN_2022_VALIDATION_MATRIX.json` et est validée avant d’être retournée.
|
||
|
||
## Parcourir les scénarios publics
|
||
|
||
```rust
|
||
fn scenario_ids() -> Vec<String> {
|
||
kb_pipeline_demo_scenarios::devnet_spl_validation_scenarios()
|
||
.iter()
|
||
.map(|scenario| scenario.id.clone())
|
||
.collect()
|
||
}
|
||
```
|
||
|
||
Cette liste permet au CLI ou au desktop de présenter l’inventaire sans dupliquer les identifiants.
|
||
|
||
## Préparer une fixture Token-2022
|
||
|
||
```rust
|
||
async fn prepare_fixture(
|
||
wallet_path: std::path::PathBuf,
|
||
wallet_dir: std::path::PathBuf,
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::Token2022FixturePreparationSummary> {
|
||
let options = kb_pipeline_demo_scenarios::Token2022FixturePreparationOptions {
|
||
rpc_url: "https://api.devnet.solana.com".to_string(),
|
||
wallet_path,
|
||
wallet_dir,
|
||
decimals: 9,
|
||
};
|
||
let result = kb_pipeline_demo_scenarios::prepare_token_2022_fixture(&options).await;
|
||
|
||
match result {
|
||
Ok(summary) => Ok(summary),
|
||
Err(error) => Err(error),
|
||
}
|
||
}
|
||
```
|
||
|
||
La préparation peut créer des comptes et exécuter des commandes Solana CLI. Elle doit rester explicitement déclenchée par l’opérateur.
|
||
|
||
## Tests de référence
|
||
|
||
Les tests de cette crate sont particulièrement utiles pour comprendre l’orchestration réelle :
|
||
|
||
- validation de la matrice Token-2022 ;
|
||
- préparation et réutilisation des fixtures ;
|
||
- simulation et exécution des scénarios ;
|
||
- hydratation canonique, extraction Core, replay et matérialisation ;
|
||
- idempotence et confirmation des états finaux ;
|
||
- test du binaire `kb-pipeline-demo-scenarios-cli`.
|
||
|
||
Les tests Devnet restent opt-in et peuvent produire des transactions réelles lorsque la soumission est explicitement activée.
|
||
|
||
## Erreurs et invariants
|
||
|
||
- aucun envoi ne doit résulter d’une simple demande de simulation ;
|
||
- le profil doit cibler Devnet pour les scénarios Devnet ;
|
||
- les secrets restent gérés par `kb-wallet` ;
|
||
- les résumés ne doivent pas déclarer une validation non observée ;
|
||
- ElGamal ne doit pas être présenté comme validé sur réseau.
|
||
|
||
## Limites durables
|
||
|
||
- cette crate est destinée aux démonstrations, validations et outils opérateur, pas au moteur de production autonome ;
|
||
- les scénarios réseau exigent un endpoint, un wallet et des fonds compatibles ;
|
||
- la bibliothèque ne fournit pas d’interface graphique.
|
||
|
||
|
||
## Charger les scénarios synthétiques Metaplex
|
||
|
||
```rust
|
||
fn metaplex_scenario_ids() -> Vec<String> {
|
||
kb_pipeline_demo_scenarios::metaplex_token_metadata_synthetic_scenarios()
|
||
.iter()
|
||
.map(|scenario| scenario.id.clone())
|
||
.collect()
|
||
}
|
||
```
|
||
|
||
L’inventaire couvre NFT, SFT, token fongible, collection et pNFT. Ces scénarios sont déterministes et ne soumettent aucune transaction.
|
||
|
||
## Charger la matrice de validation Metaplex
|
||
|
||
```rust
|
||
fn load_metaplex_matrix(
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::MetaplexTokenMetadataValidationMatrix> {
|
||
let result = kb_pipeline_demo_scenarios::load_metaplex_token_metadata_validation_matrix();
|
||
|
||
match result {
|
||
Ok(matrix) => Ok(matrix),
|
||
Err(error) => Err(error),
|
||
}
|
||
}
|
||
```
|
||
|
||
Une validation réseau ne peut passer à `confirmed` que lorsque toutes les preuves déclarées sont présentes. Les statuts `not_run` et `unavailable` n’acceptent aucune preuve observée.
|
||
|
||
## Inventaire Metaplex Devnet
|
||
|
||
```rust
|
||
let scenarios = kb_pipeline_demo_scenarios::metaplex_token_metadata_devnet_scenarios();
|
||
assert!(scenarios.iter().all(|scenario| {
|
||
scenario.mode == kb_pipeline_demo_scenarios::MetaplexTokenMetadataScenarioMode::NetworkSimulation
|
||
}));
|
||
```
|
||
|
||
Cet inventaire prépare les tests et campagnes Devnet simulation-first. Il ne constitue pas à lui seul une validation réseau réussie.
|
||
|
||
## Charger le corpus de validation croisée Metaplex
|
||
|
||
```rust
|
||
fn load_metaplex_cross_validation() -> kb_core::Result<usize> {
|
||
let matrix = kb_pipeline_demo_scenarios::load_metaplex_token_metadata_cross_validation_matrix();
|
||
return match matrix {
|
||
Ok(value) => Ok(value.cases.len()),
|
||
Err(error) => Err(error),
|
||
};
|
||
}
|
||
```
|
||
|
||
Les cas marqués `requiresNetworkEvidence` ne peuvent pas être déclarés validés à partir de preuves synthétiques. Une simulation, une soumission ou une confirmation exige les preuves RPC déclarées par le cas.
|
||
|
||
|
||
## Simuler une opération Metaplex réelle sur Devnet
|
||
|
||
L’API réseau prend un intent Metaplex typé déjà lié aux comptes et autorités de la fixture. Le wallet persistant du profil doit être l’unique signer requis.
|
||
|
||
```rust
|
||
async fn simulate_metaplex_operation<O>(
|
||
pool: &kb_onchain_transport::HttpEndpointPool,
|
||
profile: &kb_config::ProfileConfig,
|
||
workspace_root: &std::path::Path,
|
||
operation: kb_lib::ExMetaplexTokenMetadataOperation,
|
||
observer: &O,
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::DevnetMetaplexTokenMetadataExecutionSummary>
|
||
where
|
||
O: kb_pipeline_demo_scenarios::SolanaExecutionObserver,
|
||
{
|
||
let request = kb_pipeline_demo_scenarios::DevnetMetaplexTokenMetadataExecutionRequest::new(
|
||
"metaplex-devnet-simulation",
|
||
operation,
|
||
);
|
||
return kb_pipeline_demo_scenarios::simulate_devnet_metaplex_token_metadata(
|
||
pool,
|
||
profile,
|
||
workspace_root,
|
||
&request,
|
||
observer,
|
||
)
|
||
.await;
|
||
}
|
||
```
|
||
|
||
Pour une soumission, l’appelant doit définir `submit = true` et `operator_confirmed = true`. Les opérations dépréciées sont refusées par cette API automatique. Les lectures `preflight_reads` et `postcondition_reads` doivent décrire les comptes Metadata, Edition, Token Record ou Collection nécessaires au scénario.
|
||
|
||
## Charger la matrice des opérations courantes
|
||
|
||
```rust
|
||
fn load_metaplex_devnet_contract(
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::MetaplexTokenMetadataDevnetExecutionMatrix> {
|
||
return kb_pipeline_demo_scenarios::load_metaplex_token_metadata_devnet_execution_matrix();
|
||
}
|
||
```
|
||
|
||
La matrice ne transforme jamais une implémentation disponible en validation réseau. Les valeurs restent `not_run` jusqu’à l’observation d’une simulation ou d’une confirmation réelle.
|
||
## Exécuter une opération Metaplex courante depuis un JSON typé
|
||
|
||
Le runner Devnet commun accepte toute variante non dépréciée de `ExMetaplexTokenMetadataOperation`. Le test opt-in peut être lancé avec :
|
||
|
||
```bash
|
||
KB_DEVNET_METAPLEX_EXECUTION_TEST=1 \
|
||
KB_DEVNET_METAPLEX_OPERATION_JSON='{"operation":"..."}' \
|
||
cargo test -p kb-pipeline-demo-scenarios optional_devnet_current_operation_from_env -- --nocapture
|
||
```
|
||
|
||
Variables optionnelles :
|
||
|
||
- `KB_DEVNET_WALLET_DIR` pour sélectionner le répertoire du wallet persistant ;
|
||
- `KB_DEVNET_METAPLEX_PREFLIGHT_READS_JSON` pour fournir les lectures stateful avant simulation ;
|
||
- `KB_DEVNET_METAPLEX_POSTCONDITION_READS_JSON` pour fournir les lectures après confirmation ;
|
||
- `KB_DEVNET_METAPLEX_SUBMIT=1` pour autoriser la soumission ;
|
||
- `KB_DEVNET_METAPLEX_OPERATOR_CONFIRMED=1` pour confirmer explicitement la soumission.
|
||
|
||
La soumission reste impossible si les deux dernières variables ne sont pas activées. Les opérations dépréciées sont rejetées avant tout appel RPC.
|
||
|
||
## Préparer une campagne Metaplex courante
|
||
|
||
Les exemples contenant `...` ne sont jamais exécutables. Pour connaître les opérations acceptées :
|
||
|
||
```rust
|
||
let operations =
|
||
kb_pipeline_demo_scenarios::metaplex_token_metadata_current_operation_names();
|
||
```
|
||
|
||
Les opérations disposant d’un modèle générique peuvent être inspectées ainsi :
|
||
|
||
```rust
|
||
fn verify_template() -> kb_core::Result<String> {
|
||
kb_pipeline_demo_scenarios::metaplex_token_metadata_current_operation_json_template(
|
||
"verify",
|
||
)
|
||
}
|
||
```
|
||
|
||
Les valeurs entre chevrons doivent être remplacées par les comptes Devnet réels. Le modèle peut ensuite être passé à `DevnetMetaplexTokenMetadataExecutionRequest::from_operation_json`.
|
||
|
||
Pour les parcours créateur, il est préférable de ne pas écrire de JSON manuellement :
|
||
|
||
```rust
|
||
fn creator_verify_request(
|
||
authority: kb_lib::MdPubkey,
|
||
metadata: kb_lib::MdPubkey,
|
||
) -> kb_pipeline_demo_scenarios::DevnetMetaplexTokenMetadataExecutionRequest {
|
||
kb_pipeline_demo_scenarios::devnet_metaplex_creator_verify_request(
|
||
"metaplex-verify-creator",
|
||
authority,
|
||
metadata,
|
||
)
|
||
}
|
||
```
|
||
|
||
`devnet_metaplex_creator_unverify_request` fournit le parcours inverse. Les deux requêtes restent en simulation-only par défaut.
|
||
|
||
Le test générique accepte toujours `KB_DEVNET_METAPLEX_OPERATION_JSON`, mais rejette explicitement le placeholder documentaire `...`. Les opérations plus complexes recevront des préparateurs de fixtures dédiés au lieu d’exiger de longs JSON écrits à la main.
|
||
## Solana Program Metadata
|
||
|
||
L’inventaire fermé est exposé par :
|
||
|
||
```rust
|
||
fn program_metadata_scenarios(
|
||
) -> Vec<kb_pipeline_demo_scenarios::SolanaProgramMetadataScenario> {
|
||
kb_pipeline_demo_scenarios::solana_program_metadata_devnet_scenarios()
|
||
}
|
||
```
|
||
|
||
Les deux parcours sont ordonnés ainsi :
|
||
|
||
1. `Allocate → Extend → Write → Trim → Close` pour le `Buffer` ;
|
||
2. `Initialize → SetData → SetAuthority → SetImmutable` pour le compte `Metadata`.
|
||
|
||
`Extend` précède volontairement `Write` : `Allocate` ne réserve que l’en-tête du Buffer, alors que l’écriture exige une capacité suffisante.
|
||
|
||
La préparation crée deux PDA non canoniques, les préfinance avec deux transferts System Program confirmés, puis produit neuf opérations typées avec leurs lectures, preuves de rent et postconditions. Elle exige un profil Devnet persistant, `devnet_send_enabled` et une confirmation opérateur explicite.
|
||
|
||
```rust
|
||
async fn run_program_metadata_campaign<O>(
|
||
pool: &kb_onchain_transport::HttpEndpointPool,
|
||
profile: &kb_config::ProfileConfig,
|
||
workspace_root: &std::path::Path,
|
||
observer: &O,
|
||
) -> kb_core::Result<kb_pipeline_demo_scenarios::DevnetSolanaProgramMetadataCampaignSummary>
|
||
where
|
||
O: kb_pipeline_demo_scenarios::SolanaExecutionObserver,
|
||
{
|
||
let options = kb_pipeline_demo_scenarios::SolanaProgramMetadataFixturePreparationOptions {
|
||
query_role: "http_queries".to_string(),
|
||
transaction_role: "http_transactions".to_string(),
|
||
operator_confirmed: true,
|
||
};
|
||
kb_pipeline_demo_scenarios::execute_devnet_solana_program_metadata_campaign(
|
||
pool,
|
||
profile,
|
||
workspace_root,
|
||
&options,
|
||
observer,
|
||
)
|
||
.await
|
||
}
|
||
```
|
||
|
||
Cet appel crée des comptes et soumet onze transactions réelles au minimum : deux transferts de préfinancement et neuf opérations `ProgM6…`. Il ne doit jamais être déclenché implicitement par une ouverture de fenêtre ou une simple demande de simulation.
|
||
|
||
La matrice `SOLANA_PROGRAM_METADATA_DEVNET_VALIDATION_MATRIX.json` reste à `not_run` tant que les signatures, simulations, postconditions et preuves matérialisées n’ont pas été enregistrées. `Close` exige une preuve `account_absence`, car un compte absent ne produit pas de snapshot matérialisé.
|
||
|