This commit is contained in:
2026-05-05 20:49:45 +02:00
parent f2c227e08f
commit 348e76660c
28 changed files with 3279 additions and 210 deletions

View File

@@ -0,0 +1,34 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local decoded-event diagnostics summary for the UI.
*/
export type KbDemoPipeline2LocalDecodedEventDiagnosticSummary = {
/**
* Protocol name.
*/
protocolName: string,
/**
* Event kind.
*/
eventKind: string,
/**
* Event category.
*/
eventCategory: string | null,
/**
* Trade candidate flag.
*/
tradeCandidate: boolean | null,
/**
* Candle candidate flag.
*/
candleCandidate: boolean | null,
/**
* Event count.
*/
eventCount: number,
/**
* Linked trade-event count.
*/
tradeEventCount: number, };

View File

@@ -0,0 +1,38 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local DEX diagnostics summary for the UI.
*/
export type KbDemoPipeline2LocalDexDiagnosticSummary = {
/**
* DEX code.
*/
dexCode: string,
/**
* Pool count.
*/
poolCount: number,
/**
* Pair count.
*/
pairCount: number,
/**
* Decoded event count.
*/
decodedEventCount: number,
/**
* Decoded trade candidate count.
*/
decodedTradeCandidateCount: number,
/**
* Decoded candle candidate count.
*/
decodedCandleCandidateCount: number,
/**
* Trade event count.
*/
tradeEventCount: number,
/**
* Pair candle count.
*/
pairCandleCount: number, };

View File

@@ -0,0 +1,19 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { KbDemoPipeline2LocalPipelineDiagnosticSummary } from "./KbDemoPipeline2LocalPipelineDiagnosticSummary";
/**
* Local diagnostics payload returned to the UI.
*/
export type KbDemoPipeline2LocalDiagnosticsPayload = {
/**
* Open database URL.
*/
databaseUrl: string,
/**
* Pretty JSON diagnostics summary.
*/
summaryJson: string,
/**
* Structured diagnostics summary.
*/
summary: KbDemoPipeline2LocalPipelineDiagnosticSummary, };

View File

@@ -0,0 +1,34 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local duplicate decoded-event trade diagnostic sample for the UI.
*/
export type KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample = {
/**
* Decoded event id.
*/
decodedEventId: number,
/**
* Protocol name.
*/
protocolName: string | null,
/**
* Event kind.
*/
eventKind: string | null,
/**
* Pool account.
*/
poolAccount: string | null,
/**
* Trade event count.
*/
tradeEventCount: number,
/**
* Trade event ids.
*/
tradeEventIds: string | null,
/**
* Signatures.
*/
signatures: string | null, };

View File

@@ -0,0 +1,50 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local missing-trade-event diagnostic sample for the UI.
*/
export type KbDemoPipeline2LocalMissingTradeEventDiagnosticSample = {
/**
* Decoded event id.
*/
decodedEventId: number,
/**
* Chain transaction id.
*/
transactionId: number | null,
/**
* Transaction signature.
*/
signature: string | null,
/**
* Protocol name.
*/
protocolName: string,
/**
* Event kind.
*/
eventKind: string,
/**
* Pool account.
*/
poolAccount: string | null,
/**
* Whether the source transaction failed.
*/
transactionFailed: boolean,
/**
* Diagnostic reason explaining why no trade event was linked.
*/
reason: string,
/**
* Whether payload has an explicit base amount.
*/
hasBaseAmountPayload: boolean,
/**
* Whether payload has an explicit quote amount.
*/
hasQuoteAmountPayload: boolean,
/**
* Whether payload has an explicit price.
*/
hasPricePayload: boolean, };

View File

@@ -0,0 +1,38 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local multi-trade signature/pair diagnostic sample for the UI.
*/
export type KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample = {
/**
* Transaction signature.
*/
signature: string,
/**
* Pair id.
*/
pairId: number,
/**
* Pool address.
*/
poolAddress: string | null,
/**
* DEX code.
*/
dexCode: string | null,
/**
* Trade event count.
*/
tradeEventCount: number,
/**
* Distinct decoded event count.
*/
decodedEventCount: number,
/**
* Trade event ids.
*/
tradeEventIds: string | null,
/**
* Decoded event ids.
*/
decodedEventIds: string | null, };

View File

@@ -0,0 +1,66 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local pair diagnostics summary for the UI.
*/
export type KbDemoPipeline2LocalPairDiagnosticSummary = {
/**
* Pair id.
*/
pairId: number,
/**
* Pool address.
*/
poolAddress: string,
/**
* DEX code.
*/
dexCode: string,
/**
* Base mint.
*/
baseMint: string,
/**
* Base symbol.
*/
baseSymbol: string | null,
/**
* Quote mint.
*/
quoteMint: string,
/**
* Quote symbol.
*/
quoteSymbol: string | null,
/**
* Pair symbol.
*/
pairSymbol: string | null,
/**
* Decoded event count.
*/
decodedEventCount: number,
/**
* Decoded trade candidate count.
*/
decodedTradeCandidateCount: number,
/**
* Decoded candle candidate count.
*/
decodedCandleCandidateCount: number,
/**
* Trade event count.
*/
tradeEventCount: number,
/**
* Invalid trade event count.
*/
invalidTradeEventCount: number,
/**
* Pair candle count.
*/
pairCandleCount: number,
/**
* Last known price.
*/
lastPriceQuotePerBase: number | null, };

View File

@@ -0,0 +1,54 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Local pair gap diagnostic sample for the UI.
*/
export type KbDemoPipeline2LocalPairGapDiagnosticSample = {
/**
* Pair id.
*/
pairId: number,
/**
* Pool address.
*/
poolAddress: string,
/**
* DEX code.
*/
dexCode: string,
/**
* Base mint.
*/
baseMint: string,
/**
* Base symbol.
*/
baseSymbol: string | null,
/**
* Quote mint.
*/
quoteMint: string,
/**
* Quote symbol.
*/
quoteSymbol: string | null,
/**
* Pair symbol.
*/
pairSymbol: string | null,
/**
* Decoded event count.
*/
decodedEventCount: number,
/**
* Decoded trade candidate count.
*/
decodedTradeCandidateCount: number,
/**
* Trade event count.
*/
tradeEventCount: number,
/**
* Pair candle count.
*/
pairCandleCount: number, };

View File

@@ -0,0 +1,150 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { KbDemoPipeline2LocalDecodedEventDiagnosticSummary } from "./KbDemoPipeline2LocalDecodedEventDiagnosticSummary";
import type { KbDemoPipeline2LocalDexDiagnosticSummary } from "./KbDemoPipeline2LocalDexDiagnosticSummary";
import type { KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample } from "./KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample";
import type { KbDemoPipeline2LocalMissingTradeEventDiagnosticSample } from "./KbDemoPipeline2LocalMissingTradeEventDiagnosticSample";
import type { KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample } from "./KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample";
import type { KbDemoPipeline2LocalPairDiagnosticSummary } from "./KbDemoPipeline2LocalPairDiagnosticSummary";
import type { KbDemoPipeline2LocalPairGapDiagnosticSample } from "./KbDemoPipeline2LocalPairGapDiagnosticSample";
/**
* Local pipeline diagnostics summary for the UI.
*/
export type KbDemoPipeline2LocalPipelineDiagnosticSummary = {
/**
* Total persisted chain transactions.
*/
transactionCount: number,
/**
* Total successful chain transactions.
*/
okTransactionCount: number,
/**
* Total failed chain transactions.
*/
failedTransactionCount: number,
/**
* Total decoded DEX events.
*/
decodedEventCount: number,
/**
* Total decoded DEX trade candidates.
*/
decodedTradeCandidateCount: number,
/**
* Total decoded DEX candle candidates.
*/
decodedCandleCandidateCount: number,
/**
* Whether the local persisted pipeline has no blocking diagnostic issue.
*/
diagnosticsClean: boolean,
/**
* Number of blocking diagnostic issues.
*/
blockingIssueCount: number,
/**
* Total trade candidates without trade event, including ignored failed transactions.
*/
missingTradeEventCount: number,
/**
* Explicit alias for decoded trade candidates without linked trade event.
*/
decodedTradeCandidateWithoutTradeEventCount: number,
/**
* Trade candidates without linked trade event on successful transactions.
*/
decodedTradeCandidateWithoutTradeEventOnOkTransactionCount: number,
/**
* Trade candidates without linked trade event on failed transactions.
*/
decodedTradeCandidateWithoutTradeEventOnFailedTransactionCount: number,
/**
* Trade candidates without linked trade event and without explicit base/quote payload amounts.
* Actionable missing trade events on successful transactions.
*/
actionableMissingTradeEventCount: number,
/**
* Ignored missing trade events caused by failed transactions.
*/
ignoredFailedTransactionTradeCandidateCount: number, decodedTradeCandidateWithoutAmountPayloadCount: number,
/**
* Total persisted trade events.
*/
tradeEventCount: number,
/**
* Total invalid trade events.
*/
invalidTradeEventCount: number,
/**
* Total persisted pair candles.
*/
pairCandleCount: number,
/**
* Real duplicate trade rows grouped by decoded event id.
*/
duplicateDecodedEventTradeCount: number,
/**
* Multi-trade groups sharing the same signature and pair id.
*/
multiTradeSignaturePairCount: number,
/**
* Total duplicate candle buckets.
*/
duplicateCandleBucketCount: number,
/**
* Total known tokens.
*/
tokenCount: number,
/**
* Total tokens missing symbol or name.
*/
tokenMetadataMissingCount: number,
/**
* Total known pools.
*/
poolCount: number,
/**
* Total known pairs.
*/
pairCount: number,
/**
* Total pairs without trade.
*/
pairWithoutTradeCount: number,
/**
* Total pairs without candle.
*/
pairWithoutCandleCount: number,
/**
* Diagnostics grouped by DEX.
*/
dexSummaries: Array<KbDemoPipeline2LocalDexDiagnosticSummary>,
/**
* Diagnostics grouped by pair.
*/
pairSummaries: Array<KbDemoPipeline2LocalPairDiagnosticSummary>,
/**
* Diagnostics grouped by decoded event kind.
*/
decodedEventSummaries: Array<KbDemoPipeline2LocalDecodedEventDiagnosticSummary>,
/**
* Samples of decoded trade candidates without linked trade event.
*/
missingTradeEventSamples: Array<KbDemoPipeline2LocalMissingTradeEventDiagnosticSample>,
/**
* Samples of duplicated trade rows by decoded event id.
*/
duplicateDecodedEventTradeSamples: Array<KbDemoPipeline2LocalDuplicateDecodedEventTradeDiagnosticSample>,
/**
* Samples of multi-trade signature/pair groups.
*/
multiTradeSignaturePairSamples: Array<KbDemoPipeline2LocalMultiTradeSignaturePairDiagnosticSample>,
/**
* Samples of pairs without trade.
*/
pairWithoutTradeSamples: Array<KbDemoPipeline2LocalPairGapDiagnosticSample>,
/**
* Samples of pairs without candle.
*/
pairWithoutCandleSamples: Array<KbDemoPipeline2LocalPairGapDiagnosticSample>, };

View File

@@ -13,6 +13,7 @@ import type { KbDemoPipeline2BackfillPoolRequest } from "./bindings/KbDemoPipeli
import type { KbDemoPipeline2BackfillPayload } from "./bindings/KbDemoPipeline2BackfillPayload.ts";
import type { KbDemoPipeline2PairCandlesRequest } from "./bindings/KbDemoPipeline2PairCandlesRequest.ts";
import type { KbDemoPipeline2PairCandlesPayload } from "./bindings/KbDemoPipeline2PairCandlesPayload.ts";
import type { KbDemoPipeline2LocalDiagnosticsPayload } from "./bindings/KbDemoPipeline2LocalDiagnosticsPayload.ts";
(window as Window & typeof globalThis & { bootstrap?: typeof bootstrap }).bootstrap = bootstrap;
(window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver;
@@ -50,8 +51,8 @@ interface KbLocalPipelineReplayResult {
decodedEventCount: number;
detectionCount: number;
tradeEventCount: number;
pairCandleCount: number;
analyticSignalCount: number;
pairCandleUpsertCount: number;
analyticSignalUpsertCount: number;
tokenMetadataUpdatedCount: number;
pairSymbolUpdatedCount: number;
globalErrorCount: number;
@@ -349,6 +350,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const replayMetadataCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataCheckbox");
const replayMetadataLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataLimitInput");
const replayLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ReplayLocalPipelineButton");
const diagnoseLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2DiagnoseLocalPipelineButton");
const pairSelect = document.querySelector<HTMLSelectElement>("#demoPipeline2PairSelect");
const timeframeSelect = document.querySelector<HTMLSelectElement>("#demoPipeline2TimeframeSelect");
@@ -359,6 +361,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const backfillSummaryTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2BackfillSummaryTextarea");
const chartElement = document.querySelector<HTMLDivElement>("#demoPipeline2Chart");
const chartMeta = document.querySelector<HTMLDivElement>("#demoPipeline2ChartMeta");
const localDiagnosticsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2LocalDiagnosticsTextarea");
const clearLogButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ClearLogButton");
const logTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2LogTextarea");
@@ -380,12 +383,14 @@ document.addEventListener("DOMContentLoaded", async () => {
!replayMetadataCheckbox ||
!replayMetadataLimitInput ||
!replayLocalPipelineButton ||
!diagnoseLocalPipelineButton ||
!pairSelect ||
!timeframeSelect ||
!customTimeframeInput ||
!preferMaterializedInput ||
!loadCandlesButton ||
!backfillSummaryTextarea ||
!localDiagnosticsTextarea ||
!chartElement ||
!chartMeta ||
!clearLogButton ||
@@ -405,6 +410,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const safeChartMeta = chartMeta;
const safeLogTextarea = logTextarea;
const safeLocalDiagnosticsTextarea = localDiagnosticsTextarea;
const chart = echarts.init(safeChartElement);
setEmptyChart(chart, safeChartMeta, "Aucune candle disponible.");
@@ -581,7 +587,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(
logTextarea,
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.tradeEventCount.toString()} trades, ${result.pairCandleCount.toString()} candles`,
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.tradeEventCount.toString()} trades, ${result.pairCandleUpsertCount.toString()} candle upserts`,
);
await refreshCatalog();
@@ -590,6 +596,29 @@ document.addEventListener("DOMContentLoaded", async () => {
}
});
diagnoseLocalPipelineButton.addEventListener("click", async () => {
appendLogLine(logTextarea, "[ui] diagnosing local pipeline");
diagnoseLocalPipelineButton.disabled = true;
try {
const payload = await invoke<KbDemoPipeline2LocalDiagnosticsPayload>(
"demo_pipeline2_diagnose_local_pipeline",
);
safeLocalDiagnosticsTextarea.value = payload.summaryJson;
appendLogLine(
logTextarea,
`[ui] local pipeline diagnostics completed: ${payload.summary.decodedEventCount.toString()} decoded, ${payload.summary.tradeEventCount.toString()} trades, ${payload.summary.pairCandleCount.toString()} candles`,
);
} catch (error) {
appendLogLine(logTextarea, `[ui] local pipeline diagnostics error: ${String(error)}`);
} finally {
diagnoseLocalPipelineButton.disabled = false;
}
});
loadCandlesButton.addEventListener("click", async () => {
const pairIdText = pairSelect.value.trim();
if (pairIdText === "") {