# Guide d’exécution Devnet ## 1. Objet et ordre de validation Ce guide décrit la campagne Devnet de `kb-app-demo-desktop` et `kb-pipeline-demo-scenarios`. Après une modification de nomenclature persistée ou une recréation de la base Devnet, reprendre les scénarios depuis le début dans l’ordre suivant : 1. préparation commune et base PostgreSQL propre ; 2. Solana Core — System Transfer ; 3. SPL Memo v4 ; 4. SPL Associated Token Account — mint Token classique ; 5. SPL Associated Token Account — mint Token-2022 ; 6. SPL Token classique ; 7. Token-2022 ; 8. registre ElGamal. Les commandes réutilisables sont centralisées en section 4. Chaque scénario référence leur identifiant `Cxx` au lieu de les recopier. ## 2. Préconditions - `.env` contient `KB_POSTGRES_DEVNET_URL` et les secrets de transport requis ; - `KB_POSTGRES_DEVNET_URL`, `KB_POSTGRES_MAINNET_URL` et `KB_POSTGRES_TEST_URL` désignent des bases distinctes ; - le profil sélectionné est Devnet et autorise explicitement l’envoi Devnet ; - l’envoi Mainnet reste désactivé ; - les plafonds de frais, de dépense et de rent sont contrôlés ; - la politique reste `simulation-first` ; - le wallet temporaire persistant n’est jamais copié dans les logs ou les preuves ; - le financement est réalisé par un faucet Web Devnet, pas par `solana airdrop`. Lorsque `database.postgres.auto_initialize_schema` vaut `true`, l’ouverture d’une fenêtre Devnet crée les tables manquantes. Lorsqu’il vaut `false`, le schéma doit être préparé avant l’ouverture. ## 3. Organisation des terminaux La campagne utilise deux terminaux distincts. Les variables d’environnement exportées dans un terminal ne sont pas visibles dans l’autre. ### Terminal A — application Tauri Ce terminal reste occupé par `cargo tauri dev` pendant toute la campagne. Il affiche les logs Rust, Tauri, Vite, PostgreSQL et RPC. ### Terminal B — contrôles CLI et preuves Ce terminal reste disponible pour les commandes Solana, PostgreSQL, balances, confirmations et captures avec `tee`. Les commandes `C01` à `C05` doivent être exécutées dans le terminal B. Le terminal A doit exécuter `T01`, puis rester ouvert. Avant chaque scénario, le terminal B doit définir `KB_DEVNET_SCENARIO` avant d’appeler `C06`. ## 4. Commandes communes Les commandes suivantes sont exécutées depuis la racine du workspace dans un terminal interactif. Ne pas utiliser `set -e` ou `set -u` dans ce terminal : une commande de contrôle non satisfaite fermerait la session. `set -o pipefail` est suffisant pour fiabiliser les pipelines vers `tee`. ### T01 — Démarrer l’application dans le terminal A Premier lancement du workspace ou après modification des dépendances frontend : ```bash cd ~/Projects/khadhroony-bot3; command -v cargo; command -v npm; command -v cargo-tauri || cargo install tauri-cli --locked; test -d kb-app-demo-desktop/node_modules || npm --prefix kb-app-demo-desktop i; cargo tauri dev -c kb-app-demo-desktop/tauri.conf.json ``` La commande `npm --prefix kb-app-demo-desktop i -D ...` installe ou réaligne explicitement les dépendances de développement déclarées par l’application. `npm --prefix kb-app-demo-desktop i` reste nécessaire pour les dépendances runtime. Installation ou réalignement conditionnel des dépendances de développement, uniquement après modification de `package.json`, suppression de `node_modules` ou erreur de dépendance frontend : ```bash npm --prefix kb-app-demo-desktop i -D @tauri-apps/cli @types/bootstrap @types/markdown-it @types/node sass-embedded typescript vite ``` `npm run dev` est lancé automatiquement par Tauri via `beforeDevCommand`; il exécute le script `dev` du `package.json`, actuellement Vite. Il ne faut pas le lancer dans un troisième terminal. La validation frontend de cette campagne est effectuée par `cargo tauri dev -c kb-app-demo-desktop/tauri.conf.json`, qui lance Vite. Ne pas ajouter `npm --prefix kb-app-demo-desktop run build` à la procédure. Lancements suivants, lorsque `cargo-tauri` et `node_modules` sont déjà présents : ```bash cd ~/Projects/khadhroony-bot3; cargo tauri dev -c kb-app-demo-desktop/tauri.conf.json ``` Attendre avant tout scénario : - le démarrage de Vite ; - le lancement du binaire `kb-app-demo-desktop` ; - l’ouverture de la fenêtre ; - le message PostgreSQL indiquant que les 13 tables sont prêtes ; - la résolution correcte du profil `local_devnet`. Ne pas exécuter les commandes `C06` ou `C07` dans ce terminal. ### T02 — Arrêter et redémarrer Tauri conditionnellement Redémarrer Tauri après : - recréation du schéma PostgreSQL si l’application était déjà ouverte ; - modification de `.env`, de la configuration ou du profil actif ; - recompilation liée à une correction de code ; - perte de connexion entre Vite et la fenêtre. Arrêter avec `Ctrl+C`, puis relancer `T01`. ### C01 — Initialiser l’environnement de validation ```bash cd ~/Projects/khadhroony-bot3 && set -o pipefail && export KB_DEVNET_PROFILE="local_devnet" && export KB_DEVNET_RPC_URL="https://api.devnet.solana.com" && export KB_DEVNET_VALIDATION_DIR="/tmp/devnet-validation/pre.062-clean" && export KB_DEVNET_WALLET="$PWD/wallets/temporary/local_devnet/local-devnet-operator.json" && mkdir -p "$KB_DEVNET_VALIDATION_DIR" && printf 'Profil : %s\n' "$KB_DEVNET_PROFILE" && printf 'RPC Devnet : %s\n' "$KB_DEVNET_RPC_URL" && printf 'Preuves : %s\n' "$KB_DEVNET_VALIDATION_DIR" && printf 'Wallet : %s\n' "$KB_DEVNET_WALLET"; ``` ### C02 — Capturer les versions CLI ```bash command -v solana && command -v solana-keygen && command -v spl-token && { date --iso-8601=seconds; solana --version; solana-keygen --version; spl-token --version; } | tee "$KB_DEVNET_VALIDATION_DIR/00-cli-versions.txt"; ``` La première campagne `pre.062` utilisait `solana-cli 4.0.2`, `solana-keygen 4.0.2` et `spl-token-cli 5.5.0`. Une nouvelle campagne doit capturer ses propres versions. ### C03 — Vérifier l’identité du réseau ```bash solana config set --url "$KB_DEVNET_RPC_URL" && { date --iso-8601=seconds; solana config get; solana cluster-version --url "$KB_DEVNET_RPC_URL"; solana genesis-hash --url "$KB_DEVNET_RPC_URL"; solana epoch-info --url "$KB_DEVNET_RPC_URL"; } | tee "$KB_DEVNET_VALIDATION_DIR/01-devnet-network.txt"; ``` Le genesis hash Devnet attendu est : ```text EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG ``` ### C04 — Vérifier le wallet opérateur ```bash test -f "$KB_DEVNET_WALLET" && chmod 600 "$KB_DEVNET_WALLET" && export KB_DEVNET_WALLET_PUBKEY="$(solana-keygen pubkey "$KB_DEVNET_WALLET")" && { date --iso-8601=seconds; printf 'wallet_path=%s\n' "$KB_DEVNET_WALLET"; printf 'wallet_pubkey=%s\n' "$KB_DEVNET_WALLET_PUBKEY"; solana balance "$KB_DEVNET_WALLET_PUBKEY" --url "$KB_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KB_DEVNET_VALIDATION_DIR/02-wallet.txt" ``` ### C05 — Recréer la base Devnet Cette commande est destructive. Elle ne doit viser que `KB_POSTGRES_DEVNET_URL`. Elle supprime toutes les données et tous les objets du schéma `public`, puis laisse l’application recréer son schéma lors de l’ouverture d’une fenêtre Devnet. ```bash test -n "$KB_POSTGRES_DEVNET_URL" && printf '%s\n' "$KB_POSTGRES_DEVNET_URL" && export KB_CONFIRM_DEVNET_DATABASE_RESET="YES_RESET_SOLANA_DEVNET" && test "$KB_CONFIRM_DEVNET_DATABASE_RESET" = "YES_RESET_SOLANA_DEVNET" && psql "$KB_POSTGRES_DEVNET_URL" -v ON_ERROR_STOP=1 -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;' ``` Après ouverture d’une fenêtre Devnet, contrôler les tables : ```bash psql "$KB_POSTGRES_DEVNET_URL" -v ON_ERROR_STOP=1 -c "SELECT schemaname, tablename FROM pg_tables WHERE schemaname = 'public' ORDER BY tablename;" | tee "$KB_DEVNET_VALIDATION_DIR/03-devnet-schema.txt" ``` ### C06 — Capturer le solde avant scénario Définir `KB_DEVNET_SCENARIO` avant l’appel. ```bash test -n "${KB_DEVNET_SCENARIO:-}" && test -n "${KB_DEVNET_WALLET_PUBKEY:-}" && test -n "${KB_DEVNET_RPC_URL:-}" && test -n "${KB_DEVNET_VALIDATION_DIR:-}" && { date --iso-8601=seconds; printf 'scenario=%s\nwallet=%s\n' "$KB_DEVNET_SCENARIO" "$KB_DEVNET_WALLET_PUBKEY"; solana balance "$KB_DEVNET_WALLET_PUBKEY" --url "$KB_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KB_DEVNET_VALIDATION_DIR/${KB_DEVNET_SCENARIO}-wallet-before.txt" ``` ### C07 — Confirmer une signature et capturer le solde après scénario Définir `KB_DEVNET_SCENARIO` et `KB_DEVNET_SIGNATURE` avant l’appel. ```bash test -n "${KB_DEVNET_SCENARIO:-}" && test -n "${KB_DEVNET_SIGNATURE:-}" && test -n "${KB_DEVNET_WALLET_PUBKEY:-}" && test -n "${KB_DEVNET_RPC_URL:-}" && test -n "${KB_DEVNET_VALIDATION_DIR:-}" && { date --iso-8601=seconds; printf 'scenario=%s\nsignature=%s\n' "$KB_DEVNET_SCENARIO" "$KB_DEVNET_SIGNATURE"; solana confirm "$KB_DEVNET_SIGNATURE" --url "$KB_DEVNET_RPC_URL" --commitment finalized --verbose; solana balance "$KB_DEVNET_WALLET_PUBKEY" --url "$KB_DEVNET_RPC_URL" --commitment confirmed; } | tee "$KB_DEVNET_VALIDATION_DIR/${KB_DEVNET_SCENARIO}-confirmation.txt" ``` ### C08 — Préparer un mint SPL Token classique pour ATA Cette commande crée uniquement un mint de test persistant. Elle ne crée aucun compte token associé : l’ATA doit être dérivé, simulé et créé par `kb-app-demo-desktop`. L’option `--silent` est obligatoire afin que la phrase de récupération ne soit pas affichée dans le terminal, les captures ou l’historique de validation. La commande est idempotente au niveau du guide : si le compte du mint existe déjà sur Devnet, elle le réutilise. ```bash export KB_SPL_TOKEN_PROGRAM_ID="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" && export KB_DEVNET_CLASSIC_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-classic-mint.json" && mkdir -p "$(dirname "$KB_DEVNET_CLASSIC_MINT_KEYPAIR")" && { test -f "$KB_DEVNET_CLASSIC_MINT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KB_DEVNET_CLASSIC_MINT_KEYPAIR"; } ``` ```bash export KB_DEVNET_CLASSIC_MINT="$(solana-keygen pubkey "$KB_DEVNET_CLASSIC_MINT_KEYPAIR")" && { solana account "$KB_DEVNET_CLASSIC_MINT" --url "$KB_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" create-token "$KB_DEVNET_CLASSIC_MINT_KEYPAIR" --decimals 9; } && printf 'classic_mint=%s\n' "$KB_DEVNET_CLASSIC_MINT" | tee "$KB_DEVNET_VALIDATION_DIR/30a-spl-ata-classic-mint.txt" ``` ### C09 — Préparer un mint Token-2022 pour ATA Cette commande crée uniquement un mint Token-2022 de test persistant, sans extension supplémentaire. Elle ne crée aucun ATA. ```bash export KB_SPL_TOKEN_2022_PROGRAM_ID="TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" && export KB_DEVNET_TOKEN_2022_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-token-2022-mint.json" && mkdir -p "$(dirname "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR")" && { test -f "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR"; } ``` ```bash export KB_DEVNET_TOKEN_2022_MINT="$(solana-keygen pubkey "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR")" && { solana account "$KB_DEVNET_TOKEN_2022_MINT" --url "$KB_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_2022_PROGRAM_ID" create-token "$KB_DEVNET_TOKEN_2022_MINT_KEYPAIR" --decimals 9; } && printf 'token_2022_mint=%s\n' "$KB_DEVNET_TOKEN_2022_MINT" | tee "$KB_DEVNET_VALIDATION_DIR/30b-spl-ata-token-2022-mint.txt" ``` ### C10 — Préparer les comptes du scénario SPL Token classique La fenêtre actuelle **Décodeur spl_token — TransferChecked** valide uniquement `TransferChecked`. Elle exige : - un mint SPL Token classique ; - un compte source appartenant au wallet opérateur et possédant un solde token suffisant ; - un compte destination distinct pour le même mint ; - l’autorité simple du compte source, qui doit être le wallet opérateur. Cette préparation réutilise le mint créé par `C08` et l’ATA classique créée pendant `S03A`. 1. Dériver l’ATA source avec la syntaxe exigée par `spl-token-cli 5.5.0` : ```bash export KB_DEVNET_CLASSIC_SOURCE_ATA="$(spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" address --verbose --token "$KB_DEVNET_CLASSIC_MINT" --owner "$KB_DEVNET_WALLET_PUBKEY" | awk -F': ' '/Associated token address/ {print $2}')" && test -n "$KB_DEVNET_CLASSIC_SOURCE_ATA" && printf 'source_ata=%s\n' "$KB_DEVNET_CLASSIC_SOURCE_ATA" ``` 2. Préparer un owner destinataire persistant : ```bash export KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR="$PWD/wallets/temporary/local_devnet/recipients/spl-token-transfer-recipient.json" && mkdir -p "$(dirname "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR")" && { test -f "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR" || solana-keygen new --no-bip39-passphrase --force --silent --outfile "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR"; } && export KB_DEVNET_CLASSIC_RECIPIENT="$(solana-keygen pubkey "$KB_DEVNET_CLASSIC_RECIPIENT_KEYPAIR")" ``` 3. Dériver puis créer l’ATA destination si elle n’existe pas : ```bash export KB_DEVNET_CLASSIC_DESTINATION_ATA="$(spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" address --verbose --token "$KB_DEVNET_CLASSIC_MINT" --owner "$KB_DEVNET_CLASSIC_RECIPIENT" | awk -F': ' '/Associated token address/ {print $2}')" && test -n "$KB_DEVNET_CLASSIC_DESTINATION_ATA" && { solana account "$KB_DEVNET_CLASSIC_DESTINATION_ATA" --url "$KB_DEVNET_RPC_URL" --output json >/dev/null 2>&1 || spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" create-account "$KB_DEVNET_CLASSIC_MINT" --owner "$KB_DEVNET_CLASSIC_RECIPIENT" --fee-payer "$KB_DEVNET_WALLET"; } ``` 4. Créditer le compte source. Cette commande ajoute `10` tokens à chaque exécution ; ne la relancer que si le solde source est insuffisant : ```bash spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" mint "$KB_DEVNET_CLASSIC_MINT" 10 "$KB_DEVNET_CLASSIC_SOURCE_ATA" --owner "$KB_DEVNET_WALLET" --fee-payer "$KB_DEVNET_WALLET" ``` 5. Afficher les comptes par leur adresse. Avec cette version du CLI, utiliser `display` plutôt que `account-info `, car l’argument positionnel de `account-info` est interprété comme un mint : ```bash spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_DESTINATION_ATA" ``` 6. Capturer la fixture : ```bash { printf 'mint=%s\n' "$KB_DEVNET_CLASSIC_MINT"; printf 'source=%s\n' "$KB_DEVNET_CLASSIC_SOURCE_ATA"; printf 'destination=%s\n' "$KB_DEVNET_CLASSIC_DESTINATION_ATA"; printf 'authority=%s\n' "$KB_DEVNET_WALLET_PUBKEY"; printf 'amount_raw=1000000000\n'; printf 'decimals=9\n'; } | tee "$KB_DEVNET_VALIDATION_DIR/40-spl-token-fixture.txt" ``` La création du compte destination par CLI est acceptable ici : `S03A` et `S03B` ont déjà validé l’executor ATA. `S04` doit isoler et valider l’executor SPL Token `TransferChecked`. ### C11 — Créer ou réutiliser la fixture Token-2022 Le workspace fournit une commande idempotente qui prépare les comptes publics requis par les huit scénarios Token-2022 : ```bash cargo run -p kb-pipeline-demo-scenarios --bin kb-pipeline-demo-scenarios-cli -- prepare-token-2022-fixture --rpc-url "$KB_DEVNET_RPC_URL" --wallet "$KB_DEVNET_WALLET" --wallet-dir "$PWD/wallets/temporary/local_devnet" --decimals 9 | tee "$KB_DEVNET_VALIDATION_DIR/50-spl-token-2022-fixture-preparation.json" ``` Lorsque `--rpc-url` et `--wallet` sont omis, la commande utilise respectivement `KB_DEVNET_RPC_URL` et `KB_DEVNET_WALLET`. Lorsque `--wallet-dir` est omis, elle utilise le répertoire parent du wallet. La commande : - crée silencieusement les keypairs manquants avec des permissions `0600` ; - crée ou réutilise un mint Token-2022 avec mint authority et freeze authority égales au wallet opérateur ; - crée ou réutilise trois comptes Token-2022 distincts : source, destination et compte vide réservé à `CloseAccount` ; - crée ou réutilise une pubkey delegate indépendante ; - n'affiche jamais les phrases de récupération ni les octets privés ; - écrit atomiquement la fixture publique attendue par l'application. Les keypairs et la fixture sont conservés sous : ```text wallets/temporary/local_devnet/spl_token_2022_validation/ ``` La fixture publique est : ```text wallets/temporary/local_devnet/spl_token_2022_validation/fixture.env ``` Elle définit : ```text TOKEN_2022_PROGRAM TOKEN_2022_MINT TOKEN_2022_SOURCE TOKEN_2022_DESTINATION TOKEN_2022_CLOSE_ACCOUNT TOKEN_2022_DELEGATE TOKEN_2022_AUTHORITY TOKEN_2022_FREEZE_AUTHORITY TOKEN_2022_DECIMALS TOKEN_2022_MINT_AMOUNT_RAW TOKEN_2022_TRANSFER_AMOUNT_RAW TOKEN_2022_APPROVE_AMOUNT_RAW TOKEN_2022_BURN_AMOUNT_RAW KB_DEVNET_WALLET_ADDRESS ``` Vérifier puis charger uniquement les valeurs publiques dans le terminal B : ```bash export KB_DEVNET_TOKEN_2022_FIXTURE="$PWD/wallets/temporary/local_devnet/spl_token_2022_validation/fixture.env" && test -f "$KB_DEVNET_TOKEN_2022_FIXTURE" && sed -n '/^export [A-Z0-9_]*=/p' "$KB_DEVNET_TOKEN_2022_FIXTURE" | sed 's/=.*$/=/' | tee "$KB_DEVNET_VALIDATION_DIR/50-spl-token-2022-fixture-keys.txt" && source "$KB_DEVNET_TOKEN_2022_FIXTURE" ``` Afficher le mint et les trois comptes Token-2022 avec le Program ID explicite : ```bash spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_MINT" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_SOURCE" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_DESTINATION" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$TOKEN_2022_PROGRAM" display "$TOKEN_2022_CLOSE_ACCOUNT" ``` Le compte `TOKEN_2022_CLOSE_ACCOUNT` doit rester vide jusqu'au scénario `CloseAccount`. Ne pas utiliser `account-info ` dans cette campagne : avec `spl-token-cli 5.5.0`, cette forme peut interpréter l'adresse comme un mint. ### C12 — Preuves applicatives communes Pour chaque scénario, conserver depuis l’application : - profil et cluster résolus ; - paramètres saisis ; - `operation_code`, `program_id` et plan préparé ; - signers requis et fee payer ; - plafond de frais et plafond de dépense ; - résultat et logs de simulation ; - signature d’envoi ; - résultat de confirmation ; - insertion canonique ; - extraction Core ; - Decode replay ciblé ; - projections matérialisées ; - second replay démontrant l’idempotence ; - diagnostics ou écarts observés. Un scénario n’est validé que si le replay ne produit ni échec fonctionnel ni erreur de traitement et si les projections attendues sont présentes et idempotentes. ## 5. Préparation initiale de la campagne 1. Dans le terminal B, exécuter `C01`, `C02`, `C03` et `C04`. 2. Dans le terminal B, exécuter `C05` pour repartir d’une base propre. 3. Dans le terminal A, exécuter `T01`. 4. Attendre la création des 13 tables et la disponibilité de la fenêtre. 5. Dans la fenêtre Configuration, vérifier que `local_devnet` utilise la base Devnet. 6. Dans le terminal B, exécuter le contrôle de tables de `C05`. 7. Financer la pubkey par un faucet Web Devnet si le solde est insuffisant. 8. Réexécuter `C04` dans le terminal B après financement. 9. Avant chaque scénario, définir `KB_DEVNET_SCENARIO` dans le terminal B, puis exécuter `C06`. ## 6. Scénario S01 — Solana Core System Transfer ### Objectif Valider la chaîne complète : préparation, simulation, envoi, confirmation, stockage canonique, extraction Core et replay. ### Procédure 1. Définir puis exécuter `C06` : ```bash export KB_DEVNET_SCENARIO="10-system-transfer" ``` 2. Dans la fenêtre **Exécution Devnet — Solana Core** : - générer un nouveau destinataire ; - conserver sa pubkey ; - saisir un montant borné ; - vérifier `solana.core.system.transfer` ; - simuler ; - contrôler frais, spend et signer ; - confirmer explicitement l’envoi. 3. Définir la signature et exécuter `C07`. 4. Capturer séparément le solde du destinataire : ```bash export KB_DEVNET_RECIPIENT="COLLER_LE_DESTINATAIRE" solana balance \ "$KB_DEVNET_RECIPIENT" \ --url "$KB_DEVNET_RPC_URL" \ --commitment confirmed \ | tee "$KB_DEVNET_VALIDATION_DIR/${KB_DEVNET_SCENARIO}-recipient-after.txt" ``` 5. Exécuter les contrôles applicatifs `C08` sur la signature. ### Contrat d’erreur de l’interface Pour un nouveau destinataire inexistant, le montant doit être au moins égal au minimum de rent exemption indiqué par l’application. Avec la valeur observée de `890880` lamports, une demande de `10000` lamports doit être refusée avant simulation. Ce refus est attendu fonctionnellement, mais l’interface doit afficher l’erreur dans les panneaux de résultat : - `Résumé` doit passer de `idle` à `error` ; - `Plan exact` doit afficher l’échec de préparation ou rester explicitement indisponible avec sa cause ; - `Simulation exacte` doit indiquer qu’aucune simulation n’a été lancée à cause du préflight ; - `Confirmation et replay` doit rester non exécuté, avec une raison explicite. Un message uniquement présent dans le journal est insuffisant. Tant que les panneaux restent à `idle`, ne pas considérer le scénario comme validé et ne pas utiliser « Signer et envoyer ». ### Résultat historique de référence La première campagne a validé la signature `3k8BaQJKwSn8r2pYdvfp1Q3VYrPEcDEuUunMFn7NDq1ZqsvryjoGsxeBBNJjc1123RgDCoykp7w9VrtZgsDw4ph3`, au slot `479589279`, avec `890880` lamports transférés, `5000` lamports de frais et `150` compute units. Cette preuve réseau reste historique ; les lignes PostgreSQL doivent être recréées dans la nouvelle base. ## 7. Scénario S02 — SPL Memo v4 ### Objectif Valider l’opération exécutable `spl.memo.add_memo`, l’événement observé `spl.memo.v4.add_memo` et la projection d’annotation. ### Procédure 1. Définir puis exécuter `C06` : ```bash export KB_DEVNET_SCENARIO="20-spl-memo-v4" ``` 2. Dans la fenêtre **Exécution Devnet — SPL** : - sélectionner Memo v4 ; - saisir un texte UTF-8 borné ; - vérifier le Program ID `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` ; - vérifier le wallet signer ; - simuler puis confirmer l’envoi. 3. Définir `KB_DEVNET_SIGNATURE` et exécuter `C07`. 4. Exécuter `C08` et vérifier précisément : - `processor_name = materializer.transaction.annotations` ; - `surface_code = spl.memo.v4` ; - `event_code = spl.memo.v4.add_memo` ; - une seule annotation matérialisée ; - second replay ignoré/idempotent. ### Résultat historique de référence La première campagne a validé la signature `3uYNASrHibwpnsFWwV2JHAxtnci96RhFYf6zbUSfGMbQQV37gfHizstk7atiHYYQCBm4jhmC6cT3G3CCPCV38Lpx`, au slot `479596483`, avec `5000` lamports de frais et `513` compute units. Après recréation de la base, cette signature peut être réingérée pour tester le replay, mais la campagne propre doit également produire une nouvelle preuve complète. ## 8. Scénario S03 — SPL Associated Token Account Le scénario ATA est divisé en deux validations indépendantes. Une ATA dépend du triplet exact : ```text owner + token_program + mint ``` Un même owner et deux mints appartenant à des Token Programs différents doivent donc produire deux dérivations et deux comptes distincts. ### S03A — ATA avec SPL Token classique #### Objectif Valider la dérivation et la création idempotente d’une ATA dont le mint appartient au programme SPL Token classique. #### Préparation dans le terminal B 1. Exécuter `C08`. 2. Définir le scénario et capturer le solde : ```bash export KB_DEVNET_SCENARIO="30a-spl-ata-classic" ``` 3. Exécuter `C06`. 4. Copier la valeur affichée par : ```bash printf '%s\n' "$KB_DEVNET_CLASSIC_MINT" ``` #### Procédure dans l’application 1. Ouvrir la fenêtre **SPL Associated Token Account**. 2. Utiliser : - owner : wallet opérateur `KB_DEVNET_WALLET_PUBKEY` ; - mint : `KB_DEVNET_CLASSIC_MINT` ; - token program : SPL Token classique ; - payer : wallet opérateur. 3. Dériver l’ATA et conserver son adresse. 4. Vérifier que le Program ID sélectionné est `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`. 5. Simuler `spl.associated_token_account.create_idempotent`. 6. Contrôler le rent ceiling, le payer, l’owner, le mint, le token program et l’adresse ATA dérivée. 7. Confirmer explicitement l’envoi. 8. Définir `KB_DEVNET_SIGNATURE`, puis exécuter `C07`. 9. Exécuter `C12`. 10. Réexécuter la création idempotente et vérifier qu’elle ne produit ni fausse création ni duplication des projections. ### S03B — ATA avec Token-2022 #### Objectif Valider la dérivation et la création idempotente d’une ATA dont le mint appartient au programme Token-2022, puis démontrer qu’elle est distincte de l’ATA classique. #### Préparation dans le terminal B 1. Exécuter `C09`. 2. Définir le scénario et capturer le solde : ```bash export KB_DEVNET_SCENARIO="30b-spl-ata-token-2022" ``` 3. Exécuter `C06`. 4. Copier la valeur affichée par : ```bash printf '%s\n' "$KB_DEVNET_TOKEN_2022_MINT" ``` #### Procédure dans l’application 1. Utiliser : - owner : le même wallet opérateur ; - mint : `KB_DEVNET_TOKEN_2022_MINT` ; - token program : Token-2022 ; - payer : wallet opérateur. 2. Dériver l’ATA et conserver son adresse. 3. Vérifier que le Program ID sélectionné est `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`. 4. Vérifier que l’adresse dérivée diffère de l’ATA classique de S03A. 5. Simuler puis envoyer `spl.associated_token_account.create_idempotent`. 6. Définir `KB_DEVNET_SIGNATURE`, puis exécuter `C07`. 7. Exécuter `C12`. 8. Rejouer la création idempotente. 9. Vérifier séparément les faits parent ATA et les éventuels enfants CPI Token-2022, sans duplication. ### Critères communs S03A/S03B - le mint existe et son owner on-chain correspond au Token Program choisi ; - l’adresse ATA est dérivée avec les graines dans l’ordre canonique `owner`, `token_program`, `mint` ; - le compte créé a pour owner le Token Program attendu ; - le premier envoi peut créer le compte ; - le second envoi idempotent ne crée pas un second compte ; - le replay et les projections restent idempotents ; - aucune ATA classique n’est confondue avec une ATA Token-2022. ## 9. Scénario S04 — SPL Token classique ### Portée réellement exposée La fenêtre actuelle expose uniquement : ```text spl.token.transfer_checked ``` Elle ne permet pas encore d’enchaîner depuis l’interface `InitializeMint`, `MintToChecked`, `Approve`, `Revoke`, `BurnChecked` et `CloseAccount`. Ces opérations restent hors de ce scénario Devnet tant qu’elles ne sont pas exposées par la fenêtre. ### Préparation dans le terminal B 1. Réutiliser le mint classique de `C08` : ```bash export KB_SPL_TOKEN_PROGRAM_ID="TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" && export KB_DEVNET_CLASSIC_MINT_KEYPAIR="$PWD/wallets/temporary/local_devnet/mints/ata-classic-mint.json" && export KB_DEVNET_CLASSIC_MINT="$(solana-keygen pubkey "$KB_DEVNET_CLASSIC_MINT_KEYPAIR")" ``` 2. Définir le scénario : ```bash export KB_DEVNET_SCENARIO="40-spl-token" ``` 3. Exécuter `C06`. 4. Exécuter `C10`. 5. Vérifier les comptes token avant l’opération : ```bash spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_DESTINATION_ATA" ``` ### Valeurs à saisir dans l’application Dans **Décodeur spl_token — TransferChecked** : | Champ | Valeur | |--------------------|--------------------------------------------| | Compte source | `$KB_DEVNET_CLASSIC_SOURCE_ATA` | | Mint | `$KB_DEVNET_CLASSIC_MINT` | | Compte destination | `$KB_DEVNET_CLASSIC_DESTINATION_ATA` | | Autorité simple | `$KB_DEVNET_WALLET_PUBKEY` | | Montant brut exact | `1000000000` pour 1 token avec 9 décimales | | Decimals | `9` | Afficher les valeurs à copier : ```bash printf 'source=%s\nmint=%s\ndestination=%s\nauthority=%s\namount_raw=1000000000\ndecimals=9\n' "$KB_DEVNET_CLASSIC_SOURCE_ATA" "$KB_DEVNET_CLASSIC_MINT" "$KB_DEVNET_CLASSIC_DESTINATION_ATA" "$KB_DEVNET_WALLET_PUBKEY" ``` ### Exécution 1. Cliquer **Préflight et simuler**. 2. Vérifier : - owner des deux comptes = SPL Token classique ; - mint identique sur les deux comptes ; - decimals = `9` ; - source suffisamment financée ; - autorité simple = wallet opérateur ; - montant brut conservé exactement. 3. Cocher la confirmation opérateur. 4. Cliquer **Signer et envoyer Token**. 5. Copier la signature dans : ```bash export KB_DEVNET_SIGNATURE="SIGNATURE_SPL_TOKEN" ``` 6. Exécuter `C07`, puis `C12`. 7. Vérifier les comptes après transfert : ```bash spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_SOURCE_ATA" && spl-token --url "$KB_DEVNET_RPC_URL" --program-id "$KB_SPL_TOKEN_PROGRAM_ID" display "$KB_DEVNET_CLASSIC_DESTINATION_ATA" ``` ### Critères de validation - simulation réussie ; - transaction confirmée puis finalisée ; - `operation_code = spl.token.transfer_checked` ; - montant brut exact ; - insertion canonique, extraction Core et replay réussis ; - projection métier présente ; - second replay idempotent ; - aucun compte Token-2022 impliqué. Le journal métier SPL Token peut rester à `empty` après une simulation seule. Il doit être actualisé après l’envoi confirmé, le replay et la matérialisation. ## 10. Scénario S05 — Token-2022 ### Préparation 1. Définir le scénario et exécuter `C06` : ```bash export KB_DEVNET_SCENARIO="50-spl-token-2022" ``` 2. Exécuter `C11` pour créer ou réutiliser la fixture. 3. Contrôler le mint, la source, la destination et le compte réservé à la fermeture avec les commandes `display` de `C11`. 4. Dans l’application, ouvrir **Exécution spl_token_2022 — scénarios publics**. 5. Cliquer **Charger la fixture Token-2022**. 6. Vérifier que le message indique le chemin de `fixture.env` et le Program ID Token-2022. Le bouton lit le `fixture.env` produit par `kb-pipeline-demo-scenarios` et remplit automatiquement : - compte source ou cible ; - mint ; - compte destination ou destination lamports ; - delegate ; - autorité ; - freeze authority ; - montant brut ; - décimales. Ne remplacer manuellement une valeur que pour un test négatif délibéré. ### Ordre des sous-scénarios Exécuter les scénarios dans cet ordre, car certains modifient l’état nécessaire aux suivants : #### S05.1 — MintToChecked Champs utilisés : - source/cible : compte token à créditer ; - mint : mint Token-2022 ; - autorité : mint authority ; - montant brut : `TOKEN_2022_MINT_AMOUNT_RAW` chargé depuis la fixture ; - décimales : valeur de la fixture. Avec la fixture par défaut, le mint initial est `10000000000` unités brutes, soit 10 tokens avec 9 décimales. Cette quantité couvre ensuite le transfert, l'approbation et le burn prévus. Simuler, envoyer, exécuter `C07`, puis `C12`. #### S05.2 — TransferChecked Champs utilisés : - source : compte financé par S05.1 ; - mint ; - destination : second compte Token-2022 ; - autorité : owner du compte source ; - montant brut et décimales. Simuler, envoyer, confirmer et vérifier les balances source/destination. #### S05.3 — ApproveChecked Champs utilisés : - source ; - mint ; - delegate ; - autorité : owner du compte source ; - montant brut ; - décimales. Après confirmation, vérifier la projection de délégation. #### S05.4 — Revoke Champs utilisés : - source ; - autorité : owner du compte source. Le mint et le delegate ne sont pas requis par le formulaire pour cette opération. Vérifier que la délégation précédente est supprimée. #### S05.5 — BurnChecked Champs utilisés : - source ; - mint ; - autorité : owner du compte source ; - montant brut ; - décimales. Le compte source doit conserver un solde suffisant après le transfert. #### S05.6 — FreezeAccount Champs utilisés : - source/cible ; - mint ; - freeze authority. Vérifier que la fixture désigne une freeze authority réellement configurée sur le mint. #### S05.7 — ThawAccount Réutiliser le même compte cible et la même freeze authority. Ce scénario doit suivre FreezeAccount. #### S05.8 — CloseAccount À exécuter uniquement avec le compte de fermeture prévu par la fixture : - source/cible : `closeAccount` chargé par l’application ; - destination : autorité/destination lamports chargée ; - autorité : owner ou close authority. Le compte doit être vide et satisfaire toutes les préconditions de fermeture. ### Pour chaque sous-scénario 1. sélectionner le scénario ; 2. laisser `applyToken2022Fixture` remplir les champs adaptés ; 3. cliquer **Préflight et simuler** ; 4. contrôler le plan, les owners, les autorités, le montant et les extensions ; 5. cocher la confirmation opérateur ; 6. envoyer ; 7. définir immédiatement `KB_DEVNET_SIGNATURE` avec la signature affichée pour cette sous-opération ; 8. vérifier qu'elle diffère de la signature du scénario précédent, puis exécuter `C07` ; 9. appliquer `C12` ; 10. conserver un fichier de preuve distinct en modifiant temporairement le préfixe, par exemple : ```bash export KB_DEVNET_SCENARIO="50a-token-2022-mint-to-checked" ``` puis `50b`, `50c`, etc., avant chaque appel à `C07`. ### Critères de validation - chaque opération disponible est simulée sur son message exact ; - les comptes sont owned par Token-2022 ; - les autorités correspondent à la fixture ; - les montants bruts et décimales sont exacts ; - les projections token account, admin, fee, metadata ou risk attendues sont présentes selon l’opération ; - aucun événement n’est attribué au programme Token classique ; - chaque replay est sans échec ; - le second replay est idempotent. ## 11. Scénario S06 — Registre ElGamal ### Objectif Valider le programme indépendant de registre ElGamal sans le confondre avec Token-2022. ### Procédure 1. Définir puis exécuter `C06` : ```bash export KB_DEVNET_SCENARIO="60-spl-elgamal-registry" ``` 2. Vérifier le Program ID, le PDA de registre, l’owner, la longueur exacte du compte et les preuves requises. 3. Simuler create/update selon le scénario disponible. 4. Confirmer l’envoi, exécuter `C07`, puis appliquer `C08`. 5. Vérifier la projection admin du registre et l’absence de fausse projection Token-2022. ## 12. Future fenêtre Metadata La future fenêtre metadata devra suivre la même structure : commandes communes `C01` à `C12`, puis scénarios séparés pour les metadata incorporées Token-2022, Metaplex Token Metadata et l’enrichissement off-chain indépendant. ## 13. Critères de clôture de la campagne La campagne est clôturable uniquement lorsque : - tous les scénarios disponibles ont été rejoués depuis une base Devnet propre ; - toutes les signatures sont confirmées sur Devnet ; - les identités persistées respectent la nomenclature canonique ; - aucun ancien `processor_name`, `surface_code`, `operation_code` ou `event_code` ne subsiste ; - le replay ciblé est sans échec ni erreur de traitement ; - les projections sont présentes et idempotentes ; - le présent guide reflète les commandes réellement exécutées.