v0.5.3-pre.005-fix010

This commit is contained in:
2026-08-14 14:40:36 +02:00
parent b6583bd9fb
commit 734a27f2ca
59 changed files with 4337 additions and 747 deletions

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/app_state.rs
// version: 20
// version: 21
//! Shared Tauri application state and startup initialization.
@@ -18,6 +18,12 @@ pub(crate) struct AppState {
logging_guard: std::sync::Mutex<ks_logging::LoggingGuard>,
http_pool: ks_onchain_transport::HttpEndpointPool,
store: tokio::sync::OnceCell<ks_store::Store>,
profile_stores: tokio::sync::Mutex<
std::collections::BTreeMap<
std::string::String,
std::sync::Arc<tokio::sync::OnceCell<ks_store::Store>>,
>,
>,
ws_pool:
std::sync::Mutex<std::option::Option<std::sync::Arc<ks_onchain_transport::WsEndpointPool>>>,
demo_ws_session:
@@ -108,6 +114,7 @@ impl crate::AppState {
logging_guard: std::sync::Mutex::new(logging_guard),
http_pool,
store: tokio::sync::OnceCell::new(),
profile_stores: tokio::sync::Mutex::new(std::collections::BTreeMap::new()),
ws_pool: std::sync::Mutex::new(std::option::Option::None),
demo_ws_session: tokio::sync::Mutex::new(std::option::Option::None),
demo_backfill_running: std::sync::atomic::AtomicBool::new(false),
@@ -195,6 +202,63 @@ impl crate::AppState {
.await;
}
/// Returns a shared persistent store for one immutable configured profile.
pub(crate) async fn store_for_profile(
&self,
profile: &ks_config::ProfileConfig,
) -> ks_core::Result<ks_store::Store> {
let configured_profile = self
.app_config
.profiles
.iter()
.find(|candidate| return candidate.name == profile.name);
let configured_database = match configured_profile {
std::option::Option::Some(value) => value.database.clone(),
std::option::Option::None => {
return std::result::Result::Err(ks_core::Error::invalid_state(
"store profile is not part of the resolved application configuration",
));
},
};
if configured_database != profile.database {
return std::result::Result::Err(ks_core::Error::invalid_state(
"store profile database configuration mismatch",
));
}
if profile.name == self.active_profile.name {
let store_result = self.store().await;
return match store_result {
std::result::Result::Ok(store) => std::result::Result::Ok(store.clone()),
std::result::Result::Err(error) => std::result::Result::Err(error),
};
}
let cell = {
let mut stores = self.profile_stores.lock().await;
if let std::option::Option::Some(existing) = stores.get(profile.name.as_str()) {
std::sync::Arc::clone(existing)
} else {
let created = std::sync::Arc::new(tokio::sync::OnceCell::new());
stores.insert(profile.name.clone(), std::sync::Arc::clone(&created));
created
}
};
let options = match ks_store::StoreOpenOptions::new(
configured_database.enabled,
configured_database.backend,
configured_database.backend_options,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store_result = cell
.get_or_try_init(|| return async move { return ks_store::Store::open(options).await })
.await;
return match store_result {
std::result::Result::Ok(store) => std::result::Result::Ok(store.clone()),
std::result::Result::Err(error) => std::result::Result::Err(error),
};
}
/// Returns the session-only execution-wallet alias override for one profile.
pub(crate) fn demo_execution_wallet_alias_override(
&self,

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_decode_replay.rs
// version: 45
// version: 46
//! Tauri commands and UI payloads for contextual instruction decode replay.
@@ -271,8 +271,10 @@ pub(crate) struct DemoDecodeDiagnosticsPayload {
pub(crate) struct DemoTransactionAnnotationRequest {
/// Optional partial transaction signature.
pub(crate) signature_contains: std::option::Option<std::string::String>,
/// Maximum returned rows.
pub(crate) limit: u32,
/// Opaque cursor identifying the requested Store block.
pub(crate) cursor: std::option::Option<std::string::String>,
/// One-based Store block index maintained by the desktop navigation.
pub(crate) block_index: u32,
}
/// UI-safe committed transaction annotation row.
@@ -313,6 +315,20 @@ pub(crate) struct DemoTransactionAnnotationRow {
pub(crate) updated_at: std::string::String,
}
/// One counted Store block of committed transaction annotations.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_decode_replay/DemoTransactionAnnotationPagePayload.ts"
)]
pub(crate) struct DemoTransactionAnnotationPagePayload {
/// Shared block metadata refreshed with this load.
pub(crate) page: crate::DemoStoreBlockMetadata,
/// Annotations in the current Store block.
pub(crate) rows: std::vec::Vec<crate::DemoTransactionAnnotationRow>,
}
pub(crate) struct DemoDecodeReplayObserver<'a> {
pub(crate) app_handle: tauri::AppHandle,
pub(crate) campaign_id: std::string::String,
@@ -604,39 +620,49 @@ pub(crate) async fn demo_decode_replay_diagnostics(
pub(crate) async fn demo_decode_replay_annotations(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoTransactionAnnotationRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoTransactionAnnotationRow>, std::string::String> {
let filter_result = ks_store::MaterializedOutputFilter::new(
) -> std::result::Result<crate::DemoTransactionAnnotationPagePayload, std::string::String> {
let filter = ks_store::MaterializedOutputPageFilter::new(
std::option::Option::Some("materializer.transaction.annotations".to_string()),
std::option::Option::Some("transaction_annotation".to_string()),
std::option::Option::Some("spl.memo".to_string()),
request.signature_contains,
request.limit,
std::vec::Vec::new(),
);
let filter = match filter_result {
let page_request_result = crate::demo_store_block_request(request.cursor);
let page_request = match page_request_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
tracing::debug!(target: crate::TRACING_TARGET, action = "load_transaction_annotations", signature_contains = ?filter.signature_contains, limit = filter.limit, "load bounded committed transaction annotation journal");
tracing::debug!(target: crate::TRACING_TARGET, action = "load_transaction_annotations", block_index = request.block_index, "load committed transaction annotation Store block");
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let rows_result =
ks_store::DecodePipelineStore::list_materialized_outputs(&store, &filter).await;
let rows = match rows_result {
let page_result = store.materialized_output_page(&filter, &page_request).await;
let page = match page_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let mut output = std::vec::Vec::with_capacity(rows.len());
for row in rows {
let metadata_result =
crate::demo_store_block_metadata(page.total_rows, page.next_cursor, request.block_index);
let metadata = match metadata_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut rows = std::vec::Vec::with_capacity(page.rows.len());
for row in page.rows {
let mapped = annotation_payload(row);
match mapped {
std::result::Result::Ok(value) => output.push(value),
std::result::Result::Ok(value) => rows.push(value),
std::result::Result::Err(error) => return std::result::Result::Err(error),
}
}
tracing::debug!(target: crate::TRACING_TARGET, action = "load_transaction_annotations", row_count = output.len(), "bounded committed transaction annotation journal loaded");
return std::result::Result::Ok(output);
tracing::debug!(target: crate::TRACING_TARGET, action = "load_transaction_annotations", row_count = rows.len(), total_rows = %metadata.total_rows, block_index = metadata.block_index, total_blocks = metadata.total_blocks, "committed transaction annotation Store block loaded");
return std::result::Result::Ok(crate::DemoTransactionAnnotationPagePayload {
page: metadata,
rows,
});
}
fn register_active_campaign(

View File

@@ -1,7 +1,7 @@
// file: kb-app-demo-desktop/src/demo_devnet_common.rs
// version: 7
// version: 9
//! Shared Devnet demo UI contracts.
//! Shared Devnet demo UI contracts and profile/store helpers.
use ts_rs::TS; // rust-rules: derive-import
@@ -31,8 +31,57 @@ pub(crate) struct DemoExecutionDevnetStoreReadinessPayload {
pub(crate) expected_resources: u32,
}
/// Resolves one explicitly selected compatible Devnet profile.
pub(crate) fn select_devnet_profile(
config: &ks_config::AppConfig,
profile_name: &str,
) -> std::result::Result<ks_config::ProfileConfig, std::string::String> {
return ks_pipeline_demo_scenarios::resolve_demo_devnet_profile(
config,
std::option::Option::Some(profile_name),
)
.map_err(|error| return error.to_string());
}
/// Verifies or initializes the configured store selected by one Devnet profile.
pub(crate) async fn demo_execution_devnet_prepare_profile(
state: tauri::State<'_, crate::AppState>,
profile_name: std::string::String,
) -> std::result::Result<DemoExecutionDevnetStoreReadinessPayload, std::string::String> {
let profile = match select_devnet_profile(state.app_config(), profile_name.as_str()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let configuration = store.configuration_summary();
let initialization = store.initialization_summary();
if initialization.status != ks_store::StoreInitializationStatus::Ready {
return std::result::Result::Err(format!(
"Devnet profile '{}' store model is incomplete and automatic initialization is {}",
profile.name,
if configuration.auto_initialize_schema { "enabled" } else { "disabled" }
));
}
let readiness = ks_pipeline_demo_scenarios::DevnetProfileStoreReadiness {
profile_name: profile.name.clone(),
backend: configuration.backend_code.clone(),
auto_initialize_schema: configuration.auto_initialize_schema,
available_resources_before: initialization
.available_resource_count
.saturating_sub(initialization.created_resource_count)
as usize,
created_resources: initialization.created_resource_count as usize,
available_resources_after: initialization.available_resource_count as usize,
expected_resources: initialization.expected_resource_count as usize,
};
return std::result::Result::Ok(devnet_store_readiness_payload(readiness));
}
/// Converts the reusable scenario readiness report to the desktop TS-RS payload.
pub(crate) fn devnet_store_readiness_payload(
fn devnet_store_readiness_payload(
readiness: ks_pipeline_demo_scenarios::DevnetProfileStoreReadiness,
) -> DemoExecutionDevnetStoreReadinessPayload {
return DemoExecutionDevnetStoreReadinessPayload {

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_execution_metadata_metaplex_token_metadata.rs
// version: 13
// version: 14
//! Desktop adapters for generic and qualified Metaplex Token Metadata execution workflows.
@@ -190,7 +190,7 @@ pub(crate) async fn demo_execution_metadata_metaplex_token_metadata_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
@@ -1041,7 +1041,7 @@ pub(crate) async fn demo_execution_metadata_metaplex_execute_campaign(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_execution_metadata_token_2022.rs
// version: 7
// version: 8
//! Thin desktop adapter for the complete Token-2022 Token Metadata Devnet campaign.
@@ -88,7 +88,7 @@ pub(crate) async fn demo_execution_metadata_token_2022_execute_campaign(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_execution_solana_core.rs
// version: 23
// version: 26
//! Tauri adapter for bounded Solana Core execution on Devnet.
@@ -359,17 +359,6 @@ impl ks_pipeline_demo_scenarios::SolanaExecutionObserver
}
}
pub(crate) fn select_devnet_profile(
config: &ks_config::AppConfig,
profile_name: &str,
) -> std::result::Result<ks_config::ProfileConfig, std::string::String> {
return ks_pipeline_demo_scenarios::resolve_demo_devnet_profile(
config,
std::option::Option::Some(profile_name),
)
.map_err(|error| return error.to_string());
}
pub(crate) fn execution_cluster_code(
cluster: ks_lib::ExApiExecutionCluster,
) -> std::string::String {
@@ -394,25 +383,6 @@ pub(crate) fn confirmation_status_code(
};
}
/// Verifies or initializes the configured store selected by one Devnet profile.
pub(crate) async fn demo_execution_devnet_prepare_profile(
state: tauri::State<'_, crate::AppState>,
profile_name: std::string::String,
) -> std::result::Result<crate::DemoExecutionDevnetStoreReadinessPayload, std::string::String> {
let profile = match crate::select_devnet_profile(state.app_config(), profile_name.as_str()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let readiness =
match ks_pipeline_demo_scenarios::prepare_demo_devnet_profile_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(error.to_string());
},
};
return std::result::Result::Ok(crate::devnet_store_readiness_payload(readiness));
}
/// Returns compatible Devnet profiles and conservative defaults.
pub(crate) fn demo_execution_solana_core_options(
state: tauri::State<'_, crate::AppState>,
@@ -473,7 +443,7 @@ pub(crate) async fn demo_execution_solana_core_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
@@ -557,7 +527,7 @@ pub(crate) async fn demo_execution_spl_memo_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_spl_ata.rs
// version: 19
// version: 21
//! Thin Tauri adapter for ATA execution, derivation and lifecycle journal reads.
@@ -129,8 +129,24 @@ pub(crate) struct DemoSplAtaJournalRequest {
pub(crate) associated_token_account: std::option::Option<std::string::String>,
/// Optional exact materialized operation.
pub(crate) operation: std::option::Option<std::string::String>,
/// Maximum returned rows.
pub(crate) limit: u32,
/// Opaque cursor identifying the requested Store block.
pub(crate) cursor: std::option::Option<std::string::String>,
/// One-based Store block index maintained by the desktop navigation.
pub(crate) block_index: u32,
}
/// One counted Store block of ATA lifecycle journal rows.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_ata/DemoSplAtaJournalPagePayload.ts"
)]
pub(crate) struct DemoSplAtaJournalPagePayload {
/// Shared block metadata refreshed with this load.
pub(crate) page: crate::DemoStoreBlockMetadata,
/// Typed rows retained from the current Store block.
pub(crate) rows: std::vec::Vec<crate::DemoSplAtaJournalRow>,
}
/// One UI-safe ATA lifecycle journal row.
@@ -260,7 +276,7 @@ pub(crate) async fn demo_execution_spl_ata_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
@@ -303,46 +319,54 @@ pub(crate) async fn demo_execution_spl_ata_execute(
pub(crate) async fn demo_spl_ata_journal(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSplAtaJournalRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSplAtaJournalRow>, std::string::String> {
if request.limit == 0 || request.limit > 500 {
return std::result::Result::Err("ATA journal limit must be between 1 and 500".to_string());
}
) -> std::result::Result<crate::DemoSplAtaJournalPagePayload, std::string::String> {
let profile =
match crate::select_devnet_profile(state.app_config(), request.profile_name.as_str()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let filter = match ks_store::MaterializedOutputFilter::new(
let mut payload_match_groups = std::vec::Vec::new();
if let std::option::Option::Some(operation) = request.operation.as_ref() {
payload_match_groups.push(vec![serde_json::json!({"operation": operation})]);
}
if let std::option::Option::Some(mint) = request.mint.as_ref() {
payload_match_groups.push(vec![serde_json::json!({"mint": mint})]);
}
if let std::option::Option::Some(associated_token_account) =
request.associated_token_account.as_ref()
{
payload_match_groups
.push(vec![serde_json::json!({"associatedTokenAccount": associated_token_account})]);
}
let filter = ks_store::MaterializedOutputPageFilter::new(
std::option::Option::Some("materializer.token.accounts".to_string()),
std::option::Option::None,
std::option::Option::Some("spl.associated_token_account".to_string()),
request.signature_contains.clone(),
500,
) {
payload_match_groups,
);
let page_request_result = crate::demo_store_block_request(request.cursor.clone());
let page_request = match page_request_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let page_result = store.materialized_output_page(&filter, &page_request).await;
let page = match page_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let rows = match ks_store::DecodePipelineStore::list_materialized_outputs(&store, &filter).await
{
let metadata_result =
crate::demo_store_block_metadata(page.total_rows, page.next_cursor, request.block_index);
let metadata = match metadata_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut output = std::vec::Vec::new();
for row in rows {
if row.source_decoder_name != "spl.associated_token_account"
|| !journal_matches(&row.payload_json, &request)
{
continue;
}
output.push(journal_row(row));
if output.len() >= request.limit as usize {
break;
}
}
return std::result::Result::Ok(output);
let rows = page.rows.into_iter().map(journal_row).collect();
return std::result::Result::Ok(crate::DemoSplAtaJournalPagePayload { page: metadata, rows });
}
async fn load_profile_wallet(
@@ -544,6 +568,7 @@ fn summary_payload(
};
}
#[cfg(test)]
fn journal_matches(payload: &serde_json::Value, request: &crate::DemoSplAtaJournalRequest) -> bool {
for (expected, key) in [
(&request.operation, "operation"),
@@ -605,7 +630,8 @@ mod tests {
mint: std::option::Option::Some("mint111".to_string()),
associated_token_account: std::option::Option::Some("ata111".to_string()),
operation: std::option::Option::Some("create_idempotent".to_string()),
limit: 100,
cursor: std::option::Option::None,
block_index: 1,
};
assert!(super::journal_matches(
&serde_json::json!({

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_spl_token.rs
// version: 17
// version: 19
//! Thin Tauri adapter for classic SPL Token execution and materialized journals.
@@ -111,8 +111,24 @@ pub(crate) struct DemoSplTokenJournalRequest {
pub(crate) family: std::option::Option<std::string::String>,
/// Optional exact operation code without the `spl.token.` prefix.
pub(crate) operation: std::option::Option<std::string::String>,
/// Maximum number of rows returned after typed filtering.
pub(crate) limit: u32,
/// Opaque cursor identifying the requested Store block.
pub(crate) cursor: std::option::Option<std::string::String>,
/// One-based Store block index maintained by the desktop navigation.
pub(crate) block_index: u32,
}
/// One counted Store block of classic SPL Token journal rows.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token/DemoSplTokenJournalPagePayload.ts"
)]
pub(crate) struct DemoSplTokenJournalPagePayload {
/// Shared block metadata refreshed with this load.
pub(crate) page: crate::DemoStoreBlockMetadata,
/// Typed rows retained from the current Store block.
pub(crate) rows: std::vec::Vec<crate::DemoSplTokenJournalRow>,
}
/// UI-safe materialized classic SPL Token journal row.
@@ -183,7 +199,7 @@ pub(crate) async fn demo_execution_spl_token_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
@@ -246,7 +262,7 @@ pub(crate) async fn demo_execution_spl_token_execute(
pub(crate) async fn demo_spl_token_journal(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSplTokenJournalRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSplTokenJournalRow>, std::string::String> {
) -> std::result::Result<crate::DemoSplTokenJournalPagePayload, std::string::String> {
let validated = match validate_journal_request(request) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
@@ -256,43 +272,48 @@ pub(crate) async fn demo_spl_token_journal(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let needs_payload_filter =
validated.mint.is_some() || validated.account.is_some() || validated.operation.is_some();
let query_limit = if needs_payload_filter {
ks_store::MAX_MATERIALIZED_OUTPUT_QUERY_ROWS
} else {
validated.limit
};
let filter = match ks_store::MaterializedOutputFilter::new(
let mut payload_match_groups = std::vec::Vec::new();
if let std::option::Option::Some(operation) = validated.operation.as_ref() {
payload_match_groups.push(vec![serde_json::json!({"operation": operation})]);
}
if let std::option::Option::Some(mint) = validated.mint.as_ref() {
payload_match_groups.push(vec![
serde_json::json!({"mint": mint}),
serde_json::json!({"accounts": [{"role": "mint", "accountKey": mint}]}),
]);
}
if let std::option::Option::Some(account) = validated.account.as_ref() {
payload_match_groups.push(vec![serde_json::json!({"accounts": [{"accountKey": account}]})]);
}
let filter = ks_store::MaterializedOutputPageFilter::new(
std::option::Option::None,
validated.family.clone(),
std::option::Option::Some("spl.token".to_string()),
validated.signature_contains.clone(),
query_limit,
) {
payload_match_groups,
);
let page_request_result = crate::demo_store_block_request(validated.cursor.clone());
let page_request = match page_request_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let page_result = store.materialized_output_page(&filter, &page_request).await;
let page = match page_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let rows = match ks_store::DecodePipelineStore::list_materialized_outputs(&store, &filter).await
{
let metadata_result =
crate::demo_store_block_metadata(page.total_rows, page.next_cursor, validated.block_index);
let metadata = match metadata_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut output = std::vec::Vec::new();
for row in rows {
if row.source_decoder_name != "spl.token" || !payload_matches(&row.payload_json, &validated)
{
continue;
}
output.push(journal_row(row));
if output.len() >= validated.limit as usize {
break;
}
}
return std::result::Result::Ok(output);
let rows = page.rows.into_iter().map(journal_row).collect();
return std::result::Result::Ok(crate::DemoSplTokenJournalPagePayload { page: metadata, rows });
}
fn summary_payload(
@@ -412,12 +433,6 @@ fn replay_diagnostics(summary: &ks_pipeline::DecodeReplaySummary) -> serde_json:
fn validate_journal_request(
request: crate::DemoSplTokenJournalRequest,
) -> std::result::Result<crate::DemoSplTokenJournalRequest, std::string::String> {
if request.limit == 0 || request.limit > ks_store::MAX_MATERIALIZED_OUTPUT_QUERY_ROWS {
return std::result::Result::Err(format!(
"journal limit must be between 1 and {}",
ks_store::MAX_MATERIALIZED_OUTPUT_QUERY_ROWS
));
}
if request.profile_name.trim().is_empty() {
return std::result::Result::Err("journal profile name must not be empty".to_string());
}
@@ -456,7 +471,8 @@ fn validate_journal_request(
account,
family,
operation,
limit: request.limit,
cursor: request.cursor,
block_index: request.block_index,
});
}
@@ -473,6 +489,7 @@ fn bounded_optional(
return std::result::Result::Ok(trimmed);
}
#[cfg(test)]
fn payload_matches(
payload: &serde_json::Value,
request: &crate::DemoSplTokenJournalRequest,
@@ -586,7 +603,8 @@ mod tests {
account: std::option::Option::Some("source111".to_string()),
family: std::option::Option::Some("token_account".to_string()),
operation: std::option::Option::Some("transfer_checked".to_string()),
limit: 25,
cursor: std::option::Option::None,
block_index: 1,
};
let payload = serde_json::json!({
"operation": "transfer_checked",
@@ -622,7 +640,7 @@ mod tests {
}
#[test]
fn journal_rejects_unbounded_or_unknown_family_requests() {
fn journal_rejects_unknown_family_requests() {
let request = crate::DemoSplTokenJournalRequest {
profile_name: "local_devnet".to_string(),
signature_contains: std::option::Option::None,
@@ -630,7 +648,8 @@ mod tests {
account: std::option::Option::None,
family: std::option::Option::Some("fee".to_string()),
operation: std::option::Option::None,
limit: 501,
cursor: std::option::Option::None,
block_index: 1,
};
assert!(super::validate_journal_request(request).is_err());
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_spl_token_2022.rs
// version: 20
// version: 21
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
@@ -159,7 +159,7 @@ pub(crate) async fn demo_execution_spl_token_2022_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::open_store(&profile).await {
let store = match crate::shared_store_for_profile(state.inner(), &profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};

View File

@@ -1,10 +1,78 @@
// file: kb-app-demo-desktop/src/demo_store_common.rs
// version: 19
// version: 21
//! Shared backend-agnostic store demo helpers and serializable payloads.
use ts_rs::TS; // rust-rules: derive-import
/// Pagination metadata shared by desktop Store block listings.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store/DemoStoreBlockMetadata.ts"
)]
pub(crate) struct DemoStoreBlockMetadata {
/// Fixed number of backend rows requested per Store block.
pub(crate) block_size: u16,
/// One-based block index, or zero when the filtered result set is empty.
pub(crate) block_index: u32,
/// Total matching rows rendered losslessly for the WebView.
pub(crate) total_rows: std::string::String,
/// Total number of fixed Store blocks.
pub(crate) total_blocks: u32,
/// Opaque cursor for the next Store block when one exists.
pub(crate) next_cursor: std::option::Option<std::string::String>,
}
/// Fixed backend block size used by desktop Store listings.
pub(crate) const DEMO_STORE_BLOCK_SIZE: u16 = ks_store::MAX_PAGE_SIZE;
/// Builds one fixed-size Store block request.
pub(crate) fn demo_store_block_request(
cursor: std::option::Option<std::string::String>,
) -> std::result::Result<ks_store::PageRequest, std::string::String> {
let request_result = ks_store::PageRequest::new(crate::DEMO_STORE_BLOCK_SIZE, cursor);
return match request_result {
std::result::Result::Ok(value) => std::result::Result::Ok(value),
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Calculates refreshed desktop block metadata from one counted Store page.
pub(crate) fn demo_store_block_metadata(
total_rows: u64,
next_cursor: std::option::Option<std::string::String>,
requested_block_index: u32,
) -> std::result::Result<crate::DemoStoreBlockMetadata, std::string::String> {
if requested_block_index == 0 {
return std::result::Result::Err("Store block index must be greater than zero".to_string());
}
let block_size = u64::from(crate::DEMO_STORE_BLOCK_SIZE);
let total_blocks_u64 = if total_rows == 0 { 0 } else { ((total_rows - 1) / block_size) + 1 };
let total_blocks_result = u32::try_from(total_blocks_u64);
let total_blocks = match total_blocks_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_error) => {
return std::result::Result::Err(
"Store block count exceeds desktop bounds".to_string(),
);
},
};
if total_blocks > 0 && requested_block_index > total_blocks {
return std::result::Result::Err(format!(
"Store block {requested_block_index} no longer exists; reload the first block"
));
}
return std::result::Result::Ok(crate::DemoStoreBlockMetadata {
block_size: crate::DEMO_STORE_BLOCK_SIZE,
block_index: if total_rows == 0 { 0 } else { requested_block_index },
total_rows: total_rows.to_string(),
total_blocks,
next_cursor,
});
}
/// UI-safe diagnostics for one logical store resource.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
@@ -34,33 +102,6 @@ pub(crate) struct DemoStoreResourceSnapshot {
pub(crate) latest_created_at: std::option::Option<std::string::String>,
}
/// Builds backend-agnostic store-open options from one resolved profile.
fn store_open_options_from_profile(
profile: &ks_config::ProfileConfig,
) -> ks_core::Result<ks_store::StoreOpenOptions> {
return ks_store::StoreOpenOptions::new(
profile.database.enabled,
profile.database.backend.clone(),
profile.database.backend_options.clone(),
);
}
/// Opens a backend-agnostic store from one resolved profile.
///
/// Prefer [`crate::AppState::store`] for desktop commands that already own application state.
pub(crate) async fn open_store(
profile: &ks_config::ProfileConfig,
) -> std::result::Result<ks_store::Store, std::string::String> {
let options = match store_open_options_from_profile(profile) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
return match ks_store::Store::open(options).await {
std::result::Result::Ok(store) => std::result::Result::Ok(store),
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Clones the persistent store held by application state.
pub(crate) async fn shared_store(
state: &crate::AppState,
@@ -72,6 +113,18 @@ pub(crate) async fn shared_store(
};
}
/// Clones the shared persistent store held for one configured profile.
pub(crate) async fn shared_store_for_profile(
state: &crate::AppState,
profile: &ks_config::ProfileConfig,
) -> std::result::Result<ks_store::Store, std::string::String> {
let store_result = state.store_for_profile(profile).await;
return match store_result {
std::result::Result::Ok(store) => std::result::Result::Ok(store),
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Converts one logical store resource diagnostic to the UI payload shape.
pub(crate) fn store_resource_snapshot(
value: &ks_store::StoreResourceDiagnostics,
@@ -262,3 +315,22 @@ fn emit_store_startup_splash(
std::option::Option::None,
);
}
#[cfg(test)]
mod tests {
#[test]
fn fixed_store_block_metadata_rounds_up_and_keeps_empty_zero() {
let first_result = crate::demo_store_block_metadata(
1749,
std::option::Option::Some("next".to_string()),
1,
);
let first = match first_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("unexpected block metadata error: {error}"),
};
assert_eq!(first.total_blocks, 4);
assert_eq!(first.total_rows, "1749");
assert_eq!(first.block_size, 500);
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_store_replay_candidates.rs
// version: 16
// version: 17
//! Backend-agnostic read-only replay candidate browser commands.
@@ -31,8 +31,8 @@ pub(crate) struct DemoStoreReplayOptionsPayload {
pub(crate) active_profile_name: std::string::String,
/// Safe backend connection descriptor.
pub(crate) connection_descriptor: std::string::String,
/// Maximum rows accepted by one query.
pub(crate) maximum_limit: u32,
/// Fixed Store block size used by every replay-candidate listing.
pub(crate) block_size: u16,
/// Program identifiers enumerable from `ks_program_ids`.
pub(crate) known_programs: std::vec::Vec<crate::DemoStoreReplayKnownProgramOption>,
}
@@ -65,8 +65,10 @@ pub(crate) struct DemoStoreReplayTransactionRequest {
pub(crate) entity_kind: std::option::Option<std::string::String>,
/// Optional exact entity value.
pub(crate) entity_value: std::option::Option<std::string::String>,
/// Maximum returned rows.
pub(crate) limit: u32,
/// Opaque cursor identifying the requested Store block.
pub(crate) cursor: std::option::Option<std::string::String>,
/// One-based Store block index maintained by the desktop navigation.
pub(crate) block_index: u32,
/// Orders newest slots first when true.
pub(crate) newest_first: bool,
}
@@ -114,6 +116,20 @@ pub(crate) struct DemoStoreReplayTransactionRow {
pub(crate) updated_at: std::string::String,
}
/// One counted Store block of transaction replay candidates.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayTransactionPagePayload.ts"
)]
pub(crate) struct DemoStoreReplayTransactionPagePayload {
/// Shared block metadata refreshed with this load.
pub(crate) page: crate::DemoStoreBlockMetadata,
/// Rows in the current Store block.
pub(crate) rows: std::vec::Vec<crate::DemoStoreReplayTransactionRow>,
}
/// UI request for bounded program summaries.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
@@ -124,8 +140,10 @@ pub(crate) struct DemoStoreReplayTransactionRow {
pub(crate) struct DemoStoreReplayProgramRequest {
/// Optional partial program id search.
pub(crate) program_id_contains: std::option::Option<std::string::String>,
/// Maximum returned rows.
pub(crate) limit: u32,
/// Opaque cursor identifying the requested Store block.
pub(crate) cursor: std::option::Option<std::string::String>,
/// One-based Store block index maintained by the desktop navigation.
pub(crate) block_index: u32,
}
/// Aggregated program row shown by the replay candidate browser.
@@ -160,6 +178,20 @@ pub(crate) struct DemoStoreReplayProgramRow {
pub(crate) max_slot: i64,
}
/// One counted Store block of program summaries.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayProgramPagePayload.ts"
)]
pub(crate) struct DemoStoreReplayProgramPagePayload {
/// Shared block metadata refreshed with this load.
pub(crate) page: crate::DemoStoreBlockMetadata,
/// Rows in the current Store block.
pub(crate) rows: std::vec::Vec<crate::DemoStoreReplayProgramRow>,
}
/// UI request for bounded core entity summaries.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
@@ -172,8 +204,10 @@ pub(crate) struct DemoStoreReplayEntityRequest {
pub(crate) entity_kind: std::string::String,
/// Optional partial entity value search.
pub(crate) entity_value_contains: std::option::Option<std::string::String>,
/// Maximum returned rows.
pub(crate) limit: u32,
/// Opaque cursor identifying the requested Store block.
pub(crate) cursor: std::option::Option<std::string::String>,
/// One-based Store block index maintained by the desktop navigation.
pub(crate) block_index: u32,
}
/// Aggregated core entity row shown by the replay candidate browser.
@@ -202,6 +236,20 @@ pub(crate) struct DemoStoreReplayEntityRow {
pub(crate) max_slot: i64,
}
/// One counted Store block of mint, owner or account-key summaries.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayEntityPagePayload.ts"
)]
pub(crate) struct DemoStoreReplayEntityPagePayload {
/// Shared block metadata refreshed with this load.
pub(crate) page: crate::DemoStoreBlockMetadata,
/// Rows in the current Store block.
pub(crate) rows: std::vec::Vec<crate::DemoStoreReplayEntityRow>,
}
/// Writes a bounded replay-candidate CSV file into `./data/exports_csv/`.
pub(crate) async fn export_demo_store_replay_csv(
file_name: std::string::String,
@@ -264,7 +312,7 @@ pub(crate) async fn demo_store_replay_options(
return std::result::Result::Ok(crate::DemoStoreReplayOptionsPayload {
active_profile_name: profile.name,
connection_descriptor,
maximum_limit: ks_store::MAX_REPLAY_CANDIDATE_ROWS,
block_size: crate::DEMO_STORE_BLOCK_SIZE,
known_programs,
});
}
@@ -273,7 +321,7 @@ pub(crate) async fn demo_store_replay_options(
pub(crate) async fn load_demo_store_replay_transactions(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoStoreReplayTransactionRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayTransactionRow>, std::string::String> {
) -> std::result::Result<crate::DemoStoreReplayTransactionPagePayload, std::string::String> {
let program_scope_result = program_scope_from_code(request.program_scope.as_str());
let program_scope = match program_scope_result {
std::result::Result::Ok(value) => value,
@@ -294,95 +342,132 @@ pub(crate) async fn load_demo_store_replay_transactions(
program_scope,
entity_kind,
request.entity_value,
request.limit,
request.newest_first,
);
let filter = match filter_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let page_request_result = crate::demo_store_block_request(request.cursor);
let page_request = match page_request_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let rows_result = store.replay_transaction_candidates(&filter).await;
let rows = match rows_result {
let page_result = store.replay_transaction_candidates(&filter, &page_request).await;
let page = match page_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), "loaded replay transaction candidates");
let mut output = std::vec::Vec::with_capacity(rows.len());
for row in rows {
output.push(transaction_row_from_store(row));
let metadata_result =
crate::demo_store_block_metadata(page.total_rows, page.next_cursor, request.block_index);
let metadata = match metadata_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut rows = std::vec::Vec::with_capacity(page.rows.len());
for row in page.rows {
rows.push(transaction_row_from_store(row));
}
return std::result::Result::Ok(output);
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), total_rows = %metadata.total_rows, block_index = metadata.block_index, total_blocks = metadata.total_blocks, "loaded replay transaction candidate block");
return std::result::Result::Ok(crate::DemoStoreReplayTransactionPagePayload {
page: metadata,
rows,
});
}
/// Loads bounded program summaries from the active store.
/// Loads one counted Store block of program summaries.
pub(crate) async fn load_demo_store_replay_programs(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoStoreReplayProgramRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayProgramRow>, std::string::String> {
let filter_result =
ks_store::ReplayProgramFilter::new(request.program_id_contains, request.limit);
) -> std::result::Result<crate::DemoStoreReplayProgramPagePayload, std::string::String> {
let filter_result = ks_store::ReplayProgramFilter::new(request.program_id_contains);
let filter = match filter_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let page_request_result = crate::demo_store_block_request(request.cursor);
let page_request = match page_request_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let rows_result = store.replay_program_summaries(&filter).await;
let rows = match rows_result {
let page_result = store.replay_program_summaries(&filter, &page_request).await;
let page = match page_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), "loaded replay program summaries");
let mut output = std::vec::Vec::with_capacity(rows.len());
for row in rows {
output.push(program_row_from_store(row));
let metadata_result =
crate::demo_store_block_metadata(page.total_rows, page.next_cursor, request.block_index);
let metadata = match metadata_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut rows = std::vec::Vec::with_capacity(page.rows.len());
for row in page.rows {
rows.push(program_row_from_store(row));
}
return std::result::Result::Ok(output);
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), total_rows = %metadata.total_rows, block_index = metadata.block_index, total_blocks = metadata.total_blocks, "loaded replay program summary block");
return std::result::Result::Ok(crate::DemoStoreReplayProgramPagePayload {
page: metadata,
rows,
});
}
/// Loads bounded mint, owner or account-key summaries from Core facts.
/// Loads one counted Store block of mint, owner or account-key summaries.
pub(crate) async fn load_demo_store_replay_entities(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoStoreReplayEntityRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayEntityRow>, std::string::String> {
) -> std::result::Result<crate::DemoStoreReplayEntityPagePayload, std::string::String> {
let entity_kind_result = entity_kind_from_code(request.entity_kind.as_str());
let entity_kind = match entity_kind_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let filter_result = ks_store::ReplayEntityFilter::new(
entity_kind,
request.entity_value_contains,
request.limit,
);
let filter_result =
ks_store::ReplayEntityFilter::new(entity_kind, request.entity_value_contains);
let filter = match filter_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let page_request_result = crate::demo_store_block_request(request.cursor);
let page_request = match page_request_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let rows_result = store.replay_entity_summaries(&filter).await;
let rows = match rows_result {
let page_result = store.replay_entity_summaries(&filter, &page_request).await;
let page = match page_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), "loaded replay entity summaries");
let mut output = std::vec::Vec::with_capacity(rows.len());
for row in rows {
output.push(entity_row_from_store(row));
let metadata_result =
crate::demo_store_block_metadata(page.total_rows, page.next_cursor, request.block_index);
let metadata = match metadata_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut rows = std::vec::Vec::with_capacity(page.rows.len());
for row in page.rows {
rows.push(entity_row_from_store(row));
}
return std::result::Result::Ok(output);
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), total_rows = %metadata.total_rows, block_index = metadata.block_index, total_blocks = metadata.total_blocks, entity_kind = request.entity_kind.as_str(), "loaded replay entity summary block");
return std::result::Result::Ok(crate::DemoStoreReplayEntityPagePayload {
page: metadata,
rows,
});
}
fn transaction_row_from_store(

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/lib.rs
// version: 47
// version: 50
//! Tauri desktop demo application for `khadhroony-bot3`.
@@ -133,6 +133,8 @@ pub(crate) use self::demo_decode_replay::DemoDecodeReplayRequest;
pub(crate) use self::demo_decode_replay::DemoDecodeReplayRunGuard;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplaySummaryPayload;
/// Counted Store block of transaction annotations.
pub(crate) use self::demo_decode_replay::DemoTransactionAnnotationPagePayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoTransactionAnnotationRequest;
/// Internal demo decode replay item.
@@ -151,16 +153,18 @@ pub(crate) use self::demo_decode_replay::demo_decode_replay_options;
pub(crate) use self::demo_devnet_common::DemoExecutionDevnetStoreReadinessPayload;
/// Restores the shared single-execution state flag when a Devnet run finishes.
pub(crate) use self::demo_devnet_common::DemoExecutionRunGuard;
/// Prepares the Store selected by one compatible Devnet profile.
pub(crate) use self::demo_devnet_common::demo_execution_devnet_prepare_profile;
/// Loads the backend-only demo wallet password.
pub(crate) use self::demo_devnet_common::demo_wallet_password;
/// Returns whether the backend-only demo wallet password is configured.
pub(crate) use self::demo_devnet_common::demo_wallet_password_configured;
/// Converts the reusable scenario readiness report to the desktop TS-RS payload.
pub(crate) use self::demo_devnet_common::devnet_store_readiness_payload;
/// Serializes a diagnostic value to indented JSON without panicking.
pub(crate) use self::demo_devnet_common::pretty_json;
/// Resolves the temporary or persistent signer selected by one Devnet profile.
pub(crate) use self::demo_devnet_common::resolve_devnet_execution_wallet;
/// Selects and validates one Devnet profile by name.
pub(crate) use self::demo_devnet_common::select_devnet_profile;
/// Bridges Metadata execution progress to the Metadata desktop window.
pub(crate) use self::demo_execution_metadata::DemoExecutionMetadataObserver;
/// Progress event emitted by Metadata execution workflows.
@@ -237,8 +241,6 @@ pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreRequest;
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreSummaryPayload;
/// Maps a confirmation status to its stable UI code.
pub(crate) use self::demo_execution_solana_core::confirmation_status_code;
/// Returns compatible Devnet profiles and conservative defaults.
pub(crate) use self::demo_execution_solana_core::demo_execution_devnet_prepare_profile;
/// Requests cooperative cancellation before the next execution stage.
pub(crate) use self::demo_execution_solana_core::demo_execution_solana_core_cancel;
/// Executes one bounded System transfer simulation or Devnet submission.
@@ -251,8 +253,6 @@ pub(crate) use self::demo_execution_solana_core::demo_execution_solana_core_opti
pub(crate) use self::demo_execution_solana_core::demo_execution_spl_memo_execute;
/// Maps an execution cluster to its stable UI code.
pub(crate) use self::demo_execution_solana_core::execution_cluster_code;
/// Selects and validates one Devnet profile by name.
pub(crate) use self::demo_execution_solana_core::select_devnet_profile;
/// Frontend payload for one independent Devnet SPL validation scenario.
pub(crate) use self::demo_execution_spl::DevnetSplValidationScenarioPayload;
/// Returns the complete ordered Devnet SPL validation inventory for milestone 0.4.6.
@@ -283,6 +283,8 @@ pub(crate) use self::demo_spl_ata::DemoExecutionSplAtaSummaryPayload;
pub(crate) use self::demo_spl_ata::DemoSplAtaDerivationPayload;
/// Request used to derive the representative wallet ATA before execution.
pub(crate) use self::demo_spl_ata::DemoSplAtaDerivationRequest;
/// One counted Store block of ATA lifecycle journal rows.
pub(crate) use self::demo_spl_ata::DemoSplAtaJournalPagePayload;
/// Bounded ATA lifecycle journal request.
pub(crate) use self::demo_spl_ata::DemoSplAtaJournalRequest;
/// One UI-safe ATA lifecycle journal row.
@@ -297,6 +299,8 @@ pub(crate) use self::demo_spl_ata::demo_spl_ata_journal;
pub(crate) use self::demo_spl_token::DemoExecutionSplTokenRequest;
/// UI-safe result of one checked SPL Token transfer orchestration.
pub(crate) use self::demo_spl_token::DemoExecutionSplTokenSummaryPayload;
/// One counted Store block of classic SPL Token journal rows.
pub(crate) use self::demo_spl_token::DemoSplTokenJournalPagePayload;
/// Bounded exact filters for the classic SPL Token materialized journal.
pub(crate) use self::demo_spl_token::DemoSplTokenJournalRequest;
/// UI-safe materialized classic SPL Token journal row.
@@ -315,16 +319,24 @@ pub(crate) use self::demo_spl_token_2022::DemoSplToken2022FixturePayload;
pub(crate) use self::demo_spl_token_2022::demo_execution_spl_token_2022_execute;
/// Loads public Token-2022 fixture values without reading private key bytes.
pub(crate) use self::demo_spl_token_2022::demo_spl_token_2022_fixture;
/// Fixed Store block size used by desktop listings.
pub(crate) use self::demo_store_common::DEMO_STORE_BLOCK_SIZE;
/// UI-safe Store block pagination metadata.
pub(crate) use self::demo_store_common::DemoStoreBlockMetadata;
/// UI-safe logical store resource diagnostic snapshot.
pub(crate) use self::demo_store_common::DemoStoreResourceSnapshot;
/// Formats diagnostic statuses.
pub(crate) use self::demo_store_common::debug_status;
/// Calculates refreshed Store block metadata for desktop listings.
pub(crate) use self::demo_store_common::demo_store_block_metadata;
/// Builds one fixed-size Store block request for desktop listings.
pub(crate) use self::demo_store_common::demo_store_block_request;
/// Opens and verifies the configured store during startup.
pub(crate) use self::demo_store_common::initialize_store_for_startup;
/// Opens the configured backend-agnostic store.
pub(crate) use self::demo_store_common::open_store;
/// Clones the persistent application store.
pub(crate) use self::demo_store_common::shared_store;
/// Clones the shared persistent store held for one configured profile.
pub(crate) use self::demo_store_common::shared_store_for_profile;
/// Returns the safe connection descriptor exposed by the active store backend.
pub(crate) use self::demo_store_common::store_connection_descriptor;
/// Converts one logical store resource diagnostic.
@@ -343,6 +355,8 @@ pub(crate) use self::demo_store_diag::load_demo_store_diag;
pub(crate) use self::demo_store_raw::DemoStoreRawPayload;
/// Loads read-only raw resource diagnostics from the active store.
pub(crate) use self::demo_store_raw::load_demo_store_raw;
/// Store replay entity page payload.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayEntityPagePayload;
/// Store replay entity request.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayEntityRequest;
/// Store replay entity row.
@@ -351,10 +365,14 @@ pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayEntityRow;
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayKnownProgramOption;
/// Store replay options payload.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayOptionsPayload;
/// Store replay program page payload.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayProgramPagePayload;
/// Store replay program request.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayProgramRequest;
/// Store replay program row.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayProgramRow;
/// Store replay transaction page payload.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayTransactionPagePayload;
/// Store replay transaction request.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayTransactionRequest;
/// Store replay transaction row.

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/tauri.rs
// version: 46
// version: 47
//! Tauri runtime assembly and private command wrappers.
@@ -513,7 +513,7 @@ async fn demo_decode_replay_diagnostics(
async fn demo_decode_replay_annotations(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoTransactionAnnotationRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoTransactionAnnotationRow>, std::string::String> {
) -> std::result::Result<crate::DemoTransactionAnnotationPagePayload, std::string::String> {
return crate::demo_decode_replay_annotations(state, request).await;
}
@@ -605,7 +605,7 @@ async fn demo_store_replay_options(
async fn load_demo_store_replay_transactions(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoStoreReplayTransactionRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayTransactionRow>, std::string::String> {
) -> std::result::Result<crate::DemoStoreReplayTransactionPagePayload, std::string::String> {
return crate::load_demo_store_replay_transactions(state, request).await;
}
@@ -613,7 +613,7 @@ async fn load_demo_store_replay_transactions(
async fn load_demo_store_replay_programs(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoStoreReplayProgramRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayProgramRow>, std::string::String> {
) -> std::result::Result<crate::DemoStoreReplayProgramPagePayload, std::string::String> {
return crate::load_demo_store_replay_programs(state, request).await;
}
@@ -621,7 +621,7 @@ async fn load_demo_store_replay_programs(
async fn load_demo_store_replay_entities(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoStoreReplayEntityRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayEntityRow>, std::string::String> {
) -> std::result::Result<crate::DemoStoreReplayEntityPagePayload, std::string::String> {
return crate::load_demo_store_replay_entities(state, request).await;
}
@@ -857,7 +857,7 @@ async fn demo_execution_spl_token_execute(
async fn demo_spl_token_journal(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSplTokenJournalRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSplTokenJournalRow>, std::string::String> {
) -> std::result::Result<crate::DemoSplTokenJournalPagePayload, std::string::String> {
return crate::demo_spl_token_journal(state, request).await;
}
@@ -882,7 +882,7 @@ async fn demo_execution_spl_ata_execute(
async fn demo_spl_ata_journal(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSplAtaJournalRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSplAtaJournalRow>, std::string::String> {
) -> std::result::Result<crate::DemoSplAtaJournalPagePayload, std::string::String> {
return crate::demo_spl_ata_journal(state, request).await;
}