0.7.25
This commit is contained in:
@@ -26,155 +26,229 @@
|
||||
<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 mb-4">
|
||||
<div class="card-body">
|
||||
<h1 class="h4 mb-3">Catalogue local</h1>
|
||||
<div class="d-flex gap-2 mb-3">
|
||||
<button id="demoPipeline2RefreshCatalogButton" type="button" class="btn btn-primary">
|
||||
Refresh catalog
|
||||
<div class="accordion" id="demoPipeline2LeftAccordion">
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h1 class="accordion-header" id="demoPipeline2CatalogHeading">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2CatalogCollapse" aria-expanded="true" aria-controls="demoPipeline2CatalogCollapse">
|
||||
Catalogue local
|
||||
</button>
|
||||
</div>
|
||||
</h1>
|
||||
<div id="demoPipeline2CatalogCollapse" class="accordion-collapse collapse show" aria-labelledby="demoPipeline2CatalogHeading" data-bs-parent="#demoPipeline2LeftAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="d-flex gap-2 mb-3">
|
||||
<button id="demoPipeline2RefreshCatalogButton" type="button" class="btn btn-primary">
|
||||
Refresh catalog
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mints</label>
|
||||
<textarea id="demoPipeline2TokensTextarea" class="form-control font-monospace" rows="8" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Mints</label>
|
||||
<textarea id="demoPipeline2TokensTextarea" class="form-control font-monospace" rows="8" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Pools</label>
|
||||
<textarea id="demoPipeline2PoolsTextarea" class="form-control font-monospace" rows="8" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Pools</label>
|
||||
<textarea id="demoPipeline2PoolsTextarea" class="form-control font-monospace" rows="8" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="form-label">Pairs</label>
|
||||
<textarea id="demoPipeline2PairsTextarea" class="form-control font-monospace" rows="8" readonly spellcheck="false"></textarea>
|
||||
<div>
|
||||
<label class="form-label">Pairs</label>
|
||||
<textarea id="demoPipeline2PairsTextarea" class="form-control font-monospace" rows="8" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3">Backfill ciblé</h2>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2HttpRoleInput" class="form-label">HTTP role</label>
|
||||
<input id="demoPipeline2HttpRoleInput" type="text" class="form-control" value="history_backfill" spellcheck="false" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2MintInput" class="form-label">Token mint</label>
|
||||
<input id="demoPipeline2MintInput" type="text" class="form-control font-monospace" spellcheck="false" placeholder="Mint SPL" />
|
||||
</div>
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-6">
|
||||
<label for="demoPipeline2MintSignatureLimitInput" class="form-label">Mint sigs</label>
|
||||
<input id="demoPipeline2MintSignatureLimitInput" type="number" min="1" step="1" class="form-control" value="20" />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label for="demoPipeline2MintPoolLimitInput" class="form-label">Pool sigs</label>
|
||||
<input id="demoPipeline2MintPoolLimitInput" type="number" min="1" step="1" class="form-control" value="20" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 mb-4">
|
||||
<button id="demoPipeline2BackfillMintButton" type="button" class="btn btn-outline-primary">
|
||||
Backfill mint
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h2 class="accordion-header" id="demoPipeline2BackfillHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2BackfillCollapse" aria-expanded="false" aria-controls="demoPipeline2BackfillCollapse">
|
||||
Backfill ciblé
|
||||
</button>
|
||||
</div>
|
||||
</h2>
|
||||
<div id="demoPipeline2BackfillCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2BackfillHeading" data-bs-parent="#demoPipeline2LeftAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2HttpRoleInput" class="form-label">HTTP role</label>
|
||||
<input id="demoPipeline2HttpRoleInput" type="text" class="form-control" value="history_backfill" spellcheck="false" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2PoolInput" class="form-label">Pool address</label>
|
||||
<input id="demoPipeline2PoolInput" type="text" class="form-control font-monospace" spellcheck="false" placeholder="Pool / pair on-chain" />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2MintInput" class="form-label">Token mint</label>
|
||||
<input id="demoPipeline2MintInput" type="text" class="form-control font-monospace" spellcheck="false" placeholder="Mint SPL" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2PoolSignatureLimitInput" class="form-label">Pool sigs</label>
|
||||
<input id="demoPipeline2PoolSignatureLimitInput" type="number" min="1" step="1" class="form-control" value="20" />
|
||||
</div>
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-6">
|
||||
<label for="demoPipeline2MintSignatureLimitInput" class="form-label">Mint sigs</label>
|
||||
<input id="demoPipeline2MintSignatureLimitInput" type="number" min="1" step="1" class="form-control" value="20" />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label for="demoPipeline2MintPoolLimitInput" class="form-label">Pool sigs</label>
|
||||
<input id="demoPipeline2MintPoolLimitInput" type="number" min="1" step="1" class="form-control" value="20" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button id="demoPipeline2BackfillPoolButton" type="button" class="btn btn-outline-primary">
|
||||
Backfill pool
|
||||
</button>
|
||||
<div class="d-flex gap-2 mb-4">
|
||||
<button id="demoPipeline2BackfillMintButton" type="button" class="btn btn-outline-primary">
|
||||
Backfill mint
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2PoolInput" class="form-label">Pool address</label>
|
||||
<input id="demoPipeline2PoolInput" type="text" class="form-control font-monospace" spellcheck="false" placeholder="Pool / pair on-chain" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2PoolSignatureLimitInput" class="form-label">Pool sigs</label>
|
||||
<input id="demoPipeline2PoolSignatureLimitInput" type="number" min="1" step="1" class="form-control" value="20" />
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button id="demoPipeline2BackfillPoolButton" type="button" class="btn btn-outline-primary">
|
||||
Backfill pool
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3">Chargement candles</h2>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2PairSelect" class="form-label">Pair</label>
|
||||
<select id="demoPipeline2PairSelect" class="form-select">
|
||||
<option value="">Aucune</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-7">
|
||||
<label for="demoPipeline2TimeframeSelect" class="form-label">Timeframe</label>
|
||||
<select id="demoPipeline2TimeframeSelect" class="form-select">
|
||||
<option value="60">1m</option>
|
||||
<option value="300">5m</option>
|
||||
<option value="900">15m</option>
|
||||
<option value="3600">1h</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<label for="demoPipeline2CustomTimeframeInput" class="form-label">Custom</label>
|
||||
<input id="demoPipeline2CustomTimeframeInput" type="number" min="1" step="1" class="form-control" placeholder="120" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-check mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="demoPipeline2PreferMaterializedInput" />
|
||||
<label class="form-check-label" for="demoPipeline2PreferMaterializedInput">
|
||||
Prefer materialized candles
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button id="demoPipeline2LoadCandlesButton" type="button" class="btn btn-primary">
|
||||
Load candles
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h2 class="accordion-header" id="demoPipeline2ReplayHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2ReplayCollapse" aria-expanded="false" aria-controls="demoPipeline2ReplayCollapse">
|
||||
Replay local
|
||||
</button>
|
||||
</h2>
|
||||
<div id="demoPipeline2ReplayCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2ReplayHeading" data-bs-parent="#demoPipeline2LeftAccordion">
|
||||
<div class="accordion-body">
|
||||
<p class="small text-body-secondary mb-3">
|
||||
Rejoue le pipeline depuis les transactions déjà stockées en base sans refaire de getTransaction.
|
||||
</p>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2ReplayLimitInput" class="form-label">Transaction limit</label>
|
||||
<input id="demoPipeline2ReplayLimitInput" type="number" min="1" step="1" class="form-control" value="10000" />
|
||||
</div>
|
||||
|
||||
<div class="form-check mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="demoPipeline2ReplayMetadataCheckbox" />
|
||||
<label class="form-check-label" for="demoPipeline2ReplayMetadataCheckbox">
|
||||
Refresh missing token metadata
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2ReplayMetadataLimitInput" class="form-label">Metadata limit</label>
|
||||
<input id="demoPipeline2ReplayMetadataLimitInput" type="number" min="1" step="1" class="form-control" value="250" />
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button id="demoPipeline2ReplayLocalPipelineButton" type="button" class="btn btn-outline-primary">
|
||||
Replay local pipeline
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item border-0 shadow-sm">
|
||||
<h2 class="accordion-header" id="demoPipeline2CandlesControlHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2CandlesControlCollapse" aria-expanded="false" aria-controls="demoPipeline2CandlesControlCollapse">
|
||||
Chargement candles
|
||||
</button>
|
||||
</h2>
|
||||
<div id="demoPipeline2CandlesControlCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2CandlesControlHeading" data-bs-parent="#demoPipeline2LeftAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="mb-3">
|
||||
<label for="demoPipeline2PairSelect" class="form-label">Pair</label>
|
||||
<select id="demoPipeline2PairSelect" class="form-select">
|
||||
<option value="">Aucune</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-7">
|
||||
<label for="demoPipeline2TimeframeSelect" class="form-label">Timeframe</label>
|
||||
<select id="demoPipeline2TimeframeSelect" class="form-select">
|
||||
<option value="60">1m</option>
|
||||
<option value="300">5m</option>
|
||||
<option value="900">15m</option>
|
||||
<option value="3600">1h</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<label for="demoPipeline2CustomTimeframeInput" class="form-label">Custom</label>
|
||||
<input id="demoPipeline2CustomTimeframeInput" type="number" min="1" step="1" class="form-control" placeholder="120" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-check mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="demoPipeline2PreferMaterializedInput" />
|
||||
<label class="form-check-label" for="demoPipeline2PreferMaterializedInput">
|
||||
Prefer materialized candles
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button id="demoPipeline2LoadCandlesButton" type="button" class="btn btn-primary">
|
||||
Load candles
|
||||
</button>
|
||||
</div>
|
||||
</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">Backfill summary</h2>
|
||||
<textarea id="demoPipeline2BackfillSummaryTextarea" class="form-control font-monospace" rows="10" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center gap-3 mb-3">
|
||||
<div>
|
||||
<h2 class="h5 mb-1">Candles / OHLCV</h2>
|
||||
<div id="demoPipeline2ChartMeta" class="small text-body-secondary">
|
||||
Aucun jeu de candles chargé.
|
||||
</div>
|
||||
<div class="accordion" id="demoPipeline2ContentAccordion">
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h2 class="accordion-header" id="demoPipeline2SummaryHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2SummaryCollapse" aria-expanded="false" aria-controls="demoPipeline2SummaryCollapse">
|
||||
Backfill / Replay summary
|
||||
</button>
|
||||
</h2>
|
||||
<div id="demoPipeline2SummaryCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2SummaryHeading" data-bs-parent="#demoPipeline2ContentAccordion">
|
||||
<div class="accordion-body">
|
||||
<textarea id="demoPipeline2BackfillSummaryTextarea" class="form-control font-monospace" rows="12" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div id="demoPipeline2Chart" class="w-100 border rounded bg-body" style="height: 560px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-sm border-0">
|
||||
<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="demoPipeline2ClearLogButton" type="button" class="btn btn-outline-secondary btn-sm">
|
||||
Clear log
|
||||
<div class="accordion-item border-0 shadow-sm mb-3">
|
||||
<h2 class="accordion-header" id="demoPipeline2ChartHeading">
|
||||
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2ChartCollapse" aria-expanded="true" aria-controls="demoPipeline2ChartCollapse">
|
||||
Candles / OHLCV
|
||||
</button>
|
||||
</h2>
|
||||
<div id="demoPipeline2ChartCollapse" class="accordion-collapse collapse show" aria-labelledby="demoPipeline2ChartHeading" data-bs-parent="#demoPipeline2ContentAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center gap-3 mb-3">
|
||||
<div id="demoPipeline2ChartMeta" class="small text-body-secondary">
|
||||
Aucun jeu de candles chargé.
|
||||
</div>
|
||||
</div>
|
||||
<div id="demoPipeline2Chart" class="w-100 border rounded bg-body" style="height: 560px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="accordion-item border-0 shadow-sm">
|
||||
<h2 class="accordion-header" id="demoPipeline2LogHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2LogCollapse" aria-expanded="false" aria-controls="demoPipeline2LogCollapse">
|
||||
Log UI
|
||||
</button>
|
||||
</h2>
|
||||
<div id="demoPipeline2LogCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2LogHeading" data-bs-parent="#demoPipeline2ContentAccordion">
|
||||
<div class="accordion-body">
|
||||
<div class="d-flex justify-content-end align-items-center mb-3">
|
||||
<button id="demoPipeline2ClearLogButton" type="button" class="btn btn-outline-secondary btn-sm">
|
||||
Clear log
|
||||
</button>
|
||||
</div>
|
||||
<textarea id="demoPipeline2LogTextarea" class="form-control font-monospace" rows="14" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="demoPipeline2LogTextarea" class="form-control font-monospace" rows="12" readonly spellcheck="false"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -38,6 +38,24 @@ interface PairCandle {
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
|
||||
interface KbLocalPipelineReplayResult {
|
||||
selectedTransactionCount: number;
|
||||
replayedTransactionCount: number;
|
||||
decodeErrorCount: number;
|
||||
detectErrorCount: number;
|
||||
tradeAggregationErrorCount: number;
|
||||
pairCandleErrorCount: number;
|
||||
analyticSignalErrorCount: number;
|
||||
decodedEventCount: number;
|
||||
detectionCount: number;
|
||||
tradeEventCount: number;
|
||||
pairCandleCount: number;
|
||||
analyticSignalCount: number;
|
||||
tokenMetadataUpdatedCount: number;
|
||||
pairSymbolUpdatedCount: number;
|
||||
globalErrorCount: number;
|
||||
}
|
||||
function appendLogLine(textarea: HTMLTextAreaElement, line: string): void {
|
||||
const now = new Date();
|
||||
const timestamp = now.toLocaleTimeString("fr-CH", { hour12: false });
|
||||
@@ -94,6 +112,25 @@ function readPositiveIntegerInput(
|
||||
return parsed;
|
||||
}
|
||||
|
||||
|
||||
function readOptionalPositiveIntegerInput(
|
||||
input: HTMLInputElement,
|
||||
logTextarea: HTMLTextAreaElement,
|
||||
label: string,
|
||||
): number | null | undefined {
|
||||
const text = input.value.trim();
|
||||
if (text === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const parsed = Number.parseInt(text, 10);
|
||||
if (Number.isNaN(parsed) || parsed <= 0) {
|
||||
appendLogLine(logTextarea, `[ui] invalid ${label} '${text}'`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
function refreshPairSelect(
|
||||
catalog: KbDemoPipeline2CatalogPayload,
|
||||
select: HTMLSelectElement,
|
||||
@@ -308,6 +345,11 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
const poolSignatureLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2PoolSignatureLimitInput");
|
||||
const backfillPoolButton = document.querySelector<HTMLButtonElement>("#demoPipeline2BackfillPoolButton");
|
||||
|
||||
const replayLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayLimitInput");
|
||||
const replayMetadataCheckbox = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataCheckbox");
|
||||
const replayMetadataLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataLimitInput");
|
||||
const replayLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ReplayLocalPipelineButton");
|
||||
|
||||
const pairSelect = document.querySelector<HTMLSelectElement>("#demoPipeline2PairSelect");
|
||||
const timeframeSelect = document.querySelector<HTMLSelectElement>("#demoPipeline2TimeframeSelect");
|
||||
const customTimeframeInput = document.querySelector<HTMLInputElement>("#demoPipeline2CustomTimeframeInput");
|
||||
@@ -334,6 +376,10 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
!poolInput ||
|
||||
!poolSignatureLimitInput ||
|
||||
!backfillPoolButton ||
|
||||
!replayLimitInput ||
|
||||
!replayMetadataCheckbox ||
|
||||
!replayMetadataLimitInput ||
|
||||
!replayLocalPipelineButton ||
|
||||
!pairSelect ||
|
||||
!timeframeSelect ||
|
||||
!customTimeframeInput ||
|
||||
@@ -497,6 +543,53 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
}
|
||||
});
|
||||
|
||||
replayLocalPipelineButton.addEventListener("click", async () => {
|
||||
const replayLimit = readOptionalPositiveIntegerInput(
|
||||
replayLimitInput,
|
||||
logTextarea,
|
||||
"replayLimit",
|
||||
);
|
||||
if (replayLimit === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tokenMetadataLimit = readOptionalPositiveIntegerInput(
|
||||
replayMetadataLimitInput,
|
||||
logTextarea,
|
||||
"tokenMetadataLimit",
|
||||
);
|
||||
if (tokenMetadataLimit === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] launching local pipeline replay limit='${replayLimit ?? "none"}' metadata='${replayMetadataCheckbox.checked ? "yes" : "no"}'`,
|
||||
);
|
||||
|
||||
try {
|
||||
const result = await invoke<KbLocalPipelineReplayResult>(
|
||||
"demo_pipeline2_replay_local_pipeline",
|
||||
{
|
||||
limit: replayLimit,
|
||||
refreshMissingTokenMetadata: replayMetadataCheckbox.checked,
|
||||
tokenMetadataLimit,
|
||||
},
|
||||
);
|
||||
|
||||
backfillSummaryTextarea.value = JSON.stringify(result, null, 2);
|
||||
|
||||
appendLogLine(
|
||||
logTextarea,
|
||||
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.tradeEventCount.toString()} trades, ${result.pairCandleCount.toString()} candles`,
|
||||
);
|
||||
|
||||
await refreshCatalog();
|
||||
} catch (error) {
|
||||
appendLogLine(logTextarea, `[ui] local pipeline replay error: ${String(error)}`);
|
||||
}
|
||||
});
|
||||
|
||||
loadCandlesButton.addEventListener("click", async () => {
|
||||
const pairIdText = pairSelect.value.trim();
|
||||
if (pairIdText === "") {
|
||||
|
||||
@@ -507,6 +507,36 @@ async fn kb_demo_pipeline2_build_catalog(
|
||||
})
|
||||
}
|
||||
|
||||
/// Replays the local pipeline from persisted raw transactions.
|
||||
#[tauri::command]
|
||||
pub(crate) async fn demo_pipeline2_replay_local_pipeline(
|
||||
state: tauri::State<'_, crate::KbAppState>,
|
||||
limit: std::option::Option<i64>,
|
||||
refresh_missing_token_metadata: bool,
|
||||
token_metadata_limit: std::option::Option<i64>,
|
||||
) -> Result<kb_lib::KbLocalPipelineReplayResult, std::string::String> {
|
||||
let config = kb_lib::KbLocalPipelineReplayConfig {
|
||||
limit,
|
||||
refresh_missing_token_metadata,
|
||||
token_metadata_limit,
|
||||
};
|
||||
let database = state.database.clone();
|
||||
let service = if refresh_missing_token_metadata {
|
||||
kb_lib::KbLocalPipelineReplayService::new_with_http_pool(
|
||||
std::sync::Arc::new(state.http_pool.clone()),
|
||||
database,
|
||||
"history_backfill".to_string(),
|
||||
)
|
||||
} else {
|
||||
kb_lib::KbLocalPipelineReplayService::new(database)
|
||||
};
|
||||
let replay_result = service.replay_local_pipeline(&config).await;
|
||||
match replay_result {
|
||||
Ok(result) => Ok(result),
|
||||
Err(error) => Err(format!("local pipeline replay failed: {}", error)),
|
||||
}
|
||||
}
|
||||
|
||||
fn kb_demo_pipeline2_normalize_http_role(
|
||||
role: std::option::Option<std::string::String>,
|
||||
) -> std::string::String {
|
||||
|
||||
@@ -150,6 +150,7 @@ pub async fn run() -> Result<(), kb_lib::KbError> {
|
||||
crate::demo_pipeline2::demo_pipeline2_backfill_token_mint,
|
||||
crate::demo_pipeline2::demo_pipeline2_backfill_pool_address,
|
||||
crate::demo_pipeline2::demo_pipeline2_get_pair_candles,
|
||||
crate::demo_pipeline2::demo_pipeline2_replay_local_pipeline,
|
||||
]);
|
||||
tauri_builder = tauri_builder.plugin(tracing_builder.build::<tauri::Wry>());
|
||||
tauri_builder = tauri_builder.setup(|app| {
|
||||
|
||||
Reference in New Issue
Block a user