// file: kb_demo_app/frontend/ts/demo3old.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"; import type { Demo3oldLocalDexCorpusSearchRequest } from "./bindings/Demo3oldLocalDexCorpusSearchRequest.ts"; import type { Demo3oldLocalDexCorpusSearchPayload } from "./bindings/Demo3oldLocalDexCorpusSearchPayload.ts"; import type { Demo3oldLocalDexCorpusSearchSummary } from "./bindings/Demo3oldLocalDexCorpusSearchSummary.ts"; import type { Demo3oldLocalDexCorpusTransactionSample } from "./bindings/Demo3oldLocalDexCorpusTransactionSample.ts"; import type { Demo3oldLocalDexCorpusPoolPairSample } from "./bindings/Demo3oldLocalDexCorpusPoolPairSample.ts"; import type { Demo3oldLocalDexCorpusDecodedEventSample } from "./bindings/Demo3oldLocalDexCorpusDecodedEventSample.ts"; (window as Window & typeof globalThis & { bootstrap?: typeof bootstrap }).bootstrap = bootstrap; (window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver; interface Demo3oldPreset { label: string; dexCode: string; programId: string; description: string; } const presets: Demo3oldPreset[] = [ { label: "PumpSwap", dexCode: "pump_swap", programId: "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", description: "DEX effectif PumpSwap.", }, { label: "Raydium CPMM", dexCode: "raydium_cpmm", programId: "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", description: "Raydium CPMM, swap AMM moderne.", }, { label: "Raydium CLMM", dexCode: "raydium_clmm", programId: "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK", description: "Raydium CLMM, actuellement observé dans le corpus local.", }, { label: "Raydium AMM v4", dexCode: "raydium_amm_v4", programId: "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", description: "Raydium AMM v4 legacy. À rechercher par corpus avant décodage swap.", }, { label: "Raydium Stable Swap", dexCode: "raydium_stable_swap", programId: "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h", description: "Stable Swap Raydium à vérifier par transactions locales.", }, { label: "Raydium Router", dexCode: "raydium_router", programId: "routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS", description: "Router Raydium. Ne doit pas être promu comme DEX direct sans preuve.", }, { label: "Meteora DLMM", dexCode: "meteora_dlmm", programId: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo", description: "Meteora DLMM.", }, { label: "Meteora DAMM v1", dexCode: "meteora_damm_v1", programId: "Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB", description: "Meteora DAMM v1, swaps non actionnables sans montants exploitables.", }, { label: "Meteora DAMM v2", dexCode: "meteora_damm_v2", programId: "cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG", description: "Meteora DAMM v2.", }, { label: "Meteora DBC", dexCode: "meteora_dbc", programId: "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN", description: "Meteora DBC, bonding curve / DEX effectif partiel.", }, { label: "Orca Whirlpools", dexCode: "orca_whirlpools", programId: "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc", description: "Orca Whirlpools CLMM.", }, { label: "FluxBeam", dexCode: "fluxbeam", programId: "FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X", description: "FluxBeam AMM à consolider par corpus.", }, { label: "DexLab", dexCode: "dexlab", programId: "DSwpgjMvXhtGn6BsbqmacdBZyfLj6jSWf3HJpdJtmg6N", description: "DexLab Swap/Pool à consolider par corpus.", }, { label: "metaDAO", dexCode: "metadao", programId: "", description: "DEX à vérifier. Aucun program id ne doit être inventé.", }, { label: "Printr", dexCode: "printr", programId: "", description: "DEX à vérifier. Aucun program id ne doit être inventé.", }, ]; let lastResultJson = ""; function byId(id: string): T { const element = document.getElementById(id); if (element === null) { throw new Error(`missing element #${id}`); } return element as T; } function valueOrNull(value: string): string | null { const trimmed = value.trim(); if (trimmed === "") { return null; } return trimmed; } function numberValueOrNull(value: string): number | null { const trimmed = value.trim(); if (trimmed === "") { return null; } const parsed = Number.parseInt(trimmed, 10); if (!Number.isFinite(parsed)) { return null; } return parsed; } function displayNullable(value: string | number | null): string { if (value === null) { return "-"; } return String(value); } function boolBadge(value: boolean): string { if (value) { return 'yes'; } return 'no'; } function escapeHtml(value: string): string { return value .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function shortText(value: string | null, maxLength: number): string { if (value === null) { return "-"; } if (value.length <= maxLength) { return value; } return `${value.slice(0, maxLength)}…`; } 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}`); textarea.value = lines.slice(-400).join("\n"); textarea.scrollTop = textarea.scrollHeight; } function setStatus(statusBadge: HTMLElement, label: string, cssClass: string): void { statusBadge.className = `badge ${cssClass}`; statusBadge.textContent = label; } function readRequest(): Demo3oldLocalDexCorpusSearchRequest { const limitInput = byId("demo3oldLimitInput"); const parsedLimit = Number.parseInt(limitInput.value, 10); const limit = Number.isFinite(parsedLimit) && parsedLimit > 0 ? parsedLimit : 50; return { dexCode: valueOrNull(byId("demo3oldDexCodeInput").value), programId: valueOrNull(byId("demo3oldProgramIdInput").value), pairId: numberValueOrNull(byId("demo3oldPairIdInput").value), poolAddress: valueOrNull(byId("demo3oldPoolAddressInput").value), tokenMint: valueOrNull(byId("demo3oldTokenMintInput").value), signature: valueOrNull(byId("demo3oldSignatureInput").value), limit, }; } function populatePresetSelect(select: HTMLSelectElement): void { select.innerHTML = ''; presets.forEach((preset, index) => { const option = document.createElement("option"); option.value = String(index); option.textContent = preset.label; select.appendChild(option); }); } function applyPreset(indexText: string): void { if (indexText === "") { return; } const index = Number.parseInt(indexText, 10); if (!Number.isFinite(index) || index < 0 || index >= presets.length) { return; } const preset = presets[index]; byId("demo3oldDexCodeInput").value = preset.dexCode; byId("demo3oldProgramIdInput").value = preset.programId; byId("demo3oldPresetHelp").textContent = preset.description; } function clearFilters(): void { byId("demo3oldDexCodeInput").value = ""; byId("demo3oldProgramIdInput").value = ""; byId("demo3oldPairIdInput").value = ""; byId("demo3oldPoolAddressInput").value = ""; byId("demo3oldTokenMintInput").value = ""; byId("demo3oldSignatureInput").value = ""; byId("demo3oldPresetSelect").value = ""; byId("demo3oldPresetHelp").textContent = "Choisis un preset ou saisis les filtres manuellement."; } function renderSummary(summary: Demo3oldLocalDexCorpusSearchSummary): void { byId("demo3oldSummaryTransactionCount").textContent = String(summary.transactionCount); byId("demo3oldSummaryInstructionCount").textContent = String(summary.instructionCount); byId("demo3oldSummaryDecodedEventCount").textContent = String(summary.decodedEventCount); byId("demo3oldSummaryPoolCount").textContent = String(summary.poolCount); byId("demo3oldSummaryPairCount").textContent = String(summary.pairCount); byId("demo3oldSummaryTradeEventCount").textContent = String(summary.tradeEventCount); byId("demo3oldSummaryCandleCount").textContent = String(summary.pairCandleCount); byId("demo3oldSummaryProtocolCandidateCount").textContent = String(summary.protocolCandidateCount); } function renderTransactionSamples(samples: Demo3oldLocalDexCorpusTransactionSample[]): void { const tbody = byId("demo3oldTransactionTableBody"); tbody.innerHTML = ""; if (samples.length === 0) { tbody.innerHTML = 'No transaction sample.'; return; } samples.forEach((sample) => { const tr = document.createElement("tr"); tr.innerHTML = ` ${escapeHtml(shortText(sample.signature, 18))} ${displayNullable(sample.slot)} ${boolBadge(sample.failed)} ${sample.instructionCount} ${sample.decodedEventCount} ${sample.tradeEventCount} ${escapeHtml(shortText(sample.programIdsCsv, 44))} ${sample.transactionId} `; tbody.appendChild(tr); }); } function renderPoolPairSamples(samples: Demo3oldLocalDexCorpusPoolPairSample[]): void { const tbody = byId("demo3oldPoolPairTableBody"); tbody.innerHTML = ""; if (samples.length === 0) { tbody.innerHTML = 'No pool/pair sample.'; return; } samples.forEach((sample) => { const baseLabel = `${displayNullable(sample.baseSymbol)} / ${shortText(sample.baseMint, 12)}`; const quoteLabel = `${displayNullable(sample.quoteSymbol)} / ${shortText(sample.quoteMint, 12)}`; const tr = document.createElement("tr"); tr.innerHTML = ` ${displayNullable(sample.dexCode)} ${escapeHtml(shortText(sample.poolAddress, 16))} ${displayNullable(sample.pairId)} ${escapeHtml(displayNullable(sample.pairSymbol))} ${escapeHtml(baseLabel)} ${escapeHtml(quoteLabel)} ${sample.decodedEventCount} ${sample.tradeEventCount} ${sample.pairCandleCount} `; tbody.appendChild(tr); }); } function renderDecodedEventSamples(samples: Demo3oldLocalDexCorpusDecodedEventSample[]): void { const tbody = byId("demo3oldDecodedEventTableBody"); tbody.innerHTML = ""; if (samples.length === 0) { tbody.innerHTML = 'No decoded event sample.'; return; } samples.forEach((sample) => { const tr = document.createElement("tr"); tr.innerHTML = ` ${sample.decodedEventId} ${escapeHtml(shortText(sample.signature, 16))} ${displayNullable(sample.slot)} ${escapeHtml(sample.protocolName)} ${escapeHtml(sample.eventKind)} ${escapeHtml(shortText(sample.programId, 16))} ${escapeHtml(shortText(sample.poolAccount, 16))} ${escapeHtml(displayNullable(sample.eventCategory))} ${escapeHtml(displayNullable(sample.eventActionability))} ${boolBadge(sample.tradeCandidate)} ${boolBadge(sample.candleCandidate)} `; tbody.appendChild(tr); }); } function renderResult(payload: Demo3oldLocalDexCorpusSearchPayload): void { lastResultJson = payload.resultJson; byId("demo3oldDatabaseUrlText").textContent = payload.databaseUrl; byId("demo3oldJsonTextarea").value = payload.resultJson; renderSummary(payload.result.summary); renderTransactionSamples(payload.result.transactionSamples); renderPoolPairSamples(payload.result.poolPairSamples); renderDecodedEventSamples(payload.result.decodedEventSamples); } async function runSearch(): Promise { const statusBadge = byId("demo3oldStatusBadge"); const logTextarea = byId("demo3oldLogTextarea"); setStatus(statusBadge, "Searching", "text-bg-warning"); appendLogLine(logTextarea, "launching local DEX corpus search"); try { const request = readRequest(); const payload = await invoke("demo3old_search_local_dex_corpus", { request }); renderResult(payload); appendLogLine( logTextarea, `search completed: tx='${payload.result.summary.transactionCount}', pools='${payload.result.summary.poolCount}', pairs='${payload.result.summary.pairCount}', decoded='${payload.result.summary.decodedEventCount}'`, ); setStatus(statusBadge, "Ready", "text-bg-success"); } catch (error) { appendLogLine(logTextarea, `search failed: ${String(error)}`); setStatus(statusBadge, "Error", "text-bg-danger"); } } async function copyJson(): Promise { const logTextarea = byId("demo3oldLogTextarea"); if (lastResultJson === "") { appendLogLine(logTextarea, "no JSON result to copy"); return; } try { await navigator.clipboard.writeText(lastResultJson); appendLogLine(logTextarea, "JSON result copied"); } catch (error) { appendLogLine(logTextarea, `copy failed: ${String(error)}`); } } document.addEventListener("DOMContentLoaded", () => { void takeoverConsole(); debug("demo3old window loaded"); const sidebarToggle = document.querySelector('#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('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 presetSelect = byId("demo3oldPresetSelect"); populatePresetSelect(presetSelect); presetSelect.addEventListener("change", () => { applyPreset(presetSelect.value); }); byId("demo3oldSearchButton").addEventListener("click", () => { void runSearch(); }); byId("demo3oldClearFiltersButton").addEventListener("click", () => { clearFilters(); }); byId("demo3oldCopyJsonButton").addEventListener("click", () => { void copyJson(); }); byId("demo3oldClearLogButton").addEventListener("click", () => { byId("demo3oldLogTextarea").value = ""; }); applyPreset("3"); });