0.7.22
This commit is contained in:
255
kb_app/frontend/demo_pipeline.html
Normal file
255
kb_app/frontend/demo_pipeline.html
Normal file
@@ -0,0 +1,255 @@
|
||||
<!-- file: kb_app/frontend/demo_pipeline.html -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Khadhroony-BoBoBot — Demo Pipeline</title>
|
||||
<link rel="stylesheet" href="sass/main.scss" />
|
||||
</head>
|
||||
|
||||
<body class="bg-body-tertiary">
|
||||
<header class="app-header">
|
||||
<nav class="navbar navbar-expand-lg h-100 py-0 bg-light text-dark">
|
||||
<div class="container my-0">
|
||||
<a class="navbar-brand d-flex align-items-center" href="/">
|
||||
<img alt="Logo" src="imgs/logo.png" class="app-logo" />
|
||||
<span class="ps-2 fs-4 fw-bold text-primary font-logo">Demo Pipeline</span>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="app-main">
|
||||
<div class="osb-scrollable pt-1 pb-4" data-simplebar>
|
||||
<div class="container vcentered sketchy-translucid py-4">
|
||||
<div class="row g-4">
|
||||
<div class="col-12 col-xxl-4">
|
||||
<div class="card shadow-sm border-0 h-100">
|
||||
<div class="card-body">
|
||||
<h1 class="h4 mb-3">Inspection par signature</h1>
|
||||
<p class="text-body-secondary mb-3">
|
||||
Cette fenêtre inspecte la donnée déjà persistée dans <code>kb_lib</code> pour une
|
||||
signature donnée et affiche l’état du pipeline <code>0.7.x</code>.
|
||||
</p>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipelineSignatureInput" class="form-label">Signature</label>
|
||||
<input id="demoPipelineSignatureInput" type="text" class="form-control font-monospace" spellcheck="false" placeholder="Signature Solana déjà présente dans la base locale" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipelineCustomTimeframeInput" class="form-label">
|
||||
Timeframe custom optionnel (secondes)
|
||||
</label>
|
||||
<input id="demoPipelineCustomTimeframeInput" type="number" min="1" step="1" class="form-control" placeholder="Ex: 120" />
|
||||
<div class="form-text">
|
||||
Les timeframes matérialisés restent chargés depuis la base. Une valeur custom déclenche
|
||||
une régénération à la demande.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 mb-4">
|
||||
<button id="demoPipelineInspectButton" type="button" class="btn btn-primary">
|
||||
Inspecter
|
||||
</button>
|
||||
<button id="demoPipelineClearButton" type="button" class="btn btn-outline-secondary">
|
||||
Vider
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hr class="my-4" />
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipelineTokenMintInput" class="form-label">Token mint</label>
|
||||
<input id="demoPipelineTokenMintInput" type="text" class="form-control font-monospace" spellcheck="false" placeholder="Mint SPL déjà présent dans la base locale" />
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 mb-4">
|
||||
<button id="demoPipelineInspectTokenButton" type="button" class="btn btn-outline-primary">
|
||||
Inspecter token
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hr class="my-4" />
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipelinePairIdInput" class="form-label">Pair id</label>
|
||||
<input
|
||||
id="demoPipelinePairIdInput"
|
||||
type="number"
|
||||
min="1"
|
||||
step="1"
|
||||
class="form-control"
|
||||
placeholder="Identifiant interne de la paire"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 mb-3">
|
||||
<button id="demoPipelineInspectPairButton" type="button" class="btn btn-outline-primary">
|
||||
Inspecter pair
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipelinePoolAddressInput" class="form-label">Pool address</label>
|
||||
<input
|
||||
id="demoPipelinePoolAddressInput"
|
||||
type="text"
|
||||
class="form-control font-monospace"
|
||||
spellcheck="false"
|
||||
placeholder="Adresse du pool déjà présent dans la base locale"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 mb-4">
|
||||
<button id="demoPipelineInspectPoolButton" type="button" class="btn btn-outline-primary">
|
||||
Inspecter pool
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hr class="my-4" />
|
||||
|
||||
<div class="small text-body-secondary">
|
||||
<div><strong>But :</strong> vérifier rapidement la cohérence du pipeline <code>0.7.x</code>.</div>
|
||||
<div><strong>Portée :</strong> lecture seule depuis SQLite via <code>kb_lib</code>.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-xxl-8">
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3">Résumé</h2>
|
||||
<textarea id="demoPipelineSummaryTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion" id="demoPipelineAccordion">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingTransaction">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTransaction" aria-expanded="true" aria-controls="collapseTransaction">
|
||||
Transaction résolue
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseTransaction" class="accordion-collapse collapse show" aria-labelledby="headingTransaction" data-bs-parent="#demoPipelineAccordion">
|
||||
<div class="accordion-body">
|
||||
<textarea id="demoPipelineTransactionTextarea" class="form-control font-monospace" rows="14" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingDecodedEvents">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseDecodedEvents" aria-expanded="false" aria-controls="collapseDecodedEvents">
|
||||
Decoded events
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseDecodedEvents" class="accordion-collapse collapse" aria-labelledby="headingDecodedEvents" data-bs-parent="#demoPipelineAccordion">
|
||||
<div class="accordion-body">
|
||||
<textarea id="demoPipelineDecodedEventsTextarea" class="form-control font-monospace" rows="14" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingPools">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapsePools" aria-expanded="false" aria-controls="collapsePools">
|
||||
Pools / pairs / origins
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapsePools" class="accordion-collapse collapse" aria-labelledby="headingPools" data-bs-parent="#demoPipelineAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Pools</label>
|
||||
<textarea id="demoPipelinePoolsTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Pairs</label>
|
||||
<textarea id="demoPipelinePairsTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Launch attributions</label>
|
||||
<textarea id="demoPipelineLaunchAttributionsTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">Pool origins</label>
|
||||
<textarea id="demoPipelinePoolOriginsTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingWallets">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseWallets" aria-expanded="false" aria-controls="collapseWallets">
|
||||
Wallets / participations / holdings
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseWallets" class="accordion-collapse collapse" aria-labelledby="headingWallets" data-bs-parent="#demoPipelineAccordion">
|
||||
<div class="accordion-body">
|
||||
<textarea id="demoPipelineWalletsTextarea" class="form-control font-monospace" rows="16" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingTrades">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTrades" aria-expanded="false" aria-controls="collapseTrades">
|
||||
Trades / metrics / candles / analytic signals
|
||||
</button>
|
||||
</h2>
|
||||
<div id="collapseTrades" class="accordion-collapse collapse" aria-labelledby="headingTrades" data-bs-parent="#demoPipelineAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Trade events</label>
|
||||
<textarea id="demoPipelineTradeEventsTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Pair metrics</label>
|
||||
<textarea id="demoPipelinePairMetricsTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Pair candles</label>
|
||||
<textarea id="demoPipelinePairCandlesTextarea" class="form-control font-monospace" rows="12" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label class="form-label">Pair analytic signals</label>
|
||||
<textarea id="demoPipelinePairAnalyticSignalsTextarea" class="form-control font-monospace" rows="12" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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-3">
|
||||
<h2 class="h5 mb-0">Log UI</h2>
|
||||
<button id="demoPipelineClearLogButton" type="button" class="btn btn-outline-secondary btn-sm">Clear log</button>
|
||||
</div>
|
||||
<textarea id="demoPipelineLogTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="app-footer bg-dark text-light">
|
||||
<div class="container h-100 d-flex align-items-center">
|
||||
<div class="row flex-grow-1 align-items-center">
|
||||
<div class="col-12 col-md-6 text-center text-small my-1 my-md-0">
|
||||
© 2026 SASEDEV — Demo Pipeline
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script type="module" src="ts/demo_pipeline.ts" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -28,6 +28,9 @@
|
||||
<button id="openDemoWsManagerButton" type="button" class="btn btn-outline-primary">
|
||||
Demo Ws Manager
|
||||
</button>
|
||||
<button id="openDemoPipelineButton" type="button" class="btn btn-primary">
|
||||
Ouvrir Demo Pipeline
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -72,6 +75,9 @@
|
||||
<button id="openDemoWsManagerButtonSecondary" type="button" class="btn btn-primary">
|
||||
Ouvrir Demo Ws Manager
|
||||
</button>
|
||||
<button id="openDemoPipelineButtonSecondary" type="button" class="btn btn-primary">
|
||||
Ouvrir Demo Pipeline
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
420
kb_app/frontend/ts/demo_pipeline.ts
Normal file
420
kb_app/frontend/ts/demo_pipeline.ts
Normal file
@@ -0,0 +1,420 @@
|
||||
// file: kb_app/frontend/ts/demo_pipeline.ts
|
||||
|
||||
import * as bootstrap from "bootstrap";
|
||||
import "simplebar";
|
||||
import ResizeObserver from "resize-observer-polyfill";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { debug, takeoverConsole } from "@fltsci/tauri-plugin-tracing";
|
||||
|
||||
(window as Window & typeof globalThis & { bootstrap?: typeof bootstrap }).bootstrap = bootstrap;
|
||||
(window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver;
|
||||
|
||||
interface DemoPipelineInspectRequest {
|
||||
signature: string;
|
||||
customTimeframeSeconds: number | null;
|
||||
}
|
||||
|
||||
interface DemoPipelineInspectPayload {
|
||||
signature: string;
|
||||
summaryJson: string;
|
||||
transactionJson: string;
|
||||
decodedEventsJson: string;
|
||||
poolsJson: string;
|
||||
pairsJson: string;
|
||||
launchAttributionsJson: string;
|
||||
poolOriginsJson: string;
|
||||
walletsJson: string;
|
||||
tradeEventsJson: string;
|
||||
pairMetricsJson: string;
|
||||
pairCandlesJson: string;
|
||||
pairAnalyticSignalsJson: string;
|
||||
}
|
||||
|
||||
interface DemoPipelineInspectTokenRequest {
|
||||
tokenMint: string;
|
||||
customTimeframeSeconds: number | null;
|
||||
}
|
||||
|
||||
interface DemoPipelineInspectPairRequest {
|
||||
pairId: number;
|
||||
customTimeframeSeconds: number | null;
|
||||
}
|
||||
|
||||
interface DemoPipelineInspectPoolRequest {
|
||||
poolAddress: string;
|
||||
customTimeframeSeconds: number | null;
|
||||
}
|
||||
|
||||
function appendLogLine(textarea: HTMLTextAreaElement, line: string): void {
|
||||
const now = new Date();
|
||||
const timestamp = now.toLocaleTimeString("fr-CH", { hour12: false });
|
||||
|
||||
const lines = textarea.value === "" ? [] : textarea.value.split("\n");
|
||||
lines.push(`[${timestamp}] ${line}`);
|
||||
|
||||
const maxLines = 300;
|
||||
textarea.value = lines.slice(-maxLines).join("\n");
|
||||
textarea.scrollTop = textarea.scrollHeight;
|
||||
}
|
||||
|
||||
function clearInspection(
|
||||
summaryTextarea: HTMLTextAreaElement,
|
||||
transactionTextarea: HTMLTextAreaElement,
|
||||
decodedEventsTextarea: HTMLTextAreaElement,
|
||||
poolsTextarea: HTMLTextAreaElement,
|
||||
pairsTextarea: HTMLTextAreaElement,
|
||||
launchAttributionsTextarea: HTMLTextAreaElement,
|
||||
poolOriginsTextarea: HTMLTextAreaElement,
|
||||
walletsTextarea: HTMLTextAreaElement,
|
||||
tradeEventsTextarea: HTMLTextAreaElement,
|
||||
pairMetricsTextarea: HTMLTextAreaElement,
|
||||
pairCandlesTextarea: HTMLTextAreaElement,
|
||||
pairAnalyticSignalsTextarea: HTMLTextAreaElement,
|
||||
): void {
|
||||
summaryTextarea.value = "";
|
||||
transactionTextarea.value = "";
|
||||
decodedEventsTextarea.value = "";
|
||||
poolsTextarea.value = "";
|
||||
pairsTextarea.value = "";
|
||||
launchAttributionsTextarea.value = "";
|
||||
poolOriginsTextarea.value = "";
|
||||
walletsTextarea.value = "";
|
||||
tradeEventsTextarea.value = "";
|
||||
pairMetricsTextarea.value = "";
|
||||
pairCandlesTextarea.value = "";
|
||||
pairAnalyticSignalsTextarea.value = "";
|
||||
}
|
||||
|
||||
function readCustomTimeframeSeconds(
|
||||
input: HTMLInputElement,
|
||||
logTextarea: HTMLTextAreaElement,
|
||||
): number | null | undefined {
|
||||
const customTimeframeText = input.value.trim();
|
||||
if (customTimeframeText === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parsed = Number.parseInt(customTimeframeText, 10);
|
||||
if (Number.isNaN(parsed) || parsed <= 0) {
|
||||
appendLogLine(logTextarea, `[ui] invalid custom timeframe '${customTimeframeText}'`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
void takeoverConsole();
|
||||
debug("demo_pipeline window loaded");
|
||||
|
||||
const sidebarToggle = document.querySelector<HTMLButtonElement>('#sidebarToggle');
|
||||
if (sidebarToggle) {
|
||||
// restaurer l’état depuis localStorage
|
||||
if (localStorage.getItem('sidebar-toggle') === 'true') {
|
||||
document.body.classList.add('sidenav-toggled');
|
||||
}
|
||||
|
||||
sidebarToggle.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
document.body.classList.toggle('sidenav-toggled');
|
||||
localStorage.setItem('sidebar-toggle', document.body.classList.contains('sidenav-toggled') ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
||||
Array.from(tooltipTriggerList).map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
|
||||
const toastElList = document.querySelectorAll('.toast');
|
||||
Array.from(toastElList).map(toastEl => new bootstrap.Toast(toastEl));
|
||||
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]');
|
||||
Array.from(popoverTriggerList).map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl));
|
||||
|
||||
const gobackto = location.pathname + location.search;
|
||||
|
||||
document.querySelectorAll<HTMLAnchorElement>('a[data-setlang]').forEach((a) => {
|
||||
const href = a.getAttribute("href");
|
||||
if (!href) return; // pas de href => on ignore
|
||||
|
||||
const url = new URL(href, location.origin);
|
||||
url.searchParams.set("gobackto", gobackto);
|
||||
|
||||
// conserve une URL relative (path + query)
|
||||
a.setAttribute("href", url.pathname + "?" + url.searchParams.toString());
|
||||
});
|
||||
|
||||
const signatureInput = document.querySelector<HTMLInputElement>("#demoPipelineSignatureInput");
|
||||
const customTimeframeInput = document.querySelector<HTMLInputElement>("#demoPipelineCustomTimeframeInput");
|
||||
const inspectButton = document.querySelector<HTMLButtonElement>("#demoPipelineInspectButton");
|
||||
const clearButton = document.querySelector<HTMLButtonElement>("#demoPipelineClearButton");
|
||||
const clearLogButton = document.querySelector<HTMLButtonElement>("#demoPipelineClearLogButton");
|
||||
|
||||
const summaryTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineSummaryTextarea");
|
||||
const transactionTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineTransactionTextarea");
|
||||
const decodedEventsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineDecodedEventsTextarea");
|
||||
const poolsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelinePoolsTextarea");
|
||||
const pairsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelinePairsTextarea");
|
||||
const launchAttributionsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineLaunchAttributionsTextarea");
|
||||
const poolOriginsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelinePoolOriginsTextarea");
|
||||
const walletsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineWalletsTextarea");
|
||||
const tradeEventsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineTradeEventsTextarea");
|
||||
const pairMetricsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelinePairMetricsTextarea");
|
||||
const pairCandlesTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelinePairCandlesTextarea");
|
||||
const pairAnalyticSignalsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelinePairAnalyticSignalsTextarea");
|
||||
const logTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineLogTextarea");
|
||||
const tokenMintInput = document.querySelector<HTMLInputElement>("#demoPipelineTokenMintInput");
|
||||
const inspectTokenButton = document.querySelector<HTMLButtonElement>("#demoPipelineInspectTokenButton");
|
||||
const pairIdInput = document.querySelector<HTMLInputElement>("#demoPipelinePairIdInput");
|
||||
const inspectPairButton = document.querySelector<HTMLButtonElement>("#demoPipelineInspectPairButton");
|
||||
const poolAddressInput = document.querySelector<HTMLInputElement>("#demoPipelinePoolAddressInput");
|
||||
const inspectPoolButton = document.querySelector<HTMLButtonElement>("#demoPipelineInspectPoolButton");
|
||||
|
||||
if (
|
||||
!pairIdInput ||
|
||||
!inspectPairButton ||
|
||||
!poolAddressInput ||
|
||||
!inspectPoolButton ||
|
||||
!tokenMintInput ||
|
||||
!inspectTokenButton ||
|
||||
!signatureInput ||
|
||||
!customTimeframeInput ||
|
||||
!inspectButton ||
|
||||
!clearButton ||
|
||||
!clearLogButton ||
|
||||
!summaryTextarea ||
|
||||
!transactionTextarea ||
|
||||
!decodedEventsTextarea ||
|
||||
!poolsTextarea ||
|
||||
!pairsTextarea ||
|
||||
!launchAttributionsTextarea ||
|
||||
!poolOriginsTextarea ||
|
||||
!walletsTextarea ||
|
||||
!tradeEventsTextarea ||
|
||||
!pairMetricsTextarea ||
|
||||
!pairCandlesTextarea ||
|
||||
!pairAnalyticSignalsTextarea ||
|
||||
!logTextarea
|
||||
) {
|
||||
console.error("demo_pipeline DOM is incomplete");
|
||||
return;
|
||||
}
|
||||
|
||||
clearButton.addEventListener("click", () => {
|
||||
clearInspection(
|
||||
summaryTextarea,
|
||||
transactionTextarea,
|
||||
decodedEventsTextarea,
|
||||
poolsTextarea,
|
||||
pairsTextarea,
|
||||
launchAttributionsTextarea,
|
||||
poolOriginsTextarea,
|
||||
walletsTextarea,
|
||||
tradeEventsTextarea,
|
||||
pairMetricsTextarea,
|
||||
pairCandlesTextarea,
|
||||
pairAnalyticSignalsTextarea,
|
||||
);
|
||||
signatureInput.value = "";
|
||||
customTimeframeInput.value = "";
|
||||
tokenMintInput.value = "";
|
||||
pairIdInput.value = "";
|
||||
poolAddressInput.value = "";
|
||||
appendLogLine(logTextarea, "[ui] inspection state cleared");
|
||||
});
|
||||
|
||||
clearLogButton.addEventListener("click", () => {
|
||||
logTextarea.value = "";
|
||||
});
|
||||
|
||||
inspectButton.addEventListener("click", async () => {
|
||||
const signature = signatureInput.value.trim();
|
||||
if (signature === "") {
|
||||
appendLogLine(logTextarea, "[ui] signature is required");
|
||||
return;
|
||||
}
|
||||
|
||||
let customTimeframeSeconds: number | null = null;
|
||||
const customTimeframeText = customTimeframeInput.value.trim();
|
||||
if (customTimeframeText !== "") {
|
||||
const parsed = Number.parseInt(customTimeframeText, 10);
|
||||
if (Number.isNaN(parsed) || parsed <= 0) {
|
||||
appendLogLine(logTextarea, `[ui] invalid custom timeframe '${customTimeframeText}'`);
|
||||
return;
|
||||
}
|
||||
customTimeframeSeconds = parsed;
|
||||
}
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] inspecting signature '${signature}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
|
||||
);
|
||||
|
||||
const request: DemoPipelineInspectRequest = {
|
||||
signature,
|
||||
customTimeframeSeconds,
|
||||
};
|
||||
|
||||
try {
|
||||
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_signature", { request });
|
||||
|
||||
summaryTextarea.value = payload.summaryJson;
|
||||
transactionTextarea.value = payload.transactionJson;
|
||||
decodedEventsTextarea.value = payload.decodedEventsJson;
|
||||
poolsTextarea.value = payload.poolsJson;
|
||||
pairsTextarea.value = payload.pairsJson;
|
||||
launchAttributionsTextarea.value = payload.launchAttributionsJson;
|
||||
poolOriginsTextarea.value = payload.poolOriginsJson;
|
||||
walletsTextarea.value = payload.walletsJson;
|
||||
tradeEventsTextarea.value = payload.tradeEventsJson;
|
||||
pairMetricsTextarea.value = payload.pairMetricsJson;
|
||||
pairCandlesTextarea.value = payload.pairCandlesJson;
|
||||
pairAnalyticSignalsTextarea.value = payload.pairAnalyticSignalsJson;
|
||||
|
||||
appendLogLine(logTextarea, `[ui] inspection completed for '${payload.signature}'`);
|
||||
} catch (error) {
|
||||
appendLogLine(logTextarea, `[ui] inspect error: ${String(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
inspectTokenButton.addEventListener("click", async () => {
|
||||
const tokenMint = tokenMintInput.value.trim();
|
||||
if (tokenMint === "") {
|
||||
appendLogLine(logTextarea, "[ui] token mint is required");
|
||||
return;
|
||||
}
|
||||
|
||||
let customTimeframeSeconds: number | null = null;
|
||||
const customTimeframeText = customTimeframeInput.value.trim();
|
||||
if (customTimeframeText !== "") {
|
||||
const parsed = Number.parseInt(customTimeframeText, 10);
|
||||
if (Number.isNaN(parsed) || parsed <= 0) {
|
||||
appendLogLine(logTextarea, `[ui] invalid custom timeframe '${customTimeframeText}'`);
|
||||
return;
|
||||
}
|
||||
customTimeframeSeconds = parsed;
|
||||
}
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] inspecting token mint '${tokenMint}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
|
||||
);
|
||||
|
||||
const request: DemoPipelineInspectTokenRequest = {
|
||||
tokenMint,
|
||||
customTimeframeSeconds,
|
||||
};
|
||||
|
||||
try {
|
||||
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_token_mint", { request });
|
||||
|
||||
summaryTextarea.value = payload.summaryJson;
|
||||
transactionTextarea.value = payload.transactionJson;
|
||||
decodedEventsTextarea.value = payload.decodedEventsJson;
|
||||
poolsTextarea.value = payload.poolsJson;
|
||||
pairsTextarea.value = payload.pairsJson;
|
||||
launchAttributionsTextarea.value = payload.launchAttributionsJson;
|
||||
poolOriginsTextarea.value = payload.poolOriginsJson;
|
||||
walletsTextarea.value = payload.walletsJson;
|
||||
tradeEventsTextarea.value = payload.tradeEventsJson;
|
||||
pairMetricsTextarea.value = payload.pairMetricsJson;
|
||||
pairCandlesTextarea.value = payload.pairCandlesJson;
|
||||
pairAnalyticSignalsTextarea.value = payload.pairAnalyticSignalsJson;
|
||||
|
||||
appendLogLine(logTextarea, `[ui] token inspection completed for '${payload.signature}'`);
|
||||
} catch (error) {
|
||||
appendLogLine(logTextarea, `[ui] token inspect error: ${String(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
inspectPairButton.addEventListener("click", async () => {
|
||||
const pairIdText = pairIdInput.value.trim();
|
||||
if (pairIdText === "") {
|
||||
appendLogLine(logTextarea, "[ui] pair id is required");
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedPairId = Number.parseInt(pairIdText, 10);
|
||||
if (Number.isNaN(parsedPairId) || parsedPairId <= 0) {
|
||||
appendLogLine(logTextarea, `[ui] invalid pair id '${pairIdText}'`);
|
||||
return;
|
||||
}
|
||||
|
||||
const customTimeframeSeconds = readCustomTimeframeSeconds(customTimeframeInput, logTextarea);
|
||||
if (customTimeframeSeconds === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] inspecting pair id '${parsedPairId}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
|
||||
);
|
||||
|
||||
const request: DemoPipelineInspectPairRequest = {
|
||||
pairId: parsedPairId,
|
||||
customTimeframeSeconds,
|
||||
};
|
||||
|
||||
try {
|
||||
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_pair_id", { request });
|
||||
|
||||
summaryTextarea.value = payload.summaryJson;
|
||||
transactionTextarea.value = payload.transactionJson;
|
||||
decodedEventsTextarea.value = payload.decodedEventsJson;
|
||||
poolsTextarea.value = payload.poolsJson;
|
||||
pairsTextarea.value = payload.pairsJson;
|
||||
launchAttributionsTextarea.value = payload.launchAttributionsJson;
|
||||
poolOriginsTextarea.value = payload.poolOriginsJson;
|
||||
walletsTextarea.value = payload.walletsJson;
|
||||
tradeEventsTextarea.value = payload.tradeEventsJson;
|
||||
pairMetricsTextarea.value = payload.pairMetricsJson;
|
||||
pairCandlesTextarea.value = payload.pairCandlesJson;
|
||||
pairAnalyticSignalsTextarea.value = payload.pairAnalyticSignalsJson;
|
||||
|
||||
appendLogLine(logTextarea, `[ui] pair inspection completed for '${payload.signature}'`);
|
||||
} catch (error) {
|
||||
appendLogLine(logTextarea, `[ui] pair inspect error: ${String(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
inspectPoolButton.addEventListener("click", async () => {
|
||||
const poolAddress = poolAddressInput.value.trim();
|
||||
if (poolAddress === "") {
|
||||
appendLogLine(logTextarea, "[ui] pool address is required");
|
||||
return;
|
||||
}
|
||||
|
||||
const customTimeframeSeconds = readCustomTimeframeSeconds(customTimeframeInput, logTextarea);
|
||||
if (customTimeframeSeconds === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] inspecting pool '${poolAddress}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
|
||||
);
|
||||
|
||||
const request: DemoPipelineInspectPoolRequest = {
|
||||
poolAddress,
|
||||
customTimeframeSeconds,
|
||||
};
|
||||
|
||||
try {
|
||||
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_pool_address", { request });
|
||||
|
||||
summaryTextarea.value = payload.summaryJson;
|
||||
transactionTextarea.value = payload.transactionJson;
|
||||
decodedEventsTextarea.value = payload.decodedEventsJson;
|
||||
poolsTextarea.value = payload.poolsJson;
|
||||
pairsTextarea.value = payload.pairsJson;
|
||||
launchAttributionsTextarea.value = payload.launchAttributionsJson;
|
||||
poolOriginsTextarea.value = payload.poolOriginsJson;
|
||||
walletsTextarea.value = payload.walletsJson;
|
||||
tradeEventsTextarea.value = payload.tradeEventsJson;
|
||||
pairMetricsTextarea.value = payload.pairMetricsJson;
|
||||
pairCandlesTextarea.value = payload.pairCandlesJson;
|
||||
pairAnalyticSignalsTextarea.value = payload.pairAnalyticSignalsJson;
|
||||
|
||||
appendLogLine(logTextarea, `[ui] pool inspection completed for '${payload.signature}'`);
|
||||
} catch (error) {
|
||||
appendLogLine(logTextarea, `[ui] pool inspect error: ${String(error)}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -31,8 +31,19 @@ async function openDemoWsManagerWindow(): Promise<void> {
|
||||
console.error("open_demo_ws_manager_window failed:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function openDemoPipelineWindow(): Promise<void> {
|
||||
try {
|
||||
await invoke("open_demo_pipeline_window");
|
||||
} catch (error) {
|
||||
console.error("open_demo_pipeline_window failed:", error);
|
||||
}
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
void takeoverConsole();
|
||||
|
||||
debug("main window loaded");
|
||||
|
||||
const sidebarToggle = document.querySelector<HTMLButtonElement>('#sidebarToggle');
|
||||
if (sidebarToggle) {
|
||||
// restaurer l’état depuis localStorage
|
||||
@@ -66,14 +77,16 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
// conserve une URL relative (path + query)
|
||||
a.setAttribute("href", url.pathname + "?" + url.searchParams.toString());
|
||||
});
|
||||
|
||||
|
||||
const openDemoWsButton = document.querySelector<HTMLButtonElement>("#openDemoWsButton");
|
||||
const openDemoWsButtonSecondary = document.querySelector<HTMLButtonElement>("#openDemoWsButtonSecondary");
|
||||
|
||||
|
||||
const openDemoHttpButton = document.querySelector<HTMLButtonElement>("#openDemoHttpButton");
|
||||
const openDemoHttpButtonSecondary = document.querySelector<HTMLButtonElement>("#openDemoHttpButtonSecondary");
|
||||
const openDemoWsManagerButton = document.querySelector<HTMLButtonElement>("#openDemoWsManagerButton");
|
||||
const openDemoWsManagerButtonSecondary = document.querySelector<HTMLButtonElement>("#openDemoWsManagerButtonSecondary");
|
||||
const openDemoPipelineButton = document.querySelector<HTMLButtonElement>("#openDemoPipelineButton");
|
||||
const openDemoPipelineButtonSecondary = document.querySelector<HTMLButtonElement>("#openDemoPipelineButtonSecondary");
|
||||
|
||||
if (openDemoWsButton) {
|
||||
openDemoWsButton.addEventListener("click", () => {
|
||||
@@ -86,7 +99,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
void openDemoWsWindow();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (openDemoHttpButton) {
|
||||
openDemoHttpButton.addEventListener("click", () => {
|
||||
void openDemoHttpWindow();
|
||||
@@ -110,7 +123,17 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
void openDemoWsManagerWindow();
|
||||
});
|
||||
}
|
||||
|
||||
debug("window loaded");
|
||||
|
||||
if (openDemoPipelineButton) {
|
||||
openDemoPipelineButton.addEventListener("click", () => {
|
||||
void openDemoPipelineWindow();
|
||||
});
|
||||
}
|
||||
|
||||
if (openDemoPipelineButtonSecondary) {
|
||||
openDemoPipelineButtonSecondary.addEventListener("click", () => {
|
||||
void openDemoPipelineWindow();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user