This commit is contained in:
2026-05-12 18:53:42 +02:00
parent 4f6a4806e2
commit 75c2b6983d
22 changed files with 1452 additions and 368 deletions

View File

@@ -163,6 +163,15 @@
Analyse les données déjà persistées : transactions, decoded events, trades, candles, tokens, pools et pairs.
</p>
<div class="mb-3">
<label for="demoPipeline2ValidationProfileSelect" class="form-label">Validation profile</label>
<select id="demoPipeline2ValidationProfileSelect" class="form-select">
<option value="0.7.29_multi_dex_matrix_baseline" selected>0.7.29 — DEX matrix baseline</option>
<option value="0.7.28_multi_dex_non_regression">0.7.28 — multi-DEX non-regression</option>
<option value="0.7.27_dexes_non_regression" selected>0.7.27 — first DEXes non-regression</option>
</select>
</div>
<div class="d-flex gap-2">
<button id="demoPipeline2DiagnoseLocalPipelineButton" type="button" class="btn btn-outline-primary">
Diagnose local pipeline

View File

@@ -0,0 +1,82 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* One DEX support matrix entry for the UI.
*/
export type DemoPipeline2DexSupportMatrixEntry = {
/**
* Stable internal protocol or surface code.
*/
code: string,
/**
* Human-readable protocol or surface name.
*/
displayName: string,
/**
* Protocol family.
*/
family: string,
/**
* Protocol version or `unknown` when not verified locally.
*/
version: string,
/**
* Surface type: launch, bonding curve, AMM, CLMM, DLMM, router, aggregator or unknown.
*/
surfaceType: string,
/**
* Primary Solana program id, when verified in local constants or docs.
*/
programId: string | null,
/**
* Optional router program id, when this entry uses a distinct router.
*/
routerProgramId: string | null,
/**
* Program id confidence: known, to_verify or unknown.
*/
programIdStatus: string,
/**
* Whether this protocol has been observed in the local replay corpus.
*/
observed: boolean,
/**
* Whether the code currently contains a decoder for this protocol.
*/
decoded: boolean,
/**
* Whether decoded events are currently materialized beyond raw decoded rows.
*/
materialized: boolean,
/**
* Whether this protocol can currently produce trade candidates.
*/
tradeCandidate: boolean,
/**
* Whether this protocol can currently produce candle candidates.
*/
candleCandidate: boolean,
/**
* Whether this protocol can currently produce pair candidates.
*/
pairCandidate: boolean,
/**
* Whether this protocol can currently produce pool candidates.
*/
poolCandidate: boolean,
/**
* Operational support status.
*/
status: string,
/**
* Confidence level attached to this matrix entry.
*/
confidence: string,
/**
* Optional explicit skip reason for partial or ignored entries.
*/
skipReason: string | null,
/**
* Whether the entry should be inserted as an enabled DEX in the storage catalog.
*/
catalogEnabled: boolean, };

View File

@@ -1,4 +1,5 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { DemoPipeline2DexSupportMatrixEntry } from "./DemoPipeline2DexSupportMatrixEntry";
import type { DemoPipeline2LocalPipelineValidationIssue } from "./DemoPipeline2LocalPipelineValidationIssue";
/**
@@ -29,6 +30,14 @@ expectedDexCodes: Array<string>,
* Observed DEX codes found in diagnostics.
*/
observedDexCodes: Array<string>,
/**
* Number of entries currently exposed by the DEX support matrix.
*/
dexSupportMatrixEntryCount: number,
/**
* DEX support matrix snapshot exposed with the validation report.
*/
dexSupportMatrix: Array<DemoPipeline2DexSupportMatrixEntry>,
/**
* Issues produced by validation.
*/

View File

@@ -0,0 +1,10 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Request payload for local pipeline validation.
*/
export type DemoPipeline2LocalValidationRequest = {
/**
* Stable validation profile code to execute.
*/
profileCode: string, };

View File

@@ -14,6 +14,7 @@ import type { DemoPipeline2BackfillPayload } from "./bindings/DemoPipeline2Backf
import type { DemoPipeline2PairCandlesRequest } from "./bindings/DemoPipeline2PairCandlesRequest.ts";
import type { DemoPipeline2PairCandlesPayload } from "./bindings/DemoPipeline2PairCandlesPayload.ts";
import type { DemoPipeline2LocalDiagnosticsPayload } from "./bindings/DemoPipeline2LocalDiagnosticsPayload.ts";
import type { DemoPipeline2LocalValidationRequest } from "./bindings/DemoPipeline2LocalValidationRequest.ts";
import type { DemoPipeline2LocalValidationPayload } from "./bindings/DemoPipeline2LocalValidationPayload.ts";
import type { DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest } from "./bindings/DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest.ts";
import type { DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload } from "./bindings/DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload.ts";
@@ -356,6 +357,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const replayMetadataLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ReplayMetadataLimitInput");
const replayLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ReplayLocalPipelineButton");
const diagnoseLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2DiagnoseLocalPipelineButton");
const validationProfileSelect = document.querySelector<HTMLSelectElement>("#demoPipeline2ValidationProfileSelect");
const validateLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ValidateLocalPipelineButton");
const discriminatorProgramIdInput = document.querySelector<HTMLInputElement>("#demoPipeline2DiscriminatorProgramIdInput");
@@ -402,6 +404,7 @@ document.addEventListener("DOMContentLoaded", async () => {
!replayMetadataLimitInput ||
!replayLocalPipelineButton ||
!diagnoseLocalPipelineButton ||
!validationProfileSelect ||
!validateLocalPipelineButton ||
!discriminatorProgramIdInput ||
!discriminatorLimitInput ||
@@ -647,11 +650,16 @@ document.addEventListener("DOMContentLoaded", async () => {
});
validateLocalPipelineButton.addEventListener("click", async () => {
appendLogLine(logTextarea, "[ui] validating local pipeline with 0.7.28 profile");
const request: DemoPipeline2LocalValidationRequest = {
profileCode: validationProfileSelect.value,
};
appendLogLine(logTextarea, `[ui] validating local pipeline with ${request.profileCode} profile`);
try {
const payload = await invoke<DemoPipeline2LocalValidationPayload>(
"demo_pipeline2_validate_local_pipeline",
{ request },
);
localValidationTextarea.value = payload.validationJson;
@@ -659,7 +667,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine(
logTextarea,
`[ui] local pipeline validation completed: profile='${payload.run.validationProfileCode}' passed='${payload.run.validationPassed ? "yes" : "no"}' blocking='${payload.run.blockingIssueCount.toString()}' warnings='${payload.run.warningCount.toString()}'`,
`[ui] local pipeline validation completed: profile='${payload.run.validationProfileCode}' passed='${payload.run.validationPassed ? "yes" : "no"}' blocking='${payload.run.blockingIssueCount.toString()}' warnings='${payload.run.warningCount.toString()}' dexMatrix='${payload.run.report.dexSupportMatrixEntryCount.toString()}'`,
);
} catch (error) {
appendLogLine(logTextarea, `[ui] local pipeline validation error: ${String(error)}`);

View File

@@ -1,7 +1,7 @@
{
"name": "kb-demo-app",
"private": true,
"version": "0.7.28",
"version": "0.7.29",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -76,6 +76,18 @@ pub(crate) struct DemoPipeline2LocalDiagnosticsPayload {
pub summary: DemoPipeline2LocalPipelineDiagnosticSummary,
}
/// Request payload for local pipeline validation.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/DemoPipeline2LocalValidationRequest.ts"
)]
#[serde(rename_all = "camelCase")]
pub(crate) struct DemoPipeline2LocalValidationRequest {
/// Stable validation profile code to execute.
pub profile_code: std::string::String,
}
/// Local validation payload returned to the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
@@ -140,10 +152,63 @@ pub(crate) struct DemoPipeline2LocalPipelineValidationReport {
pub expected_dex_codes: std::vec::Vec<std::string::String>,
/// Observed DEX codes found in diagnostics.
pub observed_dex_codes: std::vec::Vec<std::string::String>,
/// Number of entries currently exposed by the DEX support matrix.
#[ts(type = "number")]
pub dex_support_matrix_entry_count: i64,
/// DEX support matrix snapshot exposed with the validation report.
pub dex_support_matrix: std::vec::Vec<DemoPipeline2DexSupportMatrixEntry>,
/// Issues produced by validation.
pub issues: std::vec::Vec<DemoPipeline2LocalPipelineValidationIssue>,
}
/// One DEX support matrix entry for the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/DemoPipeline2DexSupportMatrixEntry.ts"
)]
#[serde(rename_all = "camelCase")]
pub(crate) struct DemoPipeline2DexSupportMatrixEntry {
/// Stable internal protocol or surface code.
pub code: std::string::String,
/// Human-readable protocol or surface name.
pub display_name: std::string::String,
/// Protocol family.
pub family: std::string::String,
/// Protocol version or `unknown` when not verified locally.
pub version: std::string::String,
/// Surface type: launch, bonding curve, AMM, CLMM, DLMM, router, aggregator or unknown.
pub surface_type: std::string::String,
/// Primary Solana program id, when verified in local constants or docs.
pub program_id: std::option::Option<std::string::String>,
/// Optional router program id, when this entry uses a distinct router.
pub router_program_id: std::option::Option<std::string::String>,
/// Program id confidence: known, to_verify or unknown.
pub program_id_status: std::string::String,
/// Whether this protocol has been observed in the local replay corpus.
pub observed: bool,
/// Whether the code currently contains a decoder for this protocol.
pub decoded: bool,
/// Whether decoded events are currently materialized beyond raw decoded rows.
pub materialized: bool,
/// Whether this protocol can currently produce trade candidates.
pub trade_candidate: bool,
/// Whether this protocol can currently produce candle candidates.
pub candle_candidate: bool,
/// Whether this protocol can currently produce pair candidates.
pub pair_candidate: bool,
/// Whether this protocol can currently produce pool candidates.
pub pool_candidate: bool,
/// Operational support status.
pub status: std::string::String,
/// Confidence level attached to this matrix entry.
pub confidence: std::string::String,
/// Optional explicit skip reason for partial or ignored entries.
pub skip_reason: std::option::Option<std::string::String>,
/// Whether the entry should be inserted as an enabled DEX in the storage catalog.
pub catalog_enabled: bool,
}
/// One local pipeline validation issue for the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
@@ -839,14 +904,32 @@ pub(crate) async fn demo_pipeline2_diagnose_local_pipeline(
})
}
/// Validates the local pipeline with the `0.7.28` multi-DEX non-regression profile.
/// Validates the local pipeline with a selected multi-DEX validation profile.
#[tauri::command]
pub(crate) async fn demo_pipeline2_validate_local_pipeline(
state: tauri::State<'_, crate::AppState>,
request: std::option::Option<DemoPipeline2LocalValidationRequest>,
) -> Result<DemoPipeline2LocalValidationPayload, std::string::String> {
let database = state.database.clone();
let service = kb_lib::LocalPipelineValidationService::new(database.clone());
let run_result = service.validate_v0_7_28_current_database().await;
let profile_code = match request {
Some(request) => request.profile_code,
None => "0.7.29_multi_dex_matrix_baseline".to_string(),
};
let run_result = match profile_code.as_str() {
"0.7.27" | "0.7.27_dexes_non_regression" => {
service.validate_v0_7_27_current_database().await
},
"0.7.28" | "0.7.28_multi_dex_non_regression" => {
service.validate_v0_7_28_current_database().await
},
"0.7.29" | "0.7.29_multi_dex_matrix_baseline" => {
service.validate_v0_7_29_current_database().await
},
other => Err(kb_lib::Error::InvalidState(format!(
"unsupported local pipeline validation profile: {other}"
))),
};
let run = match run_result {
Ok(run) => run,
Err(error) => {
@@ -1257,6 +1340,10 @@ fn demo_pipeline2_map_local_validation_report(
for issue in report.issues {
issues.push(demo_pipeline2_map_local_validation_issue(issue));
}
let mut dex_support_matrix = std::vec::Vec::new();
for entry in report.dex_support_matrix {
dex_support_matrix.push(demo_pipeline2_map_dex_support_matrix_entry(entry));
}
return DemoPipeline2LocalPipelineValidationReport {
validation_profile_code: report.validation_profile_code,
validation_passed: report.validation_passed,
@@ -1264,10 +1351,38 @@ fn demo_pipeline2_map_local_validation_report(
warning_count: report.warning_count,
expected_dex_codes: report.expected_dex_codes,
observed_dex_codes: report.observed_dex_codes,
dex_support_matrix_entry_count: report.dex_support_matrix_entry_count,
dex_support_matrix,
issues,
};
}
fn demo_pipeline2_map_dex_support_matrix_entry(
entry: kb_lib::DexSupportMatrixEntryDto,
) -> DemoPipeline2DexSupportMatrixEntry {
return DemoPipeline2DexSupportMatrixEntry {
code: entry.code,
display_name: entry.display_name,
family: entry.family,
version: entry.version,
surface_type: entry.surface_type,
program_id: entry.program_id,
router_program_id: entry.router_program_id,
program_id_status: entry.program_id_status,
observed: entry.observed,
decoded: entry.decoded,
materialized: entry.materialized,
trade_candidate: entry.trade_candidate,
candle_candidate: entry.candle_candidate,
pair_candidate: entry.pair_candidate,
pool_candidate: entry.pool_candidate,
status: entry.status,
confidence: entry.confidence,
skip_reason: entry.skip_reason,
catalog_enabled: entry.catalog_enabled,
};
}
fn demo_pipeline2_map_local_validation_issue(
issue: kb_lib::LocalPipelineValidationIssueDto,
) -> DemoPipeline2LocalPipelineValidationIssue {

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "kb-demo-app",
"version": "0.7.28",
"version": "0.7.29",
"identifier": "com.sasedev.kb-demo-app",
"build": {
"beforeDevCommand": "npm run dev",