421 lines
18 KiB
Markdown
421 lines
18 KiB
Markdown
<!-- file: kb-app-demo-desktop/USAGE.md -->
|
||
<!-- version: 21 -->
|
||
|
||
# Utilisation de kb-app-demo-desktop
|
||
|
||
## Objectif
|
||
|
||
L’application expose une interface opérateur pour diagnostiquer, simuler et valider les couches de bot3.
|
||
|
||
## Surface wallet sûre
|
||
|
||
Le backend desktop peut lister les `.kswallet` du répertoire configuré, créer un wallet natif protégé, inspecter un fichier sélectionné explicitement ailleurs et explorer l’état on-chain d’une adresse publique. Les DTO frontend ne contiennent jamais de matériau secret. Aucun password, chemin interne du store, sel, nonce, ciphertext ou byte privé n’est renvoyé par Tauri.
|
||
|
||
La fenêtre `Wallets`, accessible depuis le menu `Démos` de `main`, fournit maintenant sept surfaces :
|
||
|
||
- inventaire des wallets natifs du profil actif ;
|
||
- sélection session-only du `.kswallet` utilisé par les démos Devnet, sans réécrire la configuration ;
|
||
- création d’un nouveau `.kswallet` dans le store du profil actif ;
|
||
- inspection et import d'un keypair externe dans un format supporté ;
|
||
- export authentifié d'un `.kswallet` vers un format supporté ;
|
||
- explorateur public on-chain ;
|
||
- inspection structurale d’un `.kswallet` explicite situé hors du store.
|
||
|
||
### Créer un wallet natif depuis la démo
|
||
|
||
Le mot de passe de création ne doit pas traverser le frontend ou Tauri IPC. La démo lit uniquement côté backend le secret applicatif :
|
||
|
||
```bash
|
||
export KB_SECRET_DEMO_WALLET_PASSWORD='mot-de-passe-de-demo'
|
||
cargo tauri dev -c kb-app-demo-desktop/tauri.conf.json
|
||
```
|
||
|
||
Le secret peut aussi être placé dans le fichier `.env` local chargé par `ks-config`. Le vrai `.env` reste non versionné et ne doit jamais être archivé. L’UI ne reçoit qu’un booléen indiquant si ce secret backend est configuré.
|
||
|
||
La création demande uniquement l’alias. Elle crée `<alias>.kswallet` dans le répertoire wallet résolu du profil actif et ne modifie pas automatiquement `wallet_alias` dans la configuration. Un changement de valeur de `KB_SECRET_DEMO_WALLET_PASSWORD` avant une autre session permet d’utiliser un autre mot de passe pour de nouveaux wallets ; ce secret de démonstration n’est pas un mot de passe global du format `.kswallet`.
|
||
|
||
### Inspecter, importer et exporter les formats keypair
|
||
|
||
Les sélecteurs de format sont alimentés par `ks-wallet` et exposent actuellement :
|
||
|
||
- `Solana CLI keypair JSON (64 octets)` ;
|
||
- `Solana private key Base58 (64 octets)`.
|
||
|
||
L'action **Inspecter la keypair** ne crée aucun `.kswallet` : le backend valide le fichier avec le codec choisi et ne renvoie que la pubkey. Cette pubkey peut être envoyée directement à l'explorateur on-chain, ce qui permet par exemple de contrôler un ancien `wallets/temporary/local_devnet/*.json` avant de décider de le migrer.
|
||
|
||
L'action **Importer en .kswallet** demande en plus un alias destination et utilise `KB_SECRET_DEMO_WALLET_PASSWORD` uniquement côté backend. La source reste inchangée. L'export fonctionne dans le sens inverse : choix d'un alias natif, du format et d'un nom de fichier ; le backend authentifie le `.kswallet` avec le même secret de démonstration, refuse d'écraser un fichier existant et contraint la destination à `./data/wallets/`. Le répertoire d'export privé est créé avec des permissions `0700` sur Unix et `ks-wallet` conserve les fichiers exportés en `0600`.
|
||
|
||
Un keypair JSON de 64 octets ne contient pas son rôle métier. L'inspection peut dire « keypair Solana valide » et donner sa pubkey, mais elle ne peut pas décider localement si cette clé a servi de wallet opérateur, mint, authority ou autre fixture. Cette classification nécessite le contexte du scénario ou une lecture on-chain séparée.
|
||
|
||
### Sélectionner le `.kswallet` utilisé par les démos Devnet
|
||
|
||
La configuration persistante continue d'utiliser `wallet_alias`, mais la fenêtre Wallets permet également de choisir un alias pour un profil Devnet uniquement pendant la session desktop. Cette sélection est authentifiée immédiatement avec `KB_SECRET_DEMO_WALLET_PASSWORD`, ne réécrit aucun JSON et s'applique aux exécutions System, Memo, ATA, SPL Token, Token-2022 et Metadata suivantes.
|
||
|
||
Le resolver applique l'ordre suivant :
|
||
|
||
1. override session desktop pour le profil, lorsqu'il existe ;
|
||
2. `wallet_alias` du profil ;
|
||
3. wallet temporaire historique uniquement si les deux précédents sont absents.
|
||
|
||
Un override valide ne peut donc pas retomber silencieusement sur `temporary_wallet_alias`. Le log `ks-pipeline-demo-scenarios.wallet` doit alors afficher `persistence="persistent"` avec l'alias et la pubkey sélectionnés.
|
||
|
||
### Explorer une adresse sur un profil RPC sélectionné
|
||
|
||
L’explorateur on-chain ne déverrouille aucun wallet : seule la pubkey publique est nécessaire. Le bouton `Explorer` d’un wallet inventorié remplit l’adresse automatiquement ; toute autre pubkey Solana peut également être saisie.
|
||
|
||
Les lectures utilisent le transport HTTP du profil choisi dans le sélecteur `Profil RPC` de la fenêtre Wallets. Le profil actif est sélectionné par défaut, mais `local_devnet`, `mainnet_research` ou tout autre profil HTTP résolu peut être choisi sans redémarrer l’application :
|
||
|
||
- `getBalance` pour le solde SOL exact en lamports ;
|
||
- `getTokenAccountsByOwner` pour les comptes SPL Token classique et Token-2022 ;
|
||
- `getSignaturesForAddress` pour les signatures récentes des transactions qui référencent l’adresse ;
|
||
- `getTransaction` à la demande pour afficher le détail JSON d’une signature.
|
||
|
||
La liste est donc intitulée **transactions impliquant l’adresse** : elle ne prétend pas que le wallet a initié ou signé chaque transaction retournée. Le profil `local_devnet` interroge Devnet ; `mainnet_research` ou `mainnet` interrogent Mainnet Beta. La sélection utilisée par l’explorateur est locale à cette fenêtre : elle ne modifie pas `active_profile`, la configuration du workspace ni le profil utilisé par les autres démos.
|
||
|
||
## Lancer le desktop
|
||
|
||
Depuis la racine du workspace :
|
||
|
||
```bash
|
||
cargo tauri dev -c kb-app-demo-desktop/tauri.conf.json
|
||
```
|
||
|
||
Le binaire applique un verrou d’instance locale. Une deuxième instance doit échouer proprement.
|
||
|
||
## Construire la release desktop
|
||
|
||
Depuis la racine du workspace :
|
||
|
||
```bash
|
||
cargo tauri build -c kb-app-demo-desktop/tauri.conf.json
|
||
```
|
||
|
||
Ne pas lancer `npm run build` directement. Tauri exécute le `beforeBuildCommand` configuré, puis consomme le même répertoire `dist` que Vite. Les commandes npm manuelles sont réservées à l’installation explicite de dépendances nécessaires.
|
||
|
||
## API Rust publique
|
||
|
||
La bibliothèque expose uniquement `run()` :
|
||
|
||
```rust
|
||
fn launch_desktop() -> ks_core::Result<()> {
|
||
return kb_app_demo_desktop_lib::run();
|
||
}
|
||
```
|
||
|
||
Le binaire `kb-app-demo-desktop` appelle cette fonction et convertit son résultat en `ExitCode`.
|
||
|
||
## Fenêtres initiales
|
||
|
||
La configuration Tauri crée :
|
||
|
||
- `splash` ;
|
||
- `main`.
|
||
|
||
Les autres fenêtres sont ouvertes par les commandes Tauri dédiées :
|
||
|
||
- backfill ;
|
||
- HTTP ;
|
||
- WebSocket ;
|
||
- diagnostics SQL ;
|
||
- candidats replay ;
|
||
- configuration ;
|
||
- wallets ;
|
||
- extraction Core ;
|
||
- decode replay ;
|
||
- exécution Solana Core ;
|
||
- exécution SPL.
|
||
|
||
## Interface Tauri publique
|
||
|
||
Les commandes Tauri constituent l’interface applicative frontend/backend. Elles ne sont pas des APIs Rust publiques pour les autres crates.
|
||
|
||
### Ouvrir une fenêtre
|
||
|
||
```typescript
|
||
import { invoke } from "@tauri-apps/api/core";
|
||
|
||
await invoke("open_demo_wallet_window");
|
||
await invoke("open_demo_http_window");
|
||
await invoke("open_demo_ws_window");
|
||
await invoke("open_demo_decode_replay_window");
|
||
```
|
||
|
||
### Charger les options HTTP
|
||
|
||
```typescript
|
||
const options = await invoke("demo_http_options");
|
||
console.log(options);
|
||
```
|
||
|
||
### Exécuter une requête HTTP de démonstration
|
||
|
||
```typescript
|
||
const result = await invoke(
|
||
"demo_http_execute_request",
|
||
{
|
||
request: {
|
||
role: "standard",
|
||
method: "getHealth",
|
||
paramsJson: "[]"
|
||
}
|
||
}
|
||
);
|
||
|
||
console.log(result);
|
||
```
|
||
|
||
Les champs exacts du payload doivent rester synchronisés avec les types TS-RS générés.
|
||
|
||
### Gérer une session WebSocket
|
||
|
||
```typescript
|
||
const status = await invoke("demo_ws_status");
|
||
console.log(status);
|
||
|
||
await invoke("demo_ws_connect", {
|
||
request: {
|
||
role: "standard",
|
||
method: "logsSubscribe",
|
||
paramsJson: "[]"
|
||
}
|
||
});
|
||
|
||
await invoke("demo_ws_unsubscribe");
|
||
await invoke("demo_ws_disconnect");
|
||
```
|
||
|
||
La fermeture de la fenêtre ne doit pas être assimilée à une demande de déconnexion.
|
||
|
||
### Lancer un backfill
|
||
|
||
```typescript
|
||
const options = await invoke("demo_backfill_options");
|
||
console.log(options);
|
||
|
||
const summary = await invoke(
|
||
"demo_backfill_execute",
|
||
{
|
||
request: {
|
||
profileName: "devnet",
|
||
address: "11111111111111111111111111111111",
|
||
limit: 100
|
||
}
|
||
}
|
||
);
|
||
|
||
console.log(summary);
|
||
```
|
||
|
||
### Extraction Core
|
||
|
||
```typescript
|
||
const options = await invoke(
|
||
"demo_core_extraction_options"
|
||
);
|
||
|
||
const summary = await invoke(
|
||
"demo_core_extraction_execute",
|
||
{
|
||
request: {
|
||
profileName: "devnet",
|
||
limit: 1000
|
||
}
|
||
}
|
||
);
|
||
|
||
console.log(options, summary);
|
||
```
|
||
|
||
Une campagne longue peut être annulée avec `demo_core_extraction_cancel`.
|
||
|
||
### Validation historique Solana Program Metadata
|
||
|
||
Avant les scénarios Devnet, utiliser les fenêtres généralistes dans cet ordre :
|
||
|
||
1. `demo_backfill` avec un échantillon borné de signatures confirmées contenant `ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S` ;
|
||
2. extraction Core sur les mêmes signatures ;
|
||
3. decode replay avec le Program ID `ProgM6…`, le décodeur `metadata.solana_program_metadata` et la matérialisation activée ;
|
||
4. lecture des événements du processor `materializer.metadata.solana_program_metadata`.
|
||
|
||
Ce parcours ne dépend pas de `ks-pipeline-demo-scenarios`. La fenêtre `demo_execution_metadata` et les scénarios Devnet `ProgM6…` seront ajoutés séparément dans `0.4.8-pre.009`.
|
||
|
||
### Decode replay
|
||
|
||
```typescript
|
||
const options = await invoke(
|
||
"demo_decode_replay_options"
|
||
);
|
||
|
||
const summary = await invoke(
|
||
"demo_decode_replay_execute",
|
||
{
|
||
request: {
|
||
profileName: "devnet",
|
||
limit: 1000,
|
||
materialize: true
|
||
}
|
||
}
|
||
);
|
||
|
||
console.log(options, summary);
|
||
```
|
||
|
||
Les diagnostics et annotations sont accessibles par des commandes séparées.
|
||
|
||
### Scénarios Devnet
|
||
|
||
Les commandes couvrent notamment :
|
||
|
||
- `demo_execution_solana_core_execute` ;
|
||
- `demo_execution_spl_memo_execute` ;
|
||
- `demo_execution_spl_token_execute` ;
|
||
- `demo_execution_spl_ata_execute` ;
|
||
- `demo_execution_spl_token_2022_execute`.
|
||
|
||
```typescript
|
||
const scenarios = await invoke(
|
||
"demo_execution_spl_validation_scenarios"
|
||
);
|
||
|
||
console.log(scenarios);
|
||
```
|
||
|
||
La simulation et l’envoi doivent rester explicitement distingués dans les requêtes.
|
||
|
||
### Exécution Metadata Devnet
|
||
|
||
Le backend distingue le module commun Metadata, Metaplex Token Metadata, Token-2022 Token Metadata et Solana Program Metadata. Metaplex est porté par un seul module Rust desktop, comme les deux autres domaines : ce module contient à la fois les contrats génériques conservés pour les tests/outils avancés et les campagnes Devnet qualifiées. Les commandes génériques Metaplex (`current_operations`, `operation_template`, `prepare_step`, `execute`) restent disponibles, mais le panneau Devnet n’utilise plus ce chemin comme workflow opérateur principal.
|
||
|
||
Le panneau charge désormais l’inventaire borné avec `demo_execution_metadata_metaplex_campaigns`, puis exécute une campagne complète avec `demo_execution_metadata_metaplex_execute_campaign`.
|
||
|
||
```typescript
|
||
const campaigns = await invoke(
|
||
"demo_execution_metadata_metaplex_campaigns"
|
||
);
|
||
|
||
const summary = await invoke(
|
||
"demo_execution_metadata_metaplex_execute_campaign",
|
||
{
|
||
request: {
|
||
profileName: "devnet",
|
||
campaignId: "create_mint_nft",
|
||
operatorConfirmed: true
|
||
}
|
||
}
|
||
);
|
||
|
||
console.log(campaigns, summary);
|
||
```
|
||
|
||
L’inventaire contient cinq variantes `Create -> Mint`, puis collection `Verify -> Unverify`, `Print -> Burn`, lifecycle pNFT, Token Owned Escrow, Maintenance et le probe Use. Maintenance et Use sont les seules campagnes mixtes/probe : `Use`, `Resize`, `Migrate`, `Collect` et `CloseAccounts` y restent simulation-only lorsqu’elles rencontrent leur indisponibilité qualifiée et ne sont jamais exposées comme boutons de soumission isolés.
|
||
|
||
Dans la colonne de résultats, `Préflight et opérations`, `Simulation et confirmation` et `Postconditions et preuves` sont présentés dans un accordéon commun. La carte `Exigences` reste sous cet accordéon et le journal d’exécution reste sous la grille, sur toute la largeur.
|
||
|
||
### Diagnostics PostgreSQL
|
||
|
||
```typescript
|
||
const diagnostics = await invoke(
|
||
"load_demo_sql_diag"
|
||
);
|
||
const rawTables = await invoke(
|
||
"load_demo_sql_pg_raw"
|
||
);
|
||
const coreTables = await invoke(
|
||
"load_demo_sql_pg_core"
|
||
);
|
||
|
||
console.log(diagnostics, rawTables, coreTables);
|
||
```
|
||
|
||
## Capabilities Tauri
|
||
|
||
Les fenêtres autorisées sont listées dans `capabilities/default.json`. La capability active doit inclure au minimum les permissions Tauri Core et tracing nécessaires aux fenêtres déclarées.
|
||
|
||
Toute nouvelle fenêtre ou commande sensible doit être auditée avant ajout de permissions.
|
||
|
||
## Erreurs et invariants
|
||
|
||
- une simulation ne doit jamais envoyer une transaction ;
|
||
- une soumission nécessite une confirmation opérateur explicite ;
|
||
- les secrets de wallet ne doivent jamais être sérialisés vers le frontend ;
|
||
- les résultats frontend doivent refléter les validations réellement exécutées ;
|
||
- l’état WebSocket appartient à l’application, pas à la durée de vie de la fenêtre ;
|
||
- les commandes Tauri adaptent les APIs réutilisables sans dupliquer leur logique.
|
||
|
||
## Tests de référence
|
||
|
||
- tests des options et payloads HTTP ;
|
||
- tests de cycle de vie WebSocket ;
|
||
- tests de sélection de profil Devnet ;
|
||
- tests de System Transfer et Memo ;
|
||
- tests ATA, SPL Token et Token-2022 ;
|
||
- tests de backfill, extraction Core et decode replay ;
|
||
- tests de diagnostics SQL et exports CSV ;
|
||
- tests de journalisation frontend ;
|
||
- test du verrou d’état applicatif et de la séquence splash.
|
||
|
||
Le nombre de tests évolue avec les surfaces raccordées ; la référence de validation est la dernière exécution réussie de `cargo test -p kb-app-demo-desktop`.
|
||
|
||
## Limites durables
|
||
|
||
- le desktop est une application de démonstration et validation, pas le worker de production ;
|
||
- les payloads Tauri sont une API applicative spécifique au frontend ;
|
||
- l’application nécessite un environnement graphique pour sa validation complète.
|
||
|
||
## Panneau Exécution Metadata
|
||
|
||
Depuis la fenêtre principale, choisir **Exécution Devnet → Exécution Metadata**. Le panneau sépare Metaplex Token Metadata, Token-2022 Token Metadata et Solana Program Metadata. Il permet actuellement :
|
||
|
||
- de choisir un scénario synthétique ou un contrat de campagne Devnet ;
|
||
- de sélectionner le profil Devnet ;
|
||
- de préparer et vérifier la base PostgreSQL du profil ;
|
||
- d’afficher les contrats, contrôles de préflight et preuves attendues dans le JSON viewer commun ;
|
||
- de restaurer le scénario sélectionné lors de la réouverture.
|
||
|
||
Un contrat marqué Devnet n’est pas, à lui seul, une exécution réseau. Les champs `networkExecutionPerformed` et `networkEvidenceCollected` doivent rester faux tant qu’aucun appel RPC réel et aucune preuve correspondante n’ont été produits.
|
||
|
||
Les scénarios synthétiques restent disponibles pour inspecter les contrats sans réseau. Le parcours Devnet Metaplex sélectionne au contraire une campagne qualifiée complète ; fixture, simulation, soumission autorisée, replay, matérialisation, idempotence et postconditions restent la responsabilité du runner spécialisé.
|
||
|
||
### Campagnes Metaplex qualifiées
|
||
|
||
Ouvrir **Metaplex Token Metadata -> Campagnes Devnet qualifiées**, sélectionner un profil persistant et préparer PostgreSQL. Le sélecteur présente 11 campagnes : cinq familles `Create -> Mint`, collection, Print/Burn, lifecycle pNFT, escrow, maintenance et Use. Après confirmation opérateur, le desktop appelle le runner correspondant et affiche :
|
||
|
||
- la fixture et son setup ;
|
||
- les exécutions confirmées et les probes indisponibles dans leur ordre réel ;
|
||
- les postconditions de campagne ;
|
||
- les compteurs `confirmed` et `unavailable`.
|
||
|
||
La surface générique par opération reste une API avancée et ne doit pas être utilisée pour reconstruire manuellement ces campagnes dans l’UI.
|
||
|
||
### Campagne Token-2022 Token Metadata
|
||
|
||
Ouvrir l’accordéon **Token-2022 Token Metadata**, sélectionner un profil Devnet persistant et préparer sa base PostgreSQL. Le panneau affiche le contrat fixe de cinq opérations :
|
||
|
||
```text
|
||
Initialize -> UpdateField -> Emit -> RemoveKey -> UpdateAuthority
|
||
```
|
||
|
||
Après confirmation explicite, **Exécuter la campagne Token-2022 Metadata** crée un mint frais avec Metadata Pointer vers lui-même, puis appelle le runner réutilisable pour les cinq opérations. La campagne conserve les simulations, signatures, confirmations, snapshots stateful, postconditions et matérialisations ; `Emit` expose également la return data validée. La fixture et les preuves sont affichées avec le JsonViewer commun.
|
||
|
||
La carte **Exigences** est placée en bas de la colonne droite, après les postconditions. Le journal d’exécution est placé sous les deux colonnes principales et occupe toute la largeur disponible de la page.
|
||
|
||
### Campagne Solana Program Metadata
|
||
|
||
Ouvrir l’accordéon **Solana Program Metadata**, sélectionner un profil Devnet persistant et préparer sa base. L’inventaire affiche deux parcours totalisant neuf opérations :
|
||
|
||
```text
|
||
Buffer : Allocate → Extend → Write → SetAuthority → Trim → Close
|
||
Metadata : Initialize → SetData → SetImmutable
|
||
```
|
||
|
||
Après confirmation explicite, le bouton **Exécuter la campagne complète** appelle le runner réutilisable. Celui-ci réalise deux transferts de préfinancement, puis les neuf simulations et soumissions dans l’ordre. Le panneau affiche :
|
||
|
||
- la fixture et les opérations préparées ;
|
||
- les signatures de préfinancement et les PDA frais ;
|
||
- les neuf simulations et confirmations ;
|
||
- les lectures stateful avant/après ;
|
||
- les rapports de postcondition ;
|
||
- les snapshots matérialisés, sauf pour `Close` qui exige l’absence du compte.
|
||
|
||
La campagne s’arrête au premier échec. Elle ne reprend pas un parcours partiellement exécuté et ne réutilise pas les PDA d’une campagne précédente.
|