v0.1.0-pre.054
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# file: kb-app-demo-desktop/Cargo.toml
|
||||
# version: 4
|
||||
# version: 5
|
||||
|
||||
[package]
|
||||
name = "kb-app-demo-desktop"
|
||||
@@ -21,6 +21,7 @@ path = "src/main.rs"
|
||||
tauri-build.workspace = true
|
||||
|
||||
[dependencies]
|
||||
dotenvy.workspace = true
|
||||
chrono.workspace = true
|
||||
fs2.workspace = true
|
||||
kb-config = { path = "../kb-config" }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: kb-app-demo-desktop/frontend/demo_backfill.html -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 3 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
@@ -155,20 +155,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="backfillLogHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#backfillLogCollapse" aria-expanded="false" aria-controls="backfillLogCollapse">Journal et résultat</button>
|
||||
</h2>
|
||||
<div id="backfillLogCollapse" class="accordion-collapse collapse" aria-labelledby="backfillLogHeading" data-bs-parent="#backfillAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h3 class="h6 mb-0">Journal</h3><button id="clearBackfillLogButton" class="btn btn-sm btn-outline-secondary" type="button">Effacer</button>
|
||||
</div>
|
||||
<textarea id="backfillLogOutput" class="form-control font-monospace mb-3" rows="15" readonly>Aucune campagne exécutée.</textarea>
|
||||
<h3 class="h6">Résumé JSON</h3>
|
||||
<textarea id="backfillSummaryOutput" class="form-control font-monospace" rows="16" readonly>Aucun résultat.</textarea>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0 mt-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h2 class="h5 mb-0">Journal</h2>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button id="copyBackfillLogButton" class="btn btn-outline-primary" type="button">Copier</button>
|
||||
<button id="clearBackfillLogButton" class="btn btn-outline-secondary" type="button">Effacer</button>
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="backfillLogOutput" class="form-control font-monospace app-log-output mb-4" readonly>Aucune campagne exécutée.</textarea>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h2 class="h5 mb-0">Résumé JSON</h2>
|
||||
<button id="copyBackfillSummaryButton" class="btn btn-sm btn-outline-primary" type="button">Copier</button>
|
||||
</div>
|
||||
<div id="backfillSummaryOutput" class="app-json-viewer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -185,4 +188,4 @@
|
||||
<script type="module" src="ts/demo_backfill.ts" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: kb-app-demo-desktop/frontend/demo_config.html -->
|
||||
<!-- version: 2 -->
|
||||
<!-- version: 3 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<div class="card shadow-sm border-0 h-100">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 card-title mb-3">Configuration active</h2>
|
||||
<div id="activeProfileJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||
<div id="activeProfileJson" class="app-json-viewer" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,7 +59,7 @@
|
||||
<div class="card shadow-sm border-0 h-100">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 card-title mb-3">Configuration complète</h2>
|
||||
<div id="fullConfigJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||
<div id="fullConfigJson" class="app-json-viewer" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -68,7 +68,7 @@
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 card-title mb-3">Schéma JSON embarqué</h2>
|
||||
<div id="schemaJson" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||
<div id="schemaJson" class="app-json-viewer" class="app-config-box app-json-viewer mb-0">Chargement...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -90,4 +90,4 @@
|
||||
<script type="module" src="ts/demo_config.ts" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
</div>
|
||||
<textarea id="coreExtractionLogOutput" class="form-control font-monospace mb-3" rows="15" readonly>Aucune campagne exécutée.</textarea>
|
||||
<h3 class="h6">Résumé JSON</h3>
|
||||
<textarea id="coreExtractionSummaryOutput" class="form-control font-monospace" rows="16" readonly>Aucun résultat.</textarea>
|
||||
<textarea id="coreExtractionSummaryOutput" class="form-control font-monospace" rows="16" readonly data-json-viewer="true">Aucun résultat.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -157,4 +157,4 @@
|
||||
<script type="module" src="ts/demo_core_extraction.ts" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -112,9 +112,9 @@
|
||||
<h2 class="h5">Journal</h2>
|
||||
<textarea id="decodeReplayLogOutput" class="form-control font-monospace mb-3" rows="14" readonly>Aucune campagne exécutée.</textarea>
|
||||
<h2 class="h5">Résumé</h2>
|
||||
<textarea id="decodeReplaySummaryOutput" class="form-control font-monospace mb-3" rows="15" readonly>Aucun résultat.</textarea>
|
||||
<textarea id="decodeReplaySummaryOutput" class="form-control font-monospace mb-3" rows="15" readonly data-json-viewer="true">Aucun résultat.</textarea>
|
||||
<h2 class="h5">Diagnostics</h2>
|
||||
<textarea id="decodeReplayDiagnosticsOutput" class="form-control font-monospace" rows="18" readonly>Diagnostics non chargés.</textarea>
|
||||
<textarea id="decodeReplayDiagnosticsOutput" class="form-control font-monospace" rows="18" readonly data-json-viewer="true">Diagnostics non chargés.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: kb-app-demo-desktop/frontend/demo_execution_solana_core.html -->
|
||||
<!-- version: 6 -->
|
||||
<!-- version: 7 -->
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="fr">
|
||||
@@ -12,8 +12,9 @@
|
||||
<body class="app-body">
|
||||
<header class="app-header bg-dark text-light">
|
||||
<nav class="container-fluid h-100 d-flex align-items-center justify-content-between px-4">
|
||||
<div>
|
||||
<h1 class="h4 mb-0">Exécution Solana Core Devnet</h1><small class="text-light-emphasis">System Program uniquement — simulation-first et replay post-exécution</small>
|
||||
<div class="navbar-brand d-flex align-items-center mb-0">
|
||||
<img alt="Logo Khadhroony" src="imgs/logo.png" class="app-logo"/>
|
||||
<span class="ps-2 fs-4 fw-bold text-primary font-logo">Bot3</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2"><span class="badge text-bg-success" id="executionStatusBadge">Prêt</span><button class="btn btn-sm btn-outline-warning" disabled="" id="cancelExecutionButton" type="button">Annuler</button></div>
|
||||
</nav>
|
||||
@@ -21,6 +22,10 @@
|
||||
<main class="app-main">
|
||||
<div class="osb-scrollable pt-1 pb-4" data-simplebar="">
|
||||
<div class="container-fluid py-4 px-4">
|
||||
<div class="card shadow-sm border-0 mb-4"><div class="card-body">
|
||||
<h1 class="h3 card-title mb-2">Exécution Solana Core Devnet</h1>
|
||||
<p class="text-body-secondary mb-0">System Program uniquement — simulation-first et replay post-exécution.</p>
|
||||
</div></div>
|
||||
<div class="alert alert-warning">Cette fenêtre est strictement réservée aux opérations Solana Core. Les opérations SPL sont disponibles dans « Exécution SPL Devnet ».</div>
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-xl-5">
|
||||
@@ -53,14 +58,14 @@
|
||||
<div class="col-12 col-xl-7">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3">Résumé</h2><textarea class="form-control font-monospace" id="executionSummaryOutput" readonly="" rows="14">Aucun résultat.</textarea>
|
||||
<h2 class="h5 mb-3">Résumé</h2><textarea class="form-control font-monospace" id="executionSummaryOutput" readonly="" rows="14" data-json-viewer="true">Aucun résultat.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card shadow-sm border-0 mt-4">
|
||||
<div class="card-body">
|
||||
<h2 class="h5">Plan exact</h2><textarea class="form-control font-monospace" id="executionPlanOutput" readonly="" rows="12">Aucun plan.</textarea>
|
||||
<h2 class="h5 mt-3">Simulation exacte</h2><textarea class="form-control font-monospace" id="executionSimulationOutput" readonly="" rows="12">Aucune simulation.</textarea>
|
||||
<h2 class="h5 mt-3">Confirmation et replay</h2><textarea class="form-control font-monospace" id="executionDiagnosticsOutput" readonly="" rows="12">Aucun diagnostic.</textarea>
|
||||
<h2 class="h5">Plan exact</h2><textarea class="form-control font-monospace" id="executionPlanOutput" readonly="" rows="12" data-json-viewer="true">Aucun plan.</textarea>
|
||||
<h2 class="h5 mt-3">Simulation exacte</h2><textarea class="form-control font-monospace" id="executionSimulationOutput" readonly="" rows="12" data-json-viewer="true">Aucune simulation.</textarea>
|
||||
<h2 class="h5 mt-3">Confirmation et replay</h2><textarea class="form-control font-monospace" id="executionDiagnosticsOutput" readonly="" rows="12" data-json-viewer="true">Aucun diagnostic.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,4 +75,4 @@
|
||||
</main>
|
||||
<script defer="" src="ts/demo_execution_solana_core.ts" type="module"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: kb-app-demo-desktop/frontend/demo_execution_spl.html -->
|
||||
<!-- version: 8 -->
|
||||
<!-- version: 9 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
@@ -12,15 +12,9 @@
|
||||
<body class="app-body">
|
||||
<header class="app-header bg-dark text-light">
|
||||
<nav class="container-fluid h-100 d-flex align-items-center justify-content-between px-4">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="navbar-brand d-flex align-items-center mb-0">
|
||||
<img alt="Logo" src="imgs/logo.png" class="app-logo" />
|
||||
<span class="ps-2 fs-4 fw-bold text-primary font-logo">Bot3</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="h4 mb-0">Exécution SPL Devnet</h1>
|
||||
<small class="text-light-emphasis">Memo, SPL Token classique, Token-2022 et ATA — simulation-first et replay post-exécution</small>
|
||||
</div>
|
||||
<div class="navbar-brand d-flex align-items-center mb-0">
|
||||
<img alt="Logo Khadhroony" src="imgs/logo.png" class="app-logo" />
|
||||
<span class="ps-2 fs-4 fw-bold text-primary font-logo">Bot3</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge text-bg-success" id="executionStatusBadge">Prêt</span>
|
||||
@@ -31,6 +25,10 @@
|
||||
<main class="app-main">
|
||||
<div class="osb-scrollable pt-1 pb-4" data-simplebar="">
|
||||
<div class="container-fluid py-4 px-4">
|
||||
<div class="card shadow-sm border-0 mb-4"><div class="card-body">
|
||||
<h1 class="h3 card-title mb-2">Exécution SPL Devnet</h1>
|
||||
<p class="text-body-secondary mb-0">Memo, SPL Token classique, Token-2022 et ATA — simulation-first et replay post-exécution.</p>
|
||||
</div></div>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
Cette fenêtre est limitée à Devnet. La clé privée du wallet source reste dans le backend Rust et n’est jamais transmise à la WebView.
|
||||
</div>
|
||||
@@ -162,7 +160,7 @@
|
||||
<label class="form-label" for="ataTokenProgramSelect">Token Program cible</label>
|
||||
<select class="form-select" id="ataTokenProgramSelect">
|
||||
<option value="classic">SPL Token classique</option>
|
||||
<option value="token_2022">Token-2022</option>
|
||||
<option value="token2022">Token-2022</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
@@ -199,21 +197,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="splToken2022DecoderHeading"><button aria-controls="splToken2022DecoderCollapse" aria-expanded="false" class="accordion-button collapsed" data-bs-target="#splToken2022DecoderCollapse" data-bs-toggle="collapse" type="button"><span class="d-flex flex-wrap align-items-center justify-content-between gap-2 w-100 me-2"><span>Exécution spl_token_2022 — scénarios publics</span><span class="badge text-bg-success">Exécutable</span></span></button></h2>
|
||||
<h2 class="accordion-header" id="splToken2022DecoderHeading"><button aria-controls="splToken2022DecoderCollapse" aria-expanded="false" class="accordion-button collapsed" data-bs-target="#splToken2022DecoderCollapse" data-bs-toggle="collapse" type="button"><span class="d-flex flex-wrap align-items-center justify-content-between gap-2 w-100 me-2"><span>Exécution spl_token2022 — scénarios publics</span><span class="badge text-bg-success">Exécutable</span></span></button></h2>
|
||||
<div aria-labelledby="splToken2022DecoderHeading" class="accordion-collapse collapse" data-bs-parent="#decoderExecutionAccordion" id="splToken2022DecoderCollapse">
|
||||
<div class="accordion-body">
|
||||
<div class="alert alert-info">Chaque opération est simulée sur le message exact avant toute signature. Les scénarios sont indépendants et réutilisent la fixture chargée dans les deux terminaux.</div>
|
||||
<div class="d-grid mb-3"><button class="btn btn-outline-secondary" id="loadToken2022FixtureButton" type="button">Charger la fixture Token-2022</button></div>
|
||||
<div class="form-text mb-3" id="token2022FixtureHelp">Aucune fixture chargée.</div>
|
||||
<div class="mb-3"><label class="form-label" for="token2022ScenarioSelect">Scénario</label><select class="form-select" id="token2022ScenarioSelect">
|
||||
<option value="token_2022_mint_to_checked">MintToChecked</option>
|
||||
<option value="token_2022_transfer_checked">TransferChecked</option>
|
||||
<option value="token_2022_approve_checked">ApproveChecked</option>
|
||||
<option value="token_2022_revoke">Revoke</option>
|
||||
<option value="token_2022_burn_checked">BurnChecked</option>
|
||||
<option value="token_2022_freeze_account">FreezeAccount</option>
|
||||
<option value="token_2022_thaw_account">ThawAccount</option>
|
||||
<option value="token_2022_close_destination">CloseAccount</option>
|
||||
<option value="token2022_mint_to_checked">MintToChecked</option>
|
||||
<option value="token2022_transfer_checked">TransferChecked</option>
|
||||
<option value="token2022_approve_checked">ApproveChecked</option>
|
||||
<option value="token2022_revoke">Revoke</option>
|
||||
<option value="token2022_burn_checked">BurnChecked</option>
|
||||
<option value="token2022_freeze_account">FreezeAccount</option>
|
||||
<option value="token2022_thaw_account">ThawAccount</option>
|
||||
<option value="token2022_close_destination">CloseAccount</option>
|
||||
</select></div>
|
||||
<div class="mb-3"><label class="form-label" for="token2022SourceInput">Compte source / compte cible</label><input class="form-control font-monospace" id="token2022SourceInput" type="text" /></div>
|
||||
<div class="mb-3"><label class="form-label" for="token2022MintInput">Mint Token-2022</label><input class="form-control font-monospace" id="token2022MintInput" type="text" /></div>
|
||||
@@ -263,7 +261,7 @@
|
||||
</h2>
|
||||
<div class="accordion-collapse collapse" data-bs-parent="#executionDetailsAccordion" id="executionPlanCollapse">
|
||||
<div class="accordion-body">
|
||||
<textarea class="form-control font-monospace" id="executionPlanOutput" readonly="" rows="16">Aucun plan.</textarea>
|
||||
<textarea class="form-control font-monospace" id="executionPlanOutput" readonly="" rows="16" data-json-viewer="true">Aucun plan.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -273,7 +271,7 @@
|
||||
</h2>
|
||||
<div class="accordion-collapse collapse" data-bs-parent="#executionDetailsAccordion" id="executionSimulationCollapse">
|
||||
<div class="accordion-body">
|
||||
<textarea class="form-control font-monospace" id="executionSimulationOutput" readonly="" rows="16">Aucune simulation.</textarea>
|
||||
<textarea class="form-control font-monospace" id="executionSimulationOutput" readonly="" rows="16" data-json-viewer="true">Aucune simulation.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -283,7 +281,7 @@
|
||||
</h2>
|
||||
<div class="accordion-collapse collapse" data-bs-parent="#executionDetailsAccordion" id="executionDiagnosticsCollapse">
|
||||
<div class="accordion-body">
|
||||
<textarea class="form-control font-monospace" id="executionDiagnosticsOutput" readonly="" rows="16">Aucun diagnostic.</textarea>
|
||||
<textarea class="form-control font-monospace" id="executionDiagnosticsOutput" readonly="" rows="16" data-json-viewer="true">Aucun diagnostic.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -405,7 +403,7 @@
|
||||
<div class="card shadow-sm border-0 mt-4">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3">Résumé</h2>
|
||||
<textarea class="form-control font-monospace" id="executionSummaryOutput" readonly="" rows="14">Aucun résultat.</textarea>
|
||||
<textarea class="form-control font-monospace" id="executionSummaryOutput" readonly="" rows="14" data-json-viewer="true">Aucun résultat.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card shadow-sm border-0 mt-4">
|
||||
@@ -430,4 +428,4 @@
|
||||
<script defer="" src="ts/demo_execution_spl.ts" type="module"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
<h2 class="h5 card-title mb-0">Résultat</h2>
|
||||
<button id="copyHttpResultButton" class="btn btn-sm btn-outline-secondary">Copier</button>
|
||||
</div>
|
||||
<textarea id="httpResultOutput" class="form-control font-monospace" rows="18" readonly>Aucune requête exécutée.</textarea>
|
||||
<textarea id="httpResultOutput" class="form-control font-monospace" rows="18" readonly data-json-viewer="true">Aucune requête exécutée.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,4 +93,4 @@
|
||||
<script type="module" src="ts/demo_http.ts" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
|
||||
<main class="app-main">
|
||||
<div class="osb-scrollable pt-1 pb-4" data-simplebar>
|
||||
<div class="container py-4">
|
||||
<div class="container-fluid py-4 px-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap gap-2 justify-content-between align-items-center mb-3">
|
||||
@@ -61,11 +61,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 card-title mb-3">Tables raw/core connues</h2>
|
||||
<div class="table-responsive">
|
||||
<div class="table-responsive app-table-full-width">
|
||||
<table class="table table-sm align-middle mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -112,4 +112,4 @@
|
||||
<script type="module" src="ts/demo_sql_diag.ts" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
|
||||
<main class="app-main">
|
||||
<div class="osb-scrollable pt-1 pb-4" data-simplebar>
|
||||
<div class="container py-4">
|
||||
<div class="container-fluid py-4 px-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap gap-2 justify-content-between align-items-center mb-3">
|
||||
@@ -48,11 +48,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 card-title mb-3">Tables core</h2>
|
||||
<div class="table-responsive">
|
||||
<div class="table-responsive app-table-full-width">
|
||||
<table class="table table-sm align-middle mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -99,4 +99,4 @@
|
||||
<script type="module" src="ts/demo_sql_pg_core.ts" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
|
||||
<main class="app-main">
|
||||
<div class="osb-scrollable pt-1 pb-4" data-simplebar>
|
||||
<div class="container py-4">
|
||||
<div class="container-fluid py-4 px-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap gap-2 justify-content-between align-items-center mb-3">
|
||||
@@ -48,11 +48,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-xl-6">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 card-title mb-3">Transactions canoniques et observations</h2>
|
||||
<div class="table-responsive">
|
||||
<div class="table-responsive app-table-full-width">
|
||||
<table class="table table-sm align-middle mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<h2 class="h5 card-title mb-0">Messages</h2>
|
||||
<button id="copyWsResultButton" class="btn btn-sm btn-outline-secondary">Copier</button>
|
||||
</div>
|
||||
<textarea id="wsResultOutput" class="form-control font-monospace" rows="16" readonly>Aucune connexion active.</textarea>
|
||||
<textarea id="wsResultOutput" class="form-control font-monospace" rows="16" readonly data-json-viewer="true">Aucune connexion active.</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: kb-app-demo-desktop/frontend/main.html -->
|
||||
<!-- version: 6 -->
|
||||
<!-- version: 7 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
@@ -24,19 +24,24 @@
|
||||
<ul class="dropdown-menu dropdown-menu-end">
|
||||
<li><a id="openDemoConfigLink" class="dropdown-item" href="#">Configuration</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a id="openDemoWsLink" class="dropdown-item" href="#">WebSocket standard</a></li>
|
||||
<li><h6 class="dropdown-header">Transport et collecte</h6></li>
|
||||
<li><a id="openDemoHttpLink" class="dropdown-item" href="#">HTTP JSON-RPC</a></li>
|
||||
<li><a id="openDemoWsLink" class="dropdown-item" href="#">WebSocket standard</a></li>
|
||||
<li><a id="openDemoBackfillLink" class="dropdown-item" href="#">Backfill HTTP</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><h6 class="dropdown-header">Pipeline</h6></li>
|
||||
<li><a id="openDemoCoreExtractionLink" class="dropdown-item" href="#">Extraction core</a></li>
|
||||
<li><a id="openDemoDecodeReplayLink" class="dropdown-item" href="#">Décodage contextualisé</a></li>
|
||||
<li><a id="openDemoExecutionSolanaCoreLink" class="dropdown-item" href="#">Exécution Solana Core</a></li>
|
||||
<li><a id="openDemoExecutionSplLink" class="dropdown-item" href="#">Exécution SPL</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><h6 class="dropdown-header">Stockage</h6></li>
|
||||
<li><a id="openDemoSqlDiagLink" class="dropdown-item" href="#">SQL diagnostics</a></li>
|
||||
<li><a id="openDemoSqlPgRawLink" class="dropdown-item" href="#">SQL PostgreSQL raw</a></li>
|
||||
<li><a id="openDemoSqlPgCoreLink" class="dropdown-item" href="#">SQL PostgreSQL core</a></li>
|
||||
<li><a id="openDemoSqlReplayCandidatesLink" class="dropdown-item" href="#">SQL replay candidates</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><h6 class="dropdown-header">Exécution Devnet</h6></li>
|
||||
<li><a id="openDemoExecutionSolanaCoreLink" class="dropdown-item" href="#">Solana Core</a></li>
|
||||
<li><a id="openDemoExecutionSplLink" class="dropdown-item" href="#">SPL</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -383,3 +383,38 @@ video#vbackground:not([playsinline]) {
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.app-json-viewer {
|
||||
display: block;
|
||||
height: 24rem;
|
||||
max-height: 24rem;
|
||||
overflow: auto;
|
||||
overscroll-behavior: contain;
|
||||
border: 1px solid var(--bs-border-color);
|
||||
border-radius: var(--bs-border-radius);
|
||||
background: var(--bs-body-bg);
|
||||
}
|
||||
|
||||
.app-json-viewer > andypf-json-viewer {
|
||||
display: block;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.app-log-output {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 18rem;
|
||||
max-height: 18rem;
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.app-table-full-width {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.app-table-full-width table {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// file: kb_demo_app/frontend/sass/main.scss
|
||||
// file: kb-app-demo-desktop/frontend/sass/main.scss
|
||||
// version: 1
|
||||
|
||||
@import "bootstrap/scss/functions";
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// file: kb-app-demo-desktop/frontend/ts/demo_backfill.ts
|
||||
// version: 5
|
||||
// version: 6
|
||||
|
||||
import * as bootstrap from "bootstrap";
|
||||
import "simplebar";
|
||||
import "@andypf/json-viewer";
|
||||
import ResizeObserver from "resize-observer-polyfill";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
@@ -146,7 +147,7 @@ function validationMessage(request: DemoBackfillRequest): string | null {
|
||||
}
|
||||
|
||||
function reportValidationWarning(message: string): void {
|
||||
element<HTMLTextAreaElement>("#backfillSummaryOutput").value = JSON.stringify({ validation: message }, null, 2);
|
||||
renderBackfillSummary({ validation: message });
|
||||
appendLog({ timestamp: new Date().toISOString(), level: "warn", message });
|
||||
frontendDebug("kb-app-demo-desktop.frontend.backfill", `Backfill request rejected locally: ${message}`);
|
||||
}
|
||||
@@ -174,10 +175,10 @@ async function executeBackfill(mode: string): Promise<void> {
|
||||
return;
|
||||
}
|
||||
setRunning(true);
|
||||
element<HTMLTextAreaElement>("#backfillSummaryOutput").value = "Exécution en cours...";
|
||||
renderBackfillSummary({ status: "Exécution en cours" });
|
||||
appendLog({ timestamp: new Date().toISOString(), level: "info", message: `Démarrage du mode ${mode}` });
|
||||
const summary = await invoke<DemoBackfillSummaryPayload>("demo_backfill_execute", { request });
|
||||
element<HTMLTextAreaElement>("#backfillSummaryOutput").value = JSON.stringify(summary, null, 2);
|
||||
renderBackfillSummary(summary);
|
||||
appendLog({
|
||||
timestamp: new Date().toISOString(),
|
||||
level: summary.cancelled ? "warn" : "info",
|
||||
@@ -185,7 +186,7 @@ async function executeBackfill(mode: string): Promise<void> {
|
||||
});
|
||||
} catch (caughtError) {
|
||||
const message = caughtError instanceof Error ? caughtError.message : String(caughtError);
|
||||
element<HTMLTextAreaElement>("#backfillSummaryOutput").value = JSON.stringify({ error: message }, null, 2);
|
||||
renderBackfillSummary({ error: message });
|
||||
appendLog({ timestamp: new Date().toISOString(), level: "error", message });
|
||||
frontendError("kb-app-demo-desktop.frontend.backfill", `Backfill failed: ${message}`);
|
||||
} finally {
|
||||
@@ -232,6 +233,28 @@ async function loadOptions(): Promise<void> {
|
||||
setRunning(options.running);
|
||||
}
|
||||
|
||||
|
||||
function renderBackfillSummary(value: unknown): void {
|
||||
const container = document.querySelector<HTMLElement>("#backfillSummaryOutput");
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
container.textContent = "";
|
||||
const viewer = document.createElement("andypf-json-viewer");
|
||||
viewer.setAttribute("indent", "2");
|
||||
viewer.setAttribute("expanded", "1");
|
||||
viewer.setAttribute("theme", "default-light");
|
||||
viewer.setAttribute("show-data-types", "true");
|
||||
viewer.setAttribute("show-toolbar", "false");
|
||||
viewer.setAttribute("show-copy", "true");
|
||||
viewer.setAttribute("data", JSON.stringify(value ?? { status: "Aucun résultat" }, null, 2));
|
||||
container.appendChild(viewer);
|
||||
}
|
||||
|
||||
async function copyText(value: string): Promise<void> {
|
||||
await navigator.clipboard.writeText(value);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
installFrontendConsoleBridge("kb-app-demo-desktop.frontend.backfill");
|
||||
frontendDebug("kb-app-demo-desktop.frontend.backfill", "backfill demo window loaded");
|
||||
@@ -264,4 +287,14 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
appendLog({ timestamp: new Date().toISOString(), level: "error", message });
|
||||
frontendError("kb-app-demo-desktop.frontend.backfill", `Options loading failed: ${message}`);
|
||||
});
|
||||
|
||||
document.querySelector<HTMLButtonElement>("#copyBackfillLogButton")?.addEventListener("click", async () => {
|
||||
const value = document.querySelector<HTMLTextAreaElement>("#backfillLogOutput")?.value ?? "";
|
||||
await copyText(value);
|
||||
});
|
||||
document.querySelector<HTMLButtonElement>("#copyBackfillSummaryButton")?.addEventListener("click", async () => {
|
||||
const value = document.querySelector("#backfillSummaryOutput andypf-json-viewer")?.getAttribute("data") ?? "";
|
||||
await copyText(value);
|
||||
});
|
||||
renderBackfillSummary(null);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// file: kb-app-demo-desktop/frontend/ts/frontend_log.ts
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
//! Frontend logging helpers that preserve explicit tracing targets.
|
||||
|
||||
import "@andypf/json-viewer";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import type { FrontendLogPayload } from "./bindings/kb_app_demo_desktop/frontend_log/FrontendLogPayload.ts";
|
||||
|
||||
@@ -87,7 +88,80 @@ function buildConsoleBridge(level: FrontendLogLevel, target: string, original: C
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function upgradeJsonTextareas(): void {
|
||||
document.querySelectorAll<HTMLTextAreaElement>("textarea[data-json-viewer]").forEach(textarea => {
|
||||
if (textarea.dataset.jsonViewerInstalled === "true") {
|
||||
return;
|
||||
}
|
||||
textarea.dataset.jsonViewerInstalled = "true";
|
||||
const container = document.createElement("div");
|
||||
container.className = "app-json-viewer";
|
||||
const viewer = document.createElement("andypf-json-viewer");
|
||||
viewer.setAttribute("indent", "2");
|
||||
viewer.setAttribute("expanded", "1");
|
||||
viewer.setAttribute("theme", "default-light");
|
||||
viewer.setAttribute("show-data-types", "true");
|
||||
viewer.setAttribute("show-toolbar", "false");
|
||||
viewer.setAttribute("show-copy", "true");
|
||||
const descriptor = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value");
|
||||
let currentValue = textarea.value;
|
||||
const render = (value: string): void => {
|
||||
currentValue = value;
|
||||
let parsed: unknown = value;
|
||||
try {
|
||||
parsed = JSON.parse(value) as unknown;
|
||||
} catch {
|
||||
parsed = { message: value };
|
||||
}
|
||||
viewer.setAttribute("data", JSON.stringify(parsed, null, 2));
|
||||
};
|
||||
Object.defineProperty(textarea, "value", {
|
||||
configurable: true,
|
||||
get: () => currentValue,
|
||||
set: (value: string) => {
|
||||
descriptor?.set?.call(textarea, value);
|
||||
render(value);
|
||||
},
|
||||
});
|
||||
textarea.classList.add("d-none");
|
||||
textarea.insertAdjacentElement("afterend", container);
|
||||
container.appendChild(viewer);
|
||||
render(currentValue);
|
||||
});
|
||||
}
|
||||
|
||||
function upgradeLogOutputs(): void {
|
||||
document.querySelectorAll<HTMLTextAreaElement>("textarea[id$='LogOutput'], textarea[data-log-output]").forEach(textarea => {
|
||||
if (textarea.dataset.logOutputInstalled === "true") {
|
||||
return;
|
||||
}
|
||||
textarea.dataset.logOutputInstalled = "true";
|
||||
textarea.classList.add("app-log-output");
|
||||
const toolbar = document.createElement("div");
|
||||
toolbar.className = "d-flex justify-content-end gap-2 mb-2";
|
||||
const copyButton = document.createElement("button");
|
||||
copyButton.type = "button";
|
||||
copyButton.className = "btn btn-sm btn-outline-secondary";
|
||||
copyButton.textContent = "Copier";
|
||||
copyButton.addEventListener("click", () => {
|
||||
void navigator.clipboard.writeText(textarea.value);
|
||||
});
|
||||
const clearButton = document.createElement("button");
|
||||
clearButton.type = "button";
|
||||
clearButton.className = "btn btn-sm btn-outline-secondary";
|
||||
clearButton.textContent = "Effacer";
|
||||
clearButton.addEventListener("click", () => {
|
||||
textarea.value = "";
|
||||
});
|
||||
toolbar.append(copyButton, clearButton);
|
||||
textarea.insertAdjacentElement("beforebegin", toolbar);
|
||||
});
|
||||
}
|
||||
|
||||
export function installFrontendConsoleBridge(target: string): void {
|
||||
upgradeJsonTextareas();
|
||||
upgradeLogOutputs();
|
||||
console.trace = buildConsoleBridge("trace", target, originalConsole.trace);
|
||||
console.debug = buildConsoleBridge("debug", target, originalConsole.debug);
|
||||
console.log = buildConsoleBridge("info", target, originalConsole.log);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-app-demo-desktop/src/app_state.rs
|
||||
// version: 6
|
||||
// version: 8
|
||||
|
||||
//! Shared Tauri application state and startup initialization.
|
||||
|
||||
@@ -28,6 +28,7 @@ pub(crate) struct AppState {
|
||||
impl crate::AppState {
|
||||
/// Initializes configuration, logging and shared runtime state.
|
||||
pub(crate) fn initialize() -> kb_core::Result<crate::AppState> {
|
||||
load_workspace_dotenv();
|
||||
let config_path = resolve_config_path();
|
||||
let app_config = match kb_config::read_config_json_file(&config_path) {
|
||||
std::result::Result::Ok(config) => config,
|
||||
@@ -179,6 +180,23 @@ impl crate::AppState {
|
||||
}
|
||||
}
|
||||
|
||||
fn load_workspace_dotenv() {
|
||||
let workspace_path = crate::workspace_root_dir().join(".env");
|
||||
load_dotenv_path(&workspace_path);
|
||||
let desktop_path = crate::workspace_root_dir().join("kb-app-demo-desktop/.env");
|
||||
load_dotenv_path(&desktop_path);
|
||||
}
|
||||
|
||||
fn load_dotenv_path(path: &std::path::Path) {
|
||||
let result = dotenvy::from_path(path);
|
||||
if let std::result::Result::Err(error) = result {
|
||||
if matches!(error, dotenvy::Error::Io(ref io_error) if io_error.kind() == std::io::ErrorKind::NotFound) {
|
||||
return;
|
||||
}
|
||||
eprintln!("cannot load {}: {error}", path.display());
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_logging_config(config: &kb_config::LoggingConfig) -> kb_logging::LoggingConfig {
|
||||
let mut targets = std::vec::Vec::<kb_logging::LogTargetConfig>::new();
|
||||
for target in &config.targets {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-app-demo-desktop/src/demo_decode_replay.rs
|
||||
// version: 25
|
||||
// version: 27
|
||||
|
||||
//! Tauri commands and UI payloads for contextual instruction decode replay.
|
||||
|
||||
@@ -299,7 +299,7 @@ pub(crate) struct DemoDecodeReplayObserver<'a> {
|
||||
|
||||
impl kb_pipeline::DecodeReplayObserver for crate::DemoDecodeReplayObserver<'_> {
|
||||
fn on_progress(&self, event: &kb_pipeline::DecodeReplayProgressEvent) {
|
||||
let payload = DemoDecodeReplayProgressPayload {
|
||||
let payload = crate::DemoDecodeReplayProgressPayload {
|
||||
campaign_id: self.campaign_id.clone(),
|
||||
timestamp: event.timestamp.clone(),
|
||||
level: event.level.code().to_string(),
|
||||
@@ -727,7 +727,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
names,
|
||||
std::vec![
|
||||
"kb_decoder_metadata_metaplex_token_metadata".to_string(),
|
||||
"metadata_metaplex_token_metadata".to_string(),
|
||||
"solana_native_classifier".to_string(),
|
||||
"spl_associated_token_account".to_string(),
|
||||
"spl_elgamal_registry".to_string(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-app-demo-desktop/src/tauri.rs
|
||||
// version: 9
|
||||
// version: 10
|
||||
|
||||
//! Tauri runtime assembly and private command wrappers.
|
||||
|
||||
@@ -92,6 +92,16 @@ pub fn run() -> kb_core::Result<()> {
|
||||
open_demo_config_window,
|
||||
load_demo_config,
|
||||
]);
|
||||
builder = builder.on_window_event(|window, event| {
|
||||
if window.label() != "main" || !matches!(event, tauri::WindowEvent::Destroyed) {
|
||||
return;
|
||||
}
|
||||
let app_handle = window.app_handle().clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let state = app_handle.state::<crate::AppState>();
|
||||
crate::disconnect_demo_ws_app_state(&state, false).await;
|
||||
});
|
||||
});
|
||||
builder = builder.plugin(tracing_builder.build::<tauri::Wry>());
|
||||
builder = builder.setup(|app| {
|
||||
let splash_window = match app.get_webview_window("splash") {
|
||||
@@ -112,6 +122,7 @@ pub fn run() -> kb_core::Result<()> {
|
||||
)));
|
||||
},
|
||||
};
|
||||
let app_handle = app.handle().clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let started_at = tokio::time::Instant::now();
|
||||
crate::emit_splash_order(
|
||||
@@ -135,6 +146,8 @@ pub fn run() -> kb_core::Result<()> {
|
||||
std::option::Option::None,
|
||||
std::option::Option::None,
|
||||
);
|
||||
let state = app_handle.state::<crate::AppState>();
|
||||
crate::initialize_postgres_schema_for_startup(&state, &splash_window).await;
|
||||
crate::emit_splash_order(
|
||||
&splash_window,
|
||||
"fadein",
|
||||
@@ -230,7 +243,7 @@ fn open_demo_core_extraction_window(
|
||||
"demo_core_extraction",
|
||||
tauri::WebviewUrl::App("demo_core_extraction.html".into()),
|
||||
)
|
||||
.title("Khadhroony Bot2 - Extraction canonical vers core")
|
||||
.title("Khadhroony Bot3 - Extraction canonical vers core")
|
||||
.inner_size(1280.0, 860.0)
|
||||
.min_inner_size(960.0, 620.0)
|
||||
.resizable(true)
|
||||
@@ -341,7 +354,7 @@ fn open_demo_decode_replay_window(
|
||||
"demo_decode_replay",
|
||||
tauri::WebviewUrl::App("demo_decode_replay.html".into()),
|
||||
)
|
||||
.title("Khadhroony Bot2 - Décodage et matérialisation")
|
||||
.title("Khadhroony Bot3 - Décodage et matérialisation")
|
||||
.inner_size(1320.0, 900.0)
|
||||
.min_inner_size(980.0, 660.0)
|
||||
.resizable(true)
|
||||
|
||||
Reference in New Issue
Block a user