This commit is contained in:
2026-05-01 12:01:13 +02:00
parent c542aa9d32
commit 60db521a88
29 changed files with 639 additions and 155 deletions

View File

@@ -5,45 +5,17 @@ import "simplebar";
import ResizeObserver from "resize-observer-polyfill";
import { invoke } from "@tauri-apps/api/core";
import { debug, takeoverConsole } from "@fltsci/tauri-plugin-tracing";
import { KbDemoPipelineInspectRequest } from './bindings/KbDemoPipelineInspectRequest.ts';
import { KbDemoPipelineInspectPayload } from './bindings/KbDemoPipelineInspectPayload.ts';
import { KbDemoPipelineInspectTokenRequest } from './bindings/KbDemoPipelineInspectTokenRequest.ts';
import { KbDemoPipelineInspectPairRequest } from './bindings/KbDemoPipelineInspectPairRequest.ts';
import { KbDemoPipelineInspectPoolRequest } from './bindings/KbDemoPipelineInspectPoolRequest.ts';
import { KbDemoPipelineBackfillTokenRequest } from './bindings/KbDemoPipelineBackfillTokenRequest.ts';
import { KbDemoPipelineBackfillTokenPayload } from './bindings/KbDemoPipelineBackfillTokenPayload.ts';
(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();
@@ -58,6 +30,7 @@ function appendLogLine(textarea: HTMLTextAreaElement, line: string): void {
}
function clearInspection(
backfillTextarea: HTMLTextAreaElement,
summaryTextarea: HTMLTextAreaElement,
transactionTextarea: HTMLTextAreaElement,
decodedEventsTextarea: HTMLTextAreaElement,
@@ -71,6 +44,7 @@ function clearInspection(
pairCandlesTextarea: HTMLTextAreaElement,
pairAnalyticSignalsTextarea: HTMLTextAreaElement,
): void {
backfillTextarea.value = "";
summaryTextarea.value = "";
transactionTextarea.value = "";
decodedEventsTextarea.value = "";
@@ -88,7 +62,7 @@ function clearInspection(
function readCustomTimeframeSeconds(
input: HTMLInputElement,
logTextarea: HTMLTextAreaElement,
): number | null | undefined {
): bigint | null | undefined {
const customTimeframeText = input.value.trim();
if (customTimeframeText === "") {
return null;
@@ -100,6 +74,26 @@ function readCustomTimeframeSeconds(
return undefined;
}
return BigInt(parsed);
}
function readPositiveIntegerInput(
input: HTMLInputElement,
logTextarea: HTMLTextAreaElement,
label: string,
): number | undefined {
const text = input.value.trim();
if (text === "") {
appendLogLine(logTextarea, `[ui] ${label} is required`);
return undefined;
}
const parsed = Number.parseInt(text, 10);
if (Number.isNaN(parsed) || parsed <= 0) {
appendLogLine(logTextarea, `[ui] invalid ${label} '${text}'`);
return undefined;
}
return parsed;
}
@@ -166,8 +160,21 @@ document.addEventListener("DOMContentLoaded", async () => {
const inspectPairButton = document.querySelector<HTMLButtonElement>("#demoPipelineInspectPairButton");
const poolAddressInput = document.querySelector<HTMLInputElement>("#demoPipelinePoolAddressInput");
const inspectPoolButton = document.querySelector<HTMLButtonElement>("#demoPipelineInspectPoolButton");
const backfillTokenMintInput = document.querySelector<HTMLInputElement>("#demoPipelineBackfillTokenMintInput");
const backfillHttpRoleInput = document.querySelector<HTMLInputElement>("#demoPipelineBackfillHttpRoleInput");
const backfillMintLimitInput = document.querySelector<HTMLInputElement>("#demoPipelineBackfillMintLimitInput");
const backfillPoolLimitInput = document.querySelector<HTMLInputElement>("#demoPipelineBackfillPoolLimitInput");
const backfillTokenButton = document.querySelector<HTMLButtonElement>("#demoPipelineBackfillTokenButton");
const backfillTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipelineBackfillTextarea");
if (
!backfillTokenMintInput ||
!backfillHttpRoleInput ||
!backfillMintLimitInput ||
!backfillPoolLimitInput ||
!backfillTokenButton ||
!backfillTextarea ||
!pairIdInput ||
!inspectPairButton ||
!poolAddressInput ||
@@ -199,6 +206,7 @@ document.addEventListener("DOMContentLoaded", async () => {
clearButton.addEventListener("click", () => {
clearInspection(
backfillTextarea,
summaryTextarea,
transactionTextarea,
decodedEventsTextarea,
@@ -212,6 +220,10 @@ document.addEventListener("DOMContentLoaded", async () => {
pairCandlesTextarea,
pairAnalyticSignalsTextarea,
);
backfillTokenMintInput.value = "";
backfillHttpRoleInput.value = "history_backfill";
backfillMintLimitInput.value = "50";
backfillPoolLimitInput.value = "50";
signatureInput.value = "";
customTimeframeInput.value = "";
tokenMintInput.value = "";
@@ -231,7 +243,7 @@ document.addEventListener("DOMContentLoaded", async () => {
return;
}
let customTimeframeSeconds: number | null = null;
let customTimeframeSeconds: bigint | null = null;
const customTimeframeText = customTimeframeInput.value.trim();
if (customTimeframeText !== "") {
const parsed = Number.parseInt(customTimeframeText, 10);
@@ -239,7 +251,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(logTextarea, `[ui] invalid custom timeframe '${customTimeframeText}'`);
return;
}
customTimeframeSeconds = parsed;
customTimeframeSeconds = BigInt(parsed);
}
appendLogLine(
@@ -247,13 +259,13 @@ document.addEventListener("DOMContentLoaded", async () => {
`[ui] inspecting signature '${signature}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
);
const request: DemoPipelineInspectRequest = {
const request: KbDemoPipelineInspectRequest = {
signature,
customTimeframeSeconds,
};
try {
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_signature", { request });
const payload = await invoke<KbDemoPipelineInspectPayload>("demo_pipeline_inspect_signature", { request });
summaryTextarea.value = payload.summaryJson;
transactionTextarea.value = payload.transactionJson;
@@ -281,7 +293,7 @@ document.addEventListener("DOMContentLoaded", async () => {
return;
}
let customTimeframeSeconds: number | null = null;
let customTimeframeSeconds: bigint | null = null;
const customTimeframeText = customTimeframeInput.value.trim();
if (customTimeframeText !== "") {
const parsed = Number.parseInt(customTimeframeText, 10);
@@ -289,7 +301,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(logTextarea, `[ui] invalid custom timeframe '${customTimeframeText}'`);
return;
}
customTimeframeSeconds = parsed;
customTimeframeSeconds = BigInt(parsed);
}
appendLogLine(
@@ -297,13 +309,13 @@ document.addEventListener("DOMContentLoaded", async () => {
`[ui] inspecting token mint '${tokenMint}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
);
const request: DemoPipelineInspectTokenRequest = {
const request: KbDemoPipelineInspectTokenRequest = {
tokenMint,
customTimeframeSeconds,
};
try {
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_token_mint", { request });
const payload = await invoke<KbDemoPipelineInspectPayload>("demo_pipeline_inspect_token_mint", { request });
summaryTextarea.value = payload.summaryJson;
transactionTextarea.value = payload.transactionJson;
@@ -347,13 +359,13 @@ document.addEventListener("DOMContentLoaded", async () => {
`[ui] inspecting pair id '${parsedPairId}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
);
const request: DemoPipelineInspectPairRequest = {
pairId: parsedPairId,
const request: KbDemoPipelineInspectPairRequest = {
pairId: BigInt(parsedPairId),
customTimeframeSeconds,
};
try {
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_pair_id", { request });
const payload = await invoke<KbDemoPipelineInspectPayload>("demo_pipeline_inspect_pair_id", { request });
summaryTextarea.value = payload.summaryJson;
transactionTextarea.value = payload.transactionJson;
@@ -391,13 +403,13 @@ document.addEventListener("DOMContentLoaded", async () => {
`[ui] inspecting pool '${poolAddress}'${customTimeframeSeconds === null ? "" : ` with custom timeframe ${customTimeframeSeconds}s`}`,
);
const request: DemoPipelineInspectPoolRequest = {
const request: KbDemoPipelineInspectPoolRequest = {
poolAddress,
customTimeframeSeconds,
};
try {
const payload = await invoke<DemoPipelineInspectPayload>("demo_pipeline_inspect_pool_address", { request });
const payload = await invoke<KbDemoPipelineInspectPayload>("demo_pipeline_inspect_pool_address", { request });
summaryTextarea.value = payload.summaryJson;
transactionTextarea.value = payload.transactionJson;
@@ -417,4 +429,103 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(logTextarea, `[ui] pool inspect error: ${String(error)}`);
}
});
backfillTokenButton.addEventListener("click", async () => {
const tokenMint = backfillTokenMintInput.value.trim();
if (tokenMint === "") {
appendLogLine(logTextarea, "[ui] backfill token mint is required");
return;
}
const mintSignatureLimit = readPositiveIntegerInput(
backfillMintLimitInput,
logTextarea,
"mintSignatureLimit",
);
if (mintSignatureLimit === undefined) {
return;
}
const poolSignatureLimit = readPositiveIntegerInput(
backfillPoolLimitInput,
logTextarea,
"poolSignatureLimit",
);
if (poolSignatureLimit === undefined) {
return;
}
const httpRoleText = backfillHttpRoleInput.value.trim();
const httpRole = httpRoleText === "" ? null : httpRoleText;
appendLogLine(
logTextarea,
`[ui] launching token backfill for '${tokenMint}' with role '${httpRole ?? "history_backfill"}' (mint=${mintSignatureLimit}, pool=${poolSignatureLimit})`,
);
const request: KbDemoPipelineBackfillTokenRequest = {
tokenMint,
httpRole,
mintSignatureLimit,
poolSignatureLimit,
};
try {
const payload = await invoke<KbDemoPipelineBackfillTokenPayload>(
"demo_pipeline_backfill_token_mint",
{ request },
);
backfillTextarea.value = payload.backfillJson;
appendLogLine(
logTextarea,
`[ui] token backfill completed for '${payload.tokenMint}' with role '${payload.httpRole}'`,
);
if (!payload.tokenPersistedAfterBackfill) {
appendLogLine(
logTextarea,
`[ui] backfill completed but token '${payload.tokenMint}' is still absent from persisted token objects; automatic token inspection skipped`,
);
return;
}
const inspectRequest: KbDemoPipelineInspectTokenRequest = {
tokenMint: payload.tokenMint,
customTimeframeSeconds: null,
};
try {
const inspectPayload = await invoke<KbDemoPipelineInspectPayload>(
"demo_pipeline_inspect_token_mint",
{ request: inspectRequest },
);
summaryTextarea.value = inspectPayload.summaryJson;
transactionTextarea.value = inspectPayload.transactionJson;
decodedEventsTextarea.value = inspectPayload.decodedEventsJson;
poolsTextarea.value = inspectPayload.poolsJson;
pairsTextarea.value = inspectPayload.pairsJson;
launchAttributionsTextarea.value = inspectPayload.launchAttributionsJson;
poolOriginsTextarea.value = inspectPayload.poolOriginsJson;
walletsTextarea.value = inspectPayload.walletsJson;
tradeEventsTextarea.value = inspectPayload.tradeEventsJson;
pairMetricsTextarea.value = inspectPayload.pairMetricsJson;
pairCandlesTextarea.value = inspectPayload.pairCandlesJson;
pairAnalyticSignalsTextarea.value = inspectPayload.pairAnalyticSignalsJson;
appendLogLine(
logTextarea,
`[ui] token inspection refreshed after backfill for '${payload.tokenMint}'`,
);
} catch (error) {
appendLogLine(
logTextarea,
`[ui] backfill completed but automatic token inspection failed for '${payload.tokenMint}': ${String(error)}`,
);
}
} catch (error) {
appendLogLine(logTextarea, `[ui] token backfill error: ${String(error)}`);
}
});
});