0.7.28 - final

This commit is contained in:
2026-05-12 15:04:04 +02:00
parent 7f130dba6b
commit 4f6a4806e2
34 changed files with 4020 additions and 199 deletions

View File

@@ -168,7 +168,50 @@
Diagnose local pipeline
</button>
<button id="demoPipeline2ValidateLocalPipelineButton" type="button" class="btn btn-outline-success">
Validate 0.7.27
Validate
</button>
</div>
</div>
</div>
</div>
<div class="accordion-item border-0 shadow-sm mb-3">
<h2 class="accordion-header" id="demoPipeline2DiscriminatorDiagnosticsHeading">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2DiscriminatorDiagnosticsCollapse" aria-expanded="false" aria-controls="demoPipeline2DiscriminatorDiagnosticsCollapse">
Instruction discriminators
</button>
</h2>
<div id="demoPipeline2DiscriminatorDiagnosticsCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2DiscriminatorDiagnosticsHeading" data-bs-parent="#demoPipeline2LeftAccordion">
<div class="accordion-body">
<p class="small text-body-secondary mb-3">
Groupe les instructions dun programme par discriminator décodé, nombre de comptes, stack height et statut decoded/non-decoded.
</p>
<div class="mb-3">
<label for="demoPipeline2DiscriminatorProgramIdInput" class="form-label">Program id</label>
<input
id="demoPipeline2DiscriminatorProgramIdInput"
type="text"
class="form-control font-monospace"
value="LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
/>
</div>
<div class="mb-3">
<label for="demoPipeline2DiscriminatorLimitInput" class="form-label">Instruction row limit</label>
<input
id="demoPipeline2DiscriminatorLimitInput"
type="number"
min="1"
step="1"
class="form-control"
value="200"
/>
</div>
<div class="d-flex gap-2">
<button id="demoPipeline2LoadDiscriminatorSummariesButton" type="button" class="btn btn-outline-warning">
Load discriminator summaries
</button>
</div>
</div>
@@ -290,6 +333,25 @@
</div>
</div>
</div>
<div class="accordion-item border-0 shadow-sm mb-3">
<h2 class="accordion-header" id="demoPipeline2DiscriminatorSummaryHeading">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#demoPipeline2DiscriminatorSummaryCollapse" aria-expanded="false" aria-controls="demoPipeline2DiscriminatorSummaryCollapse">
Instruction discriminator summaries
</button>
</h2>
<div id="demoPipeline2DiscriminatorSummaryCollapse" class="accordion-collapse collapse" aria-labelledby="demoPipeline2DiscriminatorSummaryHeading" data-bs-parent="#demoPipeline2ContentAccordion">
<div class="accordion-body">
<textarea
id="demoPipeline2DiscriminatorSummariesTextarea"
class="form-control font-monospace"
rows="18"
readonly
spellcheck="false"
></textarea>
</div>
</div>
</div>
<div class="accordion-item border-0 shadow-sm mb-3">
<h2 class="accordion-header" id="demoPipeline2ProtocolCandidateSummaryHeading">

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.
/**
* Response payload for program instruction discriminator summaries.
*/
export type DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload = {
/**
* Pretty JSON summary rows.
*/
summariesJson: string, };

View File

@@ -0,0 +1,14 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
/**
* Request payload for program instruction discriminator summaries.
*/
export type DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest = {
/**
* Program id to inspect.
*/
programId: string,
/**
* Maximum number of instruction rows to inspect before grouping.
*/
limit: number, };

View File

@@ -15,6 +15,8 @@ import type { DemoPipeline2PairCandlesRequest } from "./bindings/DemoPipeline2Pa
import type { DemoPipeline2PairCandlesPayload } from "./bindings/DemoPipeline2PairCandlesPayload.ts";
import type { DemoPipeline2LocalDiagnosticsPayload } from "./bindings/DemoPipeline2LocalDiagnosticsPayload.ts";
import type { DemoPipeline2LocalValidationPayload } from "./bindings/DemoPipeline2LocalValidationPayload.ts";
import type { DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest } from "./bindings/DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest.ts";
import type { DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload } from "./bindings/DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload.ts";
import { DemoPipeline2ProtocolCandidateSummaryRequest } from './bindings/DemoPipeline2ProtocolCandidateSummaryRequest.ts';
import { DemoPipeline2ProtocolCandidateSummaryPayload } from './bindings/DemoPipeline2ProtocolCandidateSummaryPayload.ts';
@@ -356,6 +358,10 @@ document.addEventListener("DOMContentLoaded", async () => {
const diagnoseLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2DiagnoseLocalPipelineButton");
const validateLocalPipelineButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ValidateLocalPipelineButton");
const discriminatorProgramIdInput = document.querySelector<HTMLInputElement>("#demoPipeline2DiscriminatorProgramIdInput");
const discriminatorLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2DiscriminatorLimitInput");
const loadDiscriminatorSummariesButton = document.querySelector<HTMLButtonElement>("#demoPipeline2LoadDiscriminatorSummariesButton");
const protocolCandidateLimitInput = document.querySelector<HTMLInputElement>("#demoPipeline2ProtocolCandidateLimitInput");
const refreshProtocolCandidatesButton = document.querySelector<HTMLButtonElement>("#demoPipeline2RefreshProtocolCandidatesButton");
@@ -371,6 +377,8 @@ document.addEventListener("DOMContentLoaded", async () => {
const localDiagnosticsTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2LocalDiagnosticsTextarea");
const localValidationTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2LocalValidationTextarea");
const discriminatorSummariesTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2DiscriminatorSummariesTextarea");
const protocolCandidateSummariesTextarea = document.querySelector<HTMLTextAreaElement>("#demoPipeline2ProtocolCandidateSummariesTextarea");
const clearLogButton = document.querySelector<HTMLButtonElement>("#demoPipeline2ClearLogButton");
@@ -395,6 +403,9 @@ document.addEventListener("DOMContentLoaded", async () => {
!replayLocalPipelineButton ||
!diagnoseLocalPipelineButton ||
!validateLocalPipelineButton ||
!discriminatorProgramIdInput ||
!discriminatorLimitInput ||
!loadDiscriminatorSummariesButton ||
!protocolCandidateLimitInput ||
!refreshProtocolCandidatesButton ||
!pairSelect ||
@@ -405,6 +416,7 @@ document.addEventListener("DOMContentLoaded", async () => {
!backfillSummaryTextarea ||
!localDiagnosticsTextarea ||
!localValidationTextarea ||
!discriminatorSummariesTextarea ||
!protocolCandidateSummariesTextarea ||
!chartElement ||
!chartMeta ||
@@ -635,7 +647,7 @@ document.addEventListener("DOMContentLoaded", async () => {
});
validateLocalPipelineButton.addEventListener("click", async () => {
appendLogLine(logTextarea, "[ui] validating local pipeline with 0.7.27 profile");
appendLogLine(logTextarea, "[ui] validating local pipeline with 0.7.28 profile");
try {
const payload = await invoke<DemoPipeline2LocalValidationPayload>(
@@ -693,6 +705,52 @@ document.addEventListener("DOMContentLoaded", async () => {
}
});
loadDiscriminatorSummariesButton.addEventListener("click", async () => {
const programId = discriminatorProgramIdInput.value.trim();
if (programId === "") {
appendLogLine(logTextarea, "[ui] discriminator program id is required");
return;
}
const limit = readPositiveIntegerInput(
discriminatorLimitInput,
logTextarea,
"discriminatorSummaryLimit",
);
if (limit === undefined) {
return;
}
appendLogLine(
logTextarea,
`[ui] loading instruction discriminator summaries for program '${programId}' with limit '${limit.toString()}'`,
);
const request: DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest = {
programId,
limit,
};
try {
const payload = await invoke<DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload>(
"demo_pipeline2_get_program_instruction_discriminator_summaries",
{ request },
);
discriminatorSummariesTextarea.value = payload.summariesJson;
appendLogLine(
logTextarea,
"[ui] instruction discriminator summaries loaded",
);
} catch (error) {
appendLogLine(
logTextarea,
`[ui] instruction discriminator summary error: ${String(error)}`,
);
}
});
loadCandlesButton.addEventListener("click", async () => {
const pairIdText = pairSelect.value.trim();
if (pairIdText === "") {

View File

@@ -10,6 +10,31 @@
use tauri::Manager;
use ts_rs::TS;
/// Request payload for program instruction discriminator summaries.
#[derive(Clone, Debug, serde::Deserialize, ts_rs::TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest.ts"
)]
#[serde(rename_all = "camelCase")]
pub(crate) struct DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest {
/// Program id to inspect.
pub program_id: std::string::String,
/// Maximum number of instruction rows to inspect before grouping.
pub limit: u32,
}
/// Response payload for program instruction discriminator summaries.
#[derive(Clone, Debug, serde::Serialize, ts_rs::TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload.ts"
)]
#[serde(rename_all = "camelCase")]
pub(crate) struct DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload {
/// Pretty JSON summary rows.
pub summaries_json: std::string::String,
}
/// Request payload for protocol candidate summary diagnostics.
#[derive(Clone, Debug, serde::Deserialize, ts_rs::TS)]
@@ -35,9 +60,6 @@ pub(crate) struct DemoPipeline2ProtocolCandidateSummaryPayload {
pub summaries_json: std::string::String,
}
/// Local diagnostics payload returned to the UI.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
@@ -718,6 +740,43 @@ pub(crate) struct DemoPipeline2PairCandlesPayload {
pub candles_json: std::string::String,
}
/// Lists program instruction discriminator summaries for one program id.
#[tauri::command]
pub(crate) async fn demo_pipeline2_get_program_instruction_discriminator_summaries(
state: tauri::State<'_, crate::AppState>,
request: DemoPipeline2ProgramInstructionDiscriminatorSummaryRequest,
) -> Result<DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload, std::string::String> {
if request.program_id.trim().is_empty() {
return Err("program id must not be empty".to_string());
}
if request.limit == 0 {
return Err("instruction discriminator summary limit must be > 0".to_string());
}
let rows_result = kb_lib::query_program_instruction_discriminator_summaries_list_by_program_id(
state.database.as_ref(),
request.program_id.as_str(),
request.limit,
)
.await;
let rows = match rows_result {
Ok(rows) => rows,
Err(error) => {
return Err(format!(
"cannot list instruction discriminator summaries for program_id '{}': {}",
request.program_id, error
));
},
};
let summaries_json_result = serde_json::to_string_pretty(&rows);
let summaries_json = match summaries_json_result {
Ok(summaries_json) => summaries_json,
Err(error) => {
return Err(format!("cannot serialize instruction discriminator summaries: {}", error));
},
};
return Ok(DemoPipeline2ProgramInstructionDiscriminatorSummaryPayload { summaries_json });
}
/// Lists protocol candidate summaries ordered by investigation priority.
#[tauri::command]
pub(crate) async fn demo_pipeline2_get_protocol_candidate_summaries(
@@ -745,10 +804,7 @@ pub(crate) async fn demo_pipeline2_get_protocol_candidate_summaries(
let summaries_json = match summaries_json_result {
Ok(summaries_json) => summaries_json,
Err(error) => {
return Err(format!(
"cannot serialize protocol candidate summaries: {}",
error
));
return Err(format!("cannot serialize protocol candidate summaries: {}", error));
},
};
return Ok(DemoPipeline2ProtocolCandidateSummaryPayload { summaries_json });
@@ -783,14 +839,14 @@ pub(crate) async fn demo_pipeline2_diagnose_local_pipeline(
})
}
/// Validates the local pipeline with the strict `0.7.27` non-regression profile.
/// Validates the local pipeline with the `0.7.28` multi-DEX non-regression profile.
#[tauri::command]
pub(crate) async fn demo_pipeline2_validate_local_pipeline(
state: tauri::State<'_, crate::AppState>,
) -> 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_27_current_database().await;
let run_result = service.validate_v0_7_28_current_database().await;
let run = match run_result {
Ok(run) => run,
Err(error) => {

View File

@@ -154,6 +154,7 @@ pub async fn run() -> Result<(), kb_lib::Error> {
crate::demo_pipeline2::demo_pipeline2_diagnose_local_pipeline,
crate::demo_pipeline2::demo_pipeline2_validate_local_pipeline,
crate::demo_pipeline2::demo_pipeline2_get_protocol_candidate_summaries,
crate::demo_pipeline2::demo_pipeline2_get_program_instruction_discriminator_summaries,
]);
tauri_builder = tauri_builder.plugin(tracing_builder.build::<tauri::Wry>());
tauri_builder = tauri_builder.setup(|app| {