This commit is contained in:
2026-06-05 14:53:16 +02:00
parent 27e25d5bf4
commit f81e0f3bea
66 changed files with 7655 additions and 214 deletions

View File

@@ -11,6 +11,7 @@ import type { DemoPipeline2CatalogPayload } from "./bindings/DemoPipeline2Catalo
import type { DemoPipeline2BackfillTokenRequest } from "./bindings/DemoPipeline2BackfillTokenRequest.ts";
import type { DemoPipeline2BackfillPoolRequest } from "./bindings/DemoPipeline2BackfillPoolRequest.ts";
import type { DemoPipeline2BackfillSignatureRequest } from "./bindings/DemoPipeline2BackfillSignatureRequest.ts";
import type { DemoPipeline2BackfillSignaturesBatchRequest } from "./bindings/DemoPipeline2BackfillSignaturesBatchRequest.ts";
import type { DemoPipeline2BackfillPayload } from "./bindings/DemoPipeline2BackfillPayload.ts";
import type { DemoPipeline2PairCandlesRequest } from "./bindings/DemoPipeline2PairCandlesRequest.ts";
import type { DemoPipeline2PairCandlesPayload } from "./bindings/DemoPipeline2PairCandlesPayload.ts";
@@ -75,6 +76,8 @@ interface LocalPipelineReplayResult {
tokenMetadataUpdatedCount: number;
pairSymbolUpdatedCount: number;
resetMarketMaterializationDeletedCount: number;
instructionObservationScannedCount: number;
instructionObservationUpsertedCount: number;
globalErrorCount: number;
}
function appendLogLine(textarea: HTMLTextAreaElement, line: string): void {
@@ -152,6 +155,25 @@ function readOptionalPositiveIntegerInput(
return parsed;
}
function parseSignatureBatchText(raw: string): string[] {
const signatures: string[] = [];
const seen = new Set<string>();
for (const line of raw.split(/\r?\n/)) {
const signature = line.trim();
if (signature === "") {
continue;
}
if (seen.has(signature)) {
continue;
}
seen.add(signature);
signatures.push(signature);
}
return signatures;
}
function refreshPairSelect(
catalog: DemoPipeline2CatalogPayload,
select: HTMLSelectElement,
@@ -410,12 +432,16 @@ document.addEventListener("DOMContentLoaded", async () => {
const signatureInput = document.querySelector<HTMLInputElement>("#demoPipeline2SignatureInput");
const backfillSignatureButton = document.querySelector<HTMLButtonElement>("#demoPipeline2BackfillSignatureButton");
const signatureBatchTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2SignatureBatchTextarea");
const signatureBatchContinueOnErrorCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2SignatureBatchContinueOnErrorCheckbox");
const backfillSignatureBatchButton = document.querySelector<HTMLButtonElement>("#demoPipeline2BackfillSignatureBatchButton");
const replayLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayLimitInput");
const replayMetadataCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataCheckbox");
const replayMetadataLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataLimitInput");
const replaySkipCertifiedDexDecodeCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2ReplaySkipCertifiedDexDecodeCheckbox");
const replayForceDexDecodeCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayForceDexDecodeCheckbox");
const replayDeferInstructionObservationCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayDeferInstructionObservationCheckbox");
const replayLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ReplayLocalPipelineButton");
const diagnoseLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2DiagnoseLocalPipelineButton");
const validateLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ValidateLocalPipelineButton");
@@ -462,11 +488,15 @@ document.addEventListener("DOMContentLoaded", async () => {
!backfillPoolButton ||
!signatureInput ||
!backfillSignatureButton ||
!signatureBatchTextarea ||
!signatureBatchContinueOnErrorCheckbox ||
!backfillSignatureBatchButton ||
!replayLimitInput ||
!replayMetadataCheckbox ||
!replayMetadataLimitInput ||
!replaySkipCertifiedDexDecodeCheckbox ||
!replayForceDexDecodeCheckbox ||
!replayDeferInstructionObservationCheckbox ||
!replayLocalPipelineButton ||
!diagnoseLocalPipelineButton ||
!validateLocalPipelineButton ||
@@ -685,6 +715,55 @@ document.addEventListener("DOMContentLoaded", async () => {
}
});
backfillSignatureBatchButton.addEventListener("click", async () => {
const signatures = parseSignatureBatchText(signatureBatchTextarea.value);
if (signatures.length === 0) {
appendLogLine(logTextarea, "[ui] signature batch is empty");
return;
}
const httpRoleText = httpRoleInput.value.trim();
const httpRole = httpRoleText === "" ? null : httpRoleText;
const continueOnError = signatureBatchContinueOnErrorCheckbox.checked;
appendLogLine(
logTextarea,
`[ui] launching signature batch backfill count='${signatures.length.toString()}' role='${httpRole ?? "history_backfill"}' continueOnError='${continueOnError ? "yes" : "no"}'`,
);
const request: DemoPipeline2BackfillSignaturesBatchRequest = {
signatures,
httpRole,
continueOnError,
};
backfillSignatureBatchButton.disabled = true;
backfillSignatureButton.disabled = true;
backfillMintButton.disabled = true;
backfillPoolButton.disabled = true;
try {
const payload = await invoke<DemoPipeline2BackfillPayload>(
"demo_pipeline2_backfill_signatures_batch",
{ request },
);
backfillSummaryTextarea.value = payload.summaryJson;
currentCatalog = payload.catalog;
renderCatalogTextareas(payload.catalog, tokensTextarea, poolsTextarea, pairsTextarea);
refreshPairSelect(payload.catalog, pairSelect);
appendLogLine(logTextarea, `[ui] signature batch backfill completed for '${payload.objectKey}'`);
} catch (error) {
appendLogLine(logTextarea, `[ui] signature batch backfill error: ${String(error)}`);
} finally {
backfillSignatureBatchButton.disabled = false;
backfillSignatureButton.disabled = false;
backfillMintButton.disabled = false;
backfillPoolButton.disabled = false;
}
});
replayLocalPipelineButton.addEventListener("click", async () => {
const replayLimit = readOptionalPositiveIntegerInput(
replayLimitInput,
@@ -706,7 +785,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(
logTextarea,
`[ui] launching local pipeline replay limit='${replayLimit ?? "none"}' metadata='${replayMetadataCheckbox.checked ? "yes" : "no"}' skipDexDecode='${replaySkipCertifiedDexDecodeCheckbox.checked ? "yes" : "no"}' forceDexDecode='${replayForceDexDecodeCheckbox.checked ? "yes" : "no"}'`,
`[ui] launching local pipeline replay limit='${replayLimit ?? "none"}' metadata='${replayMetadataCheckbox.checked ? "yes" : "no"}' skipDexDecode='${replaySkipCertifiedDexDecodeCheckbox.checked ? "yes" : "no"}' forceDexDecode='${replayForceDexDecodeCheckbox.checked ? "yes" : "no"}' deferInstructionObservations='${replayDeferInstructionObservationCheckbox.checked ? "yes" : "no"}'`,
);
try {
@@ -718,6 +797,7 @@ document.addEventListener("DOMContentLoaded", async () => {
tokenMetadataLimit,
skipCertifiedDexDecode: replaySkipCertifiedDexDecodeCheckbox.checked,
forceDecodeReplay: replayForceDexDecodeCheckbox.checked,
deferInstructionObservationIndexRefresh: replayDeferInstructionObservationCheckbox.checked,
},
);
@@ -725,7 +805,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(
logTextarea,
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.decodeSkippedCount.toString()} decode skipped, ${result.decodeLedgerUpsertCount.toString()} ledger upserts, ${result.decodeLedgerUnsafeCount.toString()} unsafe ledger rows, ${result.tradeEventCount.toString()} trades, ${result.liquidityEventCount.toString()} liquidity, ${result.poolLifecycleEventCount.toString()} lifecycle, ${result.pairCandleUpsertCount.toString()} candle upserts, resetDeleted='${result.resetMarketMaterializationDeletedCount.toString()}'`,
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.decodeSkippedCount.toString()} decode skipped, ${result.decodeLedgerUpsertCount.toString()} ledger upserts, ${result.decodeLedgerUnsafeCount.toString()} unsafe ledger rows, ${result.tradeEventCount.toString()} trades, ${result.liquidityEventCount.toString()} liquidity, ${result.poolLifecycleEventCount.toString()} lifecycle, ${result.pairCandleUpsertCount.toString()} candle upserts, instructionObservations='${result.instructionObservationUpsertedCount.toString()}', resetDeleted='${result.resetMarketMaterializationDeletedCount.toString()}'`,
);
await refreshCatalog();