v0.1.0-pre.053

This commit is contained in:
2026-07-25 23:57:48 +02:00
parent 930056d422
commit 4e76263f88
23 changed files with 4575 additions and 82 deletions

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/app_state.rs
// version: 5
// version: 6
//! Shared Tauri application state and startup initialization.
@@ -21,6 +21,8 @@ pub(crate) struct AppState {
demo_decode_replay_running: std::sync::atomic::AtomicBool,
demo_decode_replay_cancel_requested: std::sync::atomic::AtomicBool,
demo_decode_replay_campaign_id: std::sync::Mutex<std::option::Option<std::string::String>>,
demo_execution_solana_core_running: std::sync::atomic::AtomicBool,
demo_execution_solana_core_cancel_requested: std::sync::atomic::AtomicBool,
}
impl crate::AppState {
@@ -60,6 +62,8 @@ impl crate::AppState {
demo_decode_replay_running: std::sync::atomic::AtomicBool::new(false),
demo_decode_replay_cancel_requested: std::sync::atomic::AtomicBool::new(false),
demo_decode_replay_campaign_id: std::sync::Mutex::new(std::option::Option::None),
demo_execution_solana_core_running: std::sync::atomic::AtomicBool::new(false),
demo_execution_solana_core_cancel_requested: std::sync::atomic::AtomicBool::new(false),
});
}
@@ -152,6 +156,18 @@ impl crate::AppState {
return &self.demo_decode_replay_campaign_id;
}
/// Returns the shared execution running flag used by Solana and SPL windows.
pub(crate) fn demo_execution_solana_core_running(&self) -> &std::sync::atomic::AtomicBool {
return &self.demo_execution_solana_core_running;
}
/// Returns the shared execution cancellation flag used by Solana and SPL windows.
pub(crate) fn demo_execution_solana_core_cancel_requested(
&self,
) -> &std::sync::atomic::AtomicBool {
return &self.demo_execution_solana_core_cancel_requested;
}
/// Returns the number of logging routes held by the logging guard.
pub(crate) fn logging_route_count(&self) -> usize {
let lock_result = self.logging_guard.lock();

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_decode_replay.rs
// version: 24
// version: 25
//! Tauri commands and UI payloads for contextual instruction decode replay.
@@ -370,6 +370,7 @@ pub(crate) fn available_decoders()
-> std::vec::Vec<std::sync::Arc<dyn kb_lib::DcApiInstructionDecoder>> {
return std::vec![
std::sync::Arc::new(kb_lib::DcSolanaCoreDecoder),
std::sync::Arc::new(kb_lib::DcMetadataMetaplexTokenMetadataDecoder),
std::sync::Arc::new(kb_lib::DcSplAssociatedTokenAccountDecoder,),
std::sync::Arc::new(kb_lib::DcSplElgamalRegistryDecoder),
std::sync::Arc::new(kb_lib::DcSplMemoDecoder),
@@ -716,9 +717,9 @@ mod tests {
}
#[test]
fn native_memo_token_2022_elgamal_classic_token_and_ata_decoders_are_registered() {
fn native_memo_token2022_elgamal_classic_token_and_ata_decoders_are_registered() {
let decoders = crate::available_decoders();
assert_eq!(decoders.len(), 6);
assert_eq!(decoders.len(), 7);
let names = decoders
.iter()
.map(|decoder| return decoder.identity().name)
@@ -726,12 +727,13 @@ mod tests {
assert_eq!(
names,
std::vec![
"kb_decoder_metadata_metaplex_token_metadata".to_string(),
"solana_native_classifier".to_string(),
"spl_associated_token_account".to_string(),
"spl_elgamal_registry".to_string(),
"spl_memo".to_string(),
"spl_token".to_string(),
"spl_token_2022".to_string(),
"spl_token2022".to_string(),
]
);
}

View File

@@ -0,0 +1,669 @@
// file: kb-app-demo-desktop/src/demo_execution_solana_core.rs
// version: 5
//! Tauri adapter for bounded Solana Core execution on Devnet.
use tauri::Emitter; // rust-rules: trait-import
use ts_rs::TS; // rust-rules: derive-import
/// One Devnet execution profile exposed to the demo window.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionSolanaCoreProfileOption.ts"
)]
pub(crate) struct DemoExecutionSolanaCoreProfileOption {
/// Stable profile name.
pub(crate) name: std::string::String,
/// Non-secret temporary wallet alias.
pub(crate) wallet_alias: std::string::String,
/// Maximum Devnet spend allowed by the profile.
#[ts(type = "number")]
pub(crate) max_spend_lamports: u64,
/// Maximum faucet request allowed by the profile.
#[ts(type = "number")]
pub(crate) max_airdrop_lamports: u64,
/// Whether signed Devnet submission is enabled.
pub(crate) send_enabled: bool,
/// Whether explicit operator confirmation is required.
pub(crate) require_operator_confirmation: bool,
}
/// Initial options shown by the Solana Core execution demo.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionSolanaCoreOptionsPayload.ts"
)]
pub(crate) struct DemoExecutionSolanaCoreOptionsPayload {
/// Devnet profiles compatible with the execution laboratory.
pub(crate) profiles: std::vec::Vec<crate::DemoExecutionSolanaCoreProfileOption>,
/// Suggested profile name.
pub(crate) default_profile_name: std::option::Option<std::string::String>,
/// Default transfer amount suitable for a new zero-data account on Devnet.
#[ts(type = "number")]
pub(crate) default_transfer_lamports: u64,
/// Whether one execution is currently running.
pub(crate) running: bool,
}
/// Request sent by the execution demo.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionSolanaCoreRequest.ts"
)]
pub(crate) struct DemoExecutionSolanaCoreRequest {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Recipient public key.
pub(crate) recipient: std::string::String,
/// Lamports transferred by the System instruction.
#[ts(type = "number")]
pub(crate) lamports: u64,
/// Optional bounded faucet request when the source wallet is underfunded.
#[ts(type = "number")]
pub(crate) airdrop_lamports: u64,
/// Whether the transaction should be signed and submitted after simulation.
pub(crate) submit: bool,
/// Explicit operator confirmation for signed submission.
pub(crate) operator_confirmed: bool,
/// Whether post-execution core/decode outputs should be force-replayed.
pub(crate) force_post_validation_replay: bool,
/// Whether compatible materializers should run after decode replay.
pub(crate) materialize_after_decode: bool,
}
/// Request sent by the Memo v4 Devnet execution panel.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionMemoRequest.ts"
)]
pub(crate) struct DemoExecutionMemoRequest {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Exact UTF-8 Memo payload.
pub(crate) message: std::string::String,
/// Whether the wallet is supplied as a readonly Memo signer account.
pub(crate) include_wallet_as_memo_signer: bool,
/// Whether the transaction should be signed and submitted after simulation.
pub(crate) submit: bool,
/// Explicit operator confirmation for signed submission.
pub(crate) operator_confirmed: bool,
/// Whether post-execution core and first decode outputs should be force-replayed.
pub(crate) force_post_validation_replay: bool,
}
/// Public key generated for a disposable Devnet recipient.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionSolanaCoreGeneratedRecipientPayload.ts"
)]
pub(crate) struct DemoExecutionSolanaCoreGeneratedRecipientPayload {
/// Base58 public key. The private key is not persisted or exposed.
pub(crate) public_key: std::string::String,
}
/// Progress event emitted during execution and post-validation.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionSolanaCoreProgressPayload.ts"
)]
pub(crate) struct DemoExecutionSolanaCoreProgressPayload {
/// RFC 3339 timestamp.
pub(crate) timestamp: std::string::String,
/// Stable severity code.
pub(crate) level: std::string::String,
/// Stable stage code.
pub(crate) stage: std::string::String,
/// Human-readable message.
pub(crate) message: std::string::String,
/// Transaction signature when already available.
pub(crate) signature: std::option::Option<std::string::String>,
}
/// UI-safe result of one execution orchestration.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionSolanaCoreSummaryPayload.ts"
)]
pub(crate) struct DemoExecutionSolanaCoreSummaryPayload {
/// Profile used by the execution.
pub(crate) profile_name: std::string::String,
/// Classified cluster code.
pub(crate) cluster: std::string::String,
/// Genesis hash returned by the endpoint.
pub(crate) genesis_hash: std::string::String,
/// Source wallet public key.
pub(crate) wallet_public_key: std::string::String,
/// Recipient public key.
pub(crate) recipient: std::string::String,
/// Whether the recipient account existed before execution.
pub(crate) recipient_existed_before: bool,
/// Recipient balance before execution when present.
#[ts(type = "number | null")]
pub(crate) recipient_balance_before_lamports: std::option::Option<u64>,
/// Rent-exempt minimum required for a new zero-data account.
#[ts(type = "number")]
pub(crate) recipient_minimum_balance_lamports: u64,
/// Source balance before optional funding.
#[ts(type = "number")]
pub(crate) balance_before_lamports: u64,
/// Source balance after optional funding.
#[ts(type = "number")]
pub(crate) balance_after_funding_lamports: u64,
/// Estimated transaction fee.
#[ts(type = "number | null")]
pub(crate) fee_lamports: std::option::Option<u64>,
/// Whether exact simulation succeeded.
pub(crate) simulation_success: bool,
/// Runtime simulation error when present.
pub(crate) simulation_error: std::option::Option<std::string::String>,
/// Runtime simulation logs.
pub(crate) simulation_logs: std::vec::Vec<std::string::String>,
/// Faucet signature when funding was requested.
pub(crate) airdrop_signature: std::option::Option<std::string::String>,
/// Submitted transaction signature.
pub(crate) transaction_signature: std::option::Option<std::string::String>,
/// Terminal confirmation status.
pub(crate) confirmation_status: std::option::Option<std::string::String>,
/// Canonical rows inserted after submission.
#[ts(type = "number | null")]
pub(crate) canonical_inserted: std::option::Option<u64>,
/// Core transactions extracted after submission.
#[ts(type = "number | null")]
pub(crate) core_extracted: std::option::Option<u64>,
/// Contextual decode inputs completed after submission.
#[ts(type = "number | null")]
pub(crate) decode_completed: std::option::Option<u64>,
/// Contextual decode input failures after submission.
#[ts(type = "number | null")]
pub(crate) decode_failed_inputs: std::option::Option<u64>,
/// Pretty JSON representation of the exact execution plan.
pub(crate) plan_json: std::string::String,
/// Pretty JSON representation of the simulation result.
pub(crate) simulation_json: std::string::String,
/// Pretty JSON representation of confirmation and post-validation diagnostics.
pub(crate) diagnostics_json: std::string::String,
}
/// UI-safe result of one Memo v4 Devnet execution orchestration.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_solana_core/DemoExecutionMemoSummaryPayload.ts"
)]
pub(crate) struct DemoExecutionMemoSummaryPayload {
/// Profile used by the execution.
pub(crate) profile_name: std::string::String,
/// Classified cluster code.
pub(crate) cluster: std::string::String,
/// Genesis hash returned by the endpoint.
pub(crate) genesis_hash: std::string::String,
/// Source wallet public key.
pub(crate) wallet_public_key: std::string::String,
/// Exact wallet balance rendered without JSON integer precision loss.
pub(crate) balance_lamports: std::string::String,
/// Estimated transaction fee rendered without JSON integer precision loss.
pub(crate) fee_lamports: std::option::Option<std::string::String>,
/// Whether exact simulation succeeded.
pub(crate) simulation_success: bool,
/// Runtime simulation error when present.
pub(crate) simulation_error: std::option::Option<std::string::String>,
/// Submitted transaction signature.
pub(crate) transaction_signature: std::option::Option<std::string::String>,
/// Terminal confirmation status.
pub(crate) confirmation_status: std::option::Option<std::string::String>,
/// Whether canonical hydration was validated.
pub(crate) canonical_inserted: bool,
/// Whether core extraction was validated.
pub(crate) core_extracted: bool,
/// Whether Memo decode replay was validated.
pub(crate) decode_replayed: bool,
/// Whether the committed transaction annotation was validated.
pub(crate) materialized: bool,
/// Number of exact annotation rows returned by the bounded query.
pub(crate) annotation_count: u32,
/// Whether the second replay produced no failures or new materialized output.
pub(crate) idempotence_validated: bool,
/// Pretty JSON representation of the exact execution plan.
pub(crate) plan_json: std::string::String,
/// Pretty JSON representation of the simulation result.
pub(crate) simulation_json: std::string::String,
/// Pretty JSON representation of annotations and post-validation diagnostics.
pub(crate) diagnostics_json: std::string::String,
}
pub(crate) struct DemoExecutionSolanaCoreObserver<'a> {
pub(crate) app_handle: tauri::AppHandle,
pub(crate) cancel_requested: &'a std::sync::atomic::AtomicBool,
}
impl crate::DemoExecutionSolanaCoreObserver<'_> {
fn emit(
&self,
timestamp: std::string::String,
level: &str,
stage: &str,
message: std::string::String,
signature: std::option::Option<std::string::String>,
) {
let payload = crate::DemoExecutionSolanaCoreProgressPayload {
timestamp,
level: level.to_string(),
stage: stage.to_string(),
message,
signature,
};
let emit_result = self.app_handle.emit_to(
"demo_execution_solana_core",
"demo-execution-solana-core-progress",
payload,
);
if let std::result::Result::Err(error) = emit_result {
tracing::warn!(
target: crate::TRACING_TARGET,
action = "emit_execution_progress",
error = %error,
"cannot emit Solana Core execution progress"
);
}
}
fn cancelled(&self) -> bool {
return self.cancel_requested.load(std::sync::atomic::Ordering::Relaxed);
}
}
impl kb_pipeline::BackfillObserver for crate::DemoExecutionSolanaCoreObserver<'_> {
fn on_progress(&self, event: &kb_pipeline::BackfillProgressEvent) {
self.emit(
event.timestamp.clone(),
event.level.code(),
"canonical_insert",
event.message.clone(),
std::option::Option::None,
);
}
fn is_cancelled(&self) -> bool {
return self.cancelled();
}
}
impl kb_pipeline::CoreExtractionObserver for crate::DemoExecutionSolanaCoreObserver<'_> {
fn on_progress(&self, event: &kb_pipeline::CoreExtractionProgressEvent) {
self.emit(
event.timestamp.clone(),
event.level.code(),
"core_extraction",
event.message.clone(),
std::option::Option::None,
);
}
fn is_cancelled(&self) -> bool {
return self.cancelled();
}
}
impl kb_pipeline::DecodeReplayObserver for crate::DemoExecutionSolanaCoreObserver<'_> {
fn on_progress(&self, event: &kb_pipeline::DecodeReplayProgressEvent) {
self.emit(
event.timestamp.clone(),
event.level.code(),
"decode_replay",
event.message.clone(),
std::option::Option::None,
);
}
fn is_cancelled(&self) -> bool {
return self.cancelled();
}
}
impl kb_pipeline_demo_scenarios::SolanaExecutionObserver
for crate::DemoExecutionSolanaCoreObserver<'_>
{
fn on_execution_progress(
&self,
event: &kb_pipeline_demo_scenarios::SolanaExecutionProgressEvent,
) {
self.emit(
event.timestamp.clone(),
event.level.code(),
event.stage.as_str(),
event.message.clone(),
event.signature.clone(),
);
}
fn is_execution_cancelled(&self) -> bool {
return self.cancelled();
}
}
pub(crate) struct DemoExecutionSolanaCoreRunGuard<'a> {
pub(crate) running: &'a std::sync::atomic::AtomicBool,
}
impl std::ops::Drop for crate::DemoExecutionSolanaCoreRunGuard<'_> {
fn drop(&mut self) {
self.running.store(false, std::sync::atomic::Ordering::Release);
}
}
pub(crate) fn devnet_profile_options(
config: &kb_config::AppConfig,
) -> std::vec::Vec<crate::DemoExecutionSolanaCoreProfileOption> {
let mut output = std::vec::Vec::new();
for profile in &config.profiles {
if profile.wallet.cluster != "devnet"
|| !profile.wallet.temporary_wallet_enabled
|| !profile.wallet.temporary_wallet_persist
{
continue;
}
output.push(crate::DemoExecutionSolanaCoreProfileOption {
name: profile.name.clone(),
wallet_alias: profile.wallet.temporary_wallet_alias.clone(),
max_spend_lamports: profile.execution.devnet_max_spend_lamports,
max_airdrop_lamports: profile.execution.devnet_airdrop_max_lamports,
send_enabled: profile.wallet.devnet_send_enabled,
require_operator_confirmation: profile.execution.require_operator_confirmation,
});
}
return output;
}
pub(crate) fn select_devnet_profile(
config: &kb_config::AppConfig,
profile_name: &str,
) -> std::result::Result<kb_config::ProfileConfig, std::string::String> {
for profile in &config.profiles {
if profile.name == profile_name
&& profile.wallet.cluster == "devnet"
&& profile.wallet.temporary_wallet_enabled
&& profile.wallet.temporary_wallet_persist
{
return std::result::Result::Ok(profile.clone());
}
}
return std::result::Result::Err(format!(
"Devnet execution profile '{profile_name}' is unavailable"
));
}
pub(crate) fn demo_execution_solana_core_summary_payload(
summary: kb_pipeline_demo_scenarios::DevnetSystemTransferSummary,
) -> crate::DemoExecutionSolanaCoreSummaryPayload {
let plan_json = crate::pretty_json(&summary.plan);
let simulation_json = crate::pretty_json(&summary.simulation);
let transaction_signature =
summary.send_result.as_ref().map(|value| return value.signature.0.clone());
let confirmation_status = summary.confirmation.as_ref().map(|value| {
return crate::confirmation_status_code(value.status);
});
let canonical_inserted = summary.backfill.as_ref().map(|value| return value.canonical_inserted);
let core_extracted = summary.core_extraction.as_ref().map(|value| return value.extracted);
let decode_completed = summary.decode_replay.as_ref().map(|value| return value.completed);
let decode_failed_inputs =
summary.decode_replay.as_ref().map(|value| return value.failed_inputs);
let diagnostics_value = serde_json::json!({
"airdropConfirmation": summary.airdrop_confirmation.as_ref(),
"confirmation": summary.confirmation.as_ref(),
"postExecution": summary.post_execution.as_ref(),
"backfill": summary.backfill.as_ref().map(|value| {
return serde_json::json!({
"canonicalInserted": value.canonical_inserted,
"canonicalSkipped": value.canonical_skipped,
"existingSkipped": value.existing_skipped,
"missing": value.missing,
"failed": value.failed
});
}),
"coreExtraction": summary.core_extraction.as_ref().map(|value| {
return serde_json::json!({
"selected": value.selected,
"extracted": value.extracted,
"skipped": value.skipped,
"failed": value.failed
});
}),
"decodeReplay": summary.decode_replay.as_ref().map(|value| {
return serde_json::json!({
"campaignId": value.campaign_id,
"selected": value.selected,
"completed": value.completed,
"unmatched": value.unmatched,
"failedInputs": value.failed_inputs,
"cancelled": value.cancelled
});
})
});
let diagnostics_json = crate::pretty_json(&diagnostics_value);
let cluster = crate::execution_cluster_code(summary.cluster);
return crate::DemoExecutionSolanaCoreSummaryPayload {
profile_name: summary.profile_name,
cluster,
genesis_hash: summary.genesis_hash,
wallet_public_key: summary.wallet.public_key,
recipient: summary.recipient.0,
recipient_existed_before: summary.recipient_existed_before,
recipient_balance_before_lamports: summary.recipient_balance_before_lamports,
recipient_minimum_balance_lamports: summary.recipient_minimum_balance_lamports,
balance_before_lamports: summary.balance_before_lamports,
balance_after_funding_lamports: summary.balance_after_funding_lamports,
fee_lamports: summary.fee.fee_lamports,
simulation_success: summary.simulation.success,
simulation_error: summary.simulation.error,
simulation_logs: summary.simulation.logs,
airdrop_signature: summary.airdrop_signature.map(|value| return value.0),
transaction_signature,
confirmation_status,
canonical_inserted,
core_extracted,
decode_completed,
decode_failed_inputs,
plan_json,
simulation_json,
diagnostics_json,
};
}
pub(crate) fn demo_execution_solana_core_memo_summary_payload(
summary: kb_pipeline_demo_scenarios::DevnetMemoExecutionSummary,
) -> crate::DemoExecutionMemoSummaryPayload {
let plan_json = crate::pretty_json(&summary.plan);
let simulation_json = crate::pretty_json(&summary.simulation);
let transaction_signature =
summary.send_result.as_ref().map(|value| return value.signature.0.clone());
let confirmation_status = summary.confirmation.as_ref().map(|value| {
return crate::confirmation_status_code(value.status);
});
let canonical_inserted = summary
.post_execution
.as_ref()
.is_some_and(|value| return value.canonical_inserted);
let core_extracted =
summary.post_execution.as_ref().is_some_and(|value| return value.core_extracted);
let decode_replayed = summary
.post_execution
.as_ref()
.is_some_and(|value| return value.decode_replayed);
let materialized =
summary.post_execution.as_ref().is_some_and(|value| return value.materialized);
let idempotence_validated = summary.idempotence_replay.as_ref().is_some_and(|replay| {
return replay.failed_inputs == 0
&& !replay.cancelled
&& replay.processors.iter().all(|processor| {
return processor.failed == 0
&& processor.materialized_outputs == 0
&& processor.materialization_refused == 0;
})
&& replay.processors.iter().map(|processor| return processor.skipped).sum::<u64>()
>= 1;
});
let annotation_count = match u32::try_from(summary.annotations.len()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => u32::MAX,
};
let diagnostics_value = serde_json::json!({
"confirmation": summary.confirmation.as_ref(),
"postExecution": summary.post_execution.as_ref(),
"backfill": summary.backfill.as_ref().map(|value| {
return serde_json::json!({
"canonicalInserted": value.canonical_inserted,
"canonicalSkipped": value.canonical_skipped,
"existingSkipped": value.existing_skipped,
"missing": value.missing,
"failed": value.failed
});
}),
"coreExtraction": summary.core_extraction.as_ref().map(|value| {
return serde_json::json!({
"selected": value.selected,
"extracted": value.extracted,
"skipped": value.skipped,
"failed": value.failed
});
}),
"decodeReplay": summary.decode_replay.as_ref().map(|value| {
return serde_json::json!({
"campaignId": value.campaign_id,
"selected": value.selected,
"completed": value.completed,
"failedInputs": value.failed_inputs,
"processors": value.processors.iter().map(|processor| {
return serde_json::json!({
"name": processor.processor_name,
"version": processor.processor_version,
"decoded": processor.decoded,
"skipped": processor.skipped,
"failed": processor.failed,
"materializedOutputs": processor.materialized_outputs,
"materializationRefused": processor.materialization_refused
});
}).collect::<std::vec::Vec<_>>()
});
}),
"idempotenceReplay": summary.idempotence_replay.as_ref().map(|value| {
return serde_json::json!({
"campaignId": value.campaign_id,
"selected": value.selected,
"completed": value.completed,
"failedInputs": value.failed_inputs,
"processors": value.processors.iter().map(|processor| {
return serde_json::json!({
"name": processor.processor_name,
"version": processor.processor_version,
"decoded": processor.decoded,
"skipped": processor.skipped,
"failed": processor.failed,
"materializedOutputs": processor.materialized_outputs,
"materializationRefused": processor.materialization_refused
});
}).collect::<std::vec::Vec<_>>()
});
}),
"annotations": summary.annotations
});
let diagnostics_json = crate::pretty_json(&diagnostics_value);
return crate::DemoExecutionMemoSummaryPayload {
profile_name: summary.profile_name,
cluster: crate::execution_cluster_code(summary.cluster),
genesis_hash: summary.genesis_hash,
wallet_public_key: summary.wallet.public_key,
balance_lamports: summary.balance_lamports.to_string(),
fee_lamports: summary.fee.fee_lamports.map(|value| return value.to_string()),
simulation_success: summary.simulation.success,
simulation_error: summary.simulation.error,
transaction_signature,
confirmation_status,
canonical_inserted,
core_extracted,
decode_replayed,
materialized,
annotation_count,
idempotence_validated,
plan_json,
simulation_json,
diagnostics_json,
};
}
pub(crate) fn execution_cluster_code(
cluster: kb_lib::ExApiExecutionCluster,
) -> std::string::String {
return match cluster {
kb_lib::ExApiExecutionCluster::Localnet => "localnet".to_string(),
kb_lib::ExApiExecutionCluster::Devnet => "devnet".to_string(),
kb_lib::ExApiExecutionCluster::Testnet => "testnet".to_string(),
kb_lib::ExApiExecutionCluster::Mainnet => "mainnet".to_string(),
};
}
pub(crate) fn confirmation_status_code(
status: kb_lib::ExApiExecutionConfirmationStatus,
) -> std::string::String {
return match status {
kb_lib::ExApiExecutionConfirmationStatus::Processed => "processed".to_string(),
kb_lib::ExApiExecutionConfirmationStatus::Confirmed => "confirmed".to_string(),
kb_lib::ExApiExecutionConfirmationStatus::Finalized => "finalized".to_string(),
kb_lib::ExApiExecutionConfirmationStatus::Failed => "failed".to_string(),
kb_lib::ExApiExecutionConfirmationStatus::Expired => "expired".to_string(),
kb_lib::ExApiExecutionConfirmationStatus::TimedOut => "timed_out".to_string(),
};
}
pub(crate) fn pretty_json<T>(value: &T) -> std::string::String
where
T: serde::Serialize,
{
return match serde_json::to_string_pretty(value) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
serde_json::json!({"serializationError": error.to_string()}).to_string()
},
};
}
#[cfg(test)]
mod tests {
#[test]
fn example_config_exposes_one_devnet_execution_profile() {
let config =
match kb_config::parse_config_json(include_str!("../../config/example.config.json")) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("example config parse failed: {error}"),
};
let profiles = crate::devnet_profile_options(&config);
assert_eq!(profiles.len(), 1);
assert_eq!(profiles[0].name, "local_devnet");
assert!(profiles[0].send_enabled);
assert!(profiles[0].max_spend_lamports >= 1_000_000);
}
#[test]
fn profile_selection_rejects_mainnet_profiles() {
let config =
match kb_config::parse_config_json(include_str!("../../config/example.config.json")) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("example config parse failed: {error}"),
};
assert!(crate::select_devnet_profile(&config, "local_devnet").is_ok());
assert!(crate::select_devnet_profile(&config, "mainnet").is_err());
}
}

View File

@@ -0,0 +1,71 @@
// file: kb-app-demo-desktop/src/demo_execution_spl.rs
// version: 3
//! Dedicated Tauri window for bounded SPL execution on Devnet.
/// Frontend payload for one independent Devnet SPL validation scenario.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ts_rs::TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_execution_spl/DevnetSplValidationScenarioPayload.ts"
)]
pub(crate) struct DevnetSplValidationScenarioPayload {
/// Stable scenario identifier.
pub id: std::string::String,
/// Operator-visible label.
pub label: std::string::String,
/// Stable family code.
pub family: std::string::String,
/// Stable executor operation code.
pub operation_code: std::string::String,
/// Current implementation status.
pub implementation_status: std::string::String,
/// Whether the scenario requires proof material.
pub proof_required: bool,
/// Ordered required fixture variables.
pub required_fixture_variables: std::vec::Vec<std::string::String>,
}
#[cfg(test)]
mod tests {
#[test]
fn memo_summary_keeps_lamports_as_json_strings() {
let payload = crate::DemoExecutionMemoSummaryPayload {
profile_name: "local_devnet".to_string(),
cluster: "devnet".to_string(),
genesis_hash: "EtWTRABZaYq6iMfeYKouRu166VU2xqa1".to_string(),
wallet_public_key: kb_program_ids::SYSTEM_PROGRAM_ID.to_string(),
balance_lamports: u64::MAX.to_string(),
fee_lamports: std::option::Option::Some(u64::MAX.to_string()),
simulation_success: true,
simulation_error: std::option::Option::None,
transaction_signature: std::option::Option::None,
confirmation_status: std::option::Option::None,
canonical_inserted: false,
core_extracted: false,
decode_replayed: false,
materialized: false,
annotation_count: 0,
idempotence_validated: false,
plan_json: "{}".to_string(),
simulation_json: "{}".to_string(),
diagnostics_json: "{}".to_string(),
};
let json = match serde_json::to_value(payload) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
assert_eq!(
std::option::Option::Some(error.to_string()),
std::option::Option::None,
"Memo summary serialization failed"
);
return;
},
};
assert!(json["balanceLamports"].is_string());
assert!(json["feeLamports"].is_string());
assert_eq!(json["balanceLamports"], u64::MAX.to_string());
}
}

View File

@@ -0,0 +1,438 @@
// file: kb-app-demo-desktop/src/demo_spl_ata.rs
// version: 4
//! Thin Tauri adapter for ATA execution, derivation and lifecycle journal reads.
use ts_rs::TS; // rust-rules: derive-import
/// Request for one representative ATA creation on Devnet.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_ata/DemoExecutionSplAtaRequest.ts"
)]
pub(crate) struct DemoExecutionSplAtaRequest {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Wallet owner used by canonical derivation.
pub(crate) wallet_owner: std::string::String,
/// Mint account.
pub(crate) mint: std::string::String,
/// `classic` or `token2022`.
pub(crate) token_program: std::string::String,
/// `create` or `create_idempotent`.
pub(crate) mode: std::string::String,
/// Whether to sign and submit after simulation.
pub(crate) submit: bool,
/// Explicit operator confirmation.
pub(crate) operator_confirmed: bool,
/// Whether post-execution outputs should be force-replayed.
pub(crate) force_post_validation_replay: bool,
}
/// Request used to derive the representative wallet ATA before execution.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_ata/DemoSplAtaDerivationRequest.ts"
)]
pub(crate) struct DemoSplAtaDerivationRequest {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Mint account.
pub(crate) mint: std::string::String,
/// `classic` or `token2022`.
pub(crate) token_program: std::string::String,
}
/// Readonly payer, wallet, Token Program and derived ATA values.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_ata/DemoSplAtaDerivationPayload.ts"
)]
pub(crate) struct DemoSplAtaDerivationPayload {
/// Profile wallet used as payer.
pub(crate) payer: std::string::String,
/// Wallet owner selected by the representative panel.
pub(crate) wallet_owner: std::string::String,
/// Exact Token Program ID.
pub(crate) token_program_id: std::string::String,
/// Canonically derived ATA.
pub(crate) associated_token_account: std::string::String,
}
/// UI-safe ATA execution result.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_ata/DemoExecutionSplAtaSummaryPayload.ts"
)]
pub(crate) struct DemoExecutionSplAtaSummaryPayload {
/// Stable operation code.
pub(crate) operation: std::string::String,
/// Profile name.
pub(crate) profile_name: std::string::String,
/// Profile wallet public key.
pub(crate) wallet_public_key: std::string::String,
/// Target Token Program ID.
pub(crate) token_program_id: std::string::String,
/// Derived ATA from the exact plan.
pub(crate) associated_token_account: std::string::String,
/// Wallet balance as lossless JSON text.
pub(crate) balance_lamports: std::string::String,
/// Fee estimate as lossless JSON text.
pub(crate) fee_lamports: std::option::Option<std::string::String>,
/// Aggregate stateful readiness.
pub(crate) readiness_status: std::string::String,
/// Exact simulation outcome.
pub(crate) simulation_success: bool,
/// Runtime simulation error.
pub(crate) simulation_error: std::option::Option<std::string::String>,
/// Submitted signature.
pub(crate) transaction_signature: std::option::Option<std::string::String>,
/// Terminal confirmation status.
pub(crate) confirmation_status: std::option::Option<std::string::String>,
/// Number of ATA-owned materialized facts.
pub(crate) materialization_count: u32,
/// Whether the second replay created no output.
pub(crate) idempotence_validated: bool,
/// Exact plan JSON.
pub(crate) plan_json: std::string::String,
/// Stateful readiness JSON.
pub(crate) readiness_json: std::string::String,
/// Simulation JSON.
pub(crate) simulation_json: std::string::String,
/// Confirmation and replay diagnostics JSON.
pub(crate) diagnostics_json: std::string::String,
}
/// Bounded ATA lifecycle journal request.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_ata/DemoSplAtaJournalRequest.ts"
)]
pub(crate) struct DemoSplAtaJournalRequest {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Optional partial signature.
pub(crate) signature_contains: std::option::Option<std::string::String>,
/// Optional exact mint.
pub(crate) mint: std::option::Option<std::string::String>,
/// Optional exact ATA.
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,
}
/// One UI-safe ATA lifecycle journal row.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_ata/DemoSplAtaJournalRow.ts"
)]
pub(crate) struct DemoSplAtaJournalRow {
/// Transaction signature.
pub(crate) signature: std::string::String,
/// Slot as lossless JSON text.
pub(crate) slot: std::string::String,
/// Materialized family.
pub(crate) family: std::string::String,
/// Lifecycle operation.
pub(crate) operation: std::option::Option<std::string::String>,
/// Exact mint when present.
pub(crate) mint: std::option::Option<std::string::String>,
/// Exact ATA when present.
pub(crate) associated_token_account: std::option::Option<std::string::String>,
/// Full bounded payload JSON.
pub(crate) payload_json: std::string::String,
}
pub(crate) async fn load_profile_wallet(
profile: &kb_config::ProfileConfig,
) -> std::result::Result<kb_wallet::TemporaryWallet, std::string::String> {
let configured = std::path::PathBuf::from(profile.wallet.wallet_dir.as_str());
let directory = if configured.is_absolute() {
configured
} else {
crate::workspace_root_dir().join(configured)
};
let store = match kb_wallet::TemporaryWalletStore::new(directory) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let alias = match kb_wallet::WalletAlias::parse(profile.wallet.temporary_wallet_alias.clone()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
return match store.load_or_create(alias).await {
std::result::Result::Ok(value) => std::result::Result::Ok(value),
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
pub(crate) fn parse_token_program(
value: &str,
) -> std::result::Result<kb_lib::ExSplAssociatedTokenProgram, std::string::String> {
return match value.trim() {
"classic" => std::result::Result::Ok(kb_lib::ExSplAssociatedTokenProgram::Classic),
"token2022" => std::result::Result::Ok(kb_lib::ExSplAssociatedTokenProgram::Token2022),
_ => std::result::Result::Err("Token Program must be classic or token2022".to_string()),
};
}
pub(crate) fn derive_ata(
wallet: &str,
mint: &str,
token_program: &str,
) -> std::result::Result<std::string::String, std::string::String> {
let wallet: solana_pubkey::Pubkey = match wallet.parse() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(format!("invalid wallet: {error}"));
},
};
let mint: solana_pubkey::Pubkey = match mint.parse() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(format!("invalid mint: {error}"));
},
};
let token_program: solana_pubkey::Pubkey = match token_program.parse() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(format!("invalid Token Program: {error}"));
},
};
return std::result::Result::Ok(
spl_associated_token_account_interface::address::get_associated_token_address_with_program_id(
&wallet,
&mint,
&token_program,
)
.to_string(),
);
}
pub(crate) fn demo_spl_ata_summary_payload(
summary: kb_pipeline_demo_scenarios::DevnetSplAssociatedTokenAccountExecutionSummary,
) -> crate::DemoExecutionSplAtaSummaryPayload {
let (associated_token_account, token_program_id) = match summary.plan.instructions.first() {
std::option::Option::Some(instruction) => {
let ata = match instruction.accounts.get(1) {
std::option::Option::Some(account) => account.pubkey.0.clone(),
std::option::Option::None => std::string::String::new(),
};
let token_program = match instruction.accounts.last() {
std::option::Option::Some(account) => account.pubkey.0.clone(),
std::option::Option::None => std::string::String::new(),
};
(ata, token_program)
},
std::option::Option::None => (std::string::String::new(), std::string::String::new()),
};
let transaction_signature =
summary.send_result.as_ref().map(|value| return value.signature.0.clone());
let confirmation_status = summary.confirmation.as_ref().map(|value| {
return crate::confirmation_status_code(value.status);
});
let idempotence_validated = summary.idempotence_replay.as_ref().is_some_and(|replay| {
return replay.failed_inputs == 0
&& replay.processors.iter().all(|processor| {
return processor.failed == 0
&& processor.materialized_outputs == 0
&& processor.materialization_refused == 0;
});
});
let materialization_count = match u32::try_from(summary.materializations.len()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => u32::MAX,
};
let diagnostics = serde_json::json!({
"confirmation": summary.confirmation.as_ref(),
"postStateValidation": summary.post_state_validation.as_ref(),
"postExecution": summary.post_execution.as_ref(),
"backfill": summary.backfill.as_ref().map(|value| {
return serde_json::json!({
"candidatesCompleted": value.candidates_completed,
"candidatesCancelled": value.candidates_cancelled,
"candidatesNotStarted": value.candidates_not_started,
"canonicalInserted": value.canonical_inserted,
"canonicalSkipped": value.canonical_skipped,
"existingSkipped": value.existing_skipped,
"missing": value.missing,
"failed": value.failed
});
}),
"coreExtraction": summary.core_extraction.as_ref().map(|value| {
return serde_json::json!({
"selected": value.selected,
"extracted": value.extracted,
"skipped": value.skipped,
"failed": value.failed,
"cancelled": value.cancelled
});
}),
"decodeReplay": summary.decode_replay.as_ref().map(|value| {
return serde_json::json!({
"campaignId": value.campaign_id,
"selected": value.selected,
"completed": value.completed,
"unmatched": value.unmatched,
"failedInputs": value.failed_inputs,
"cancelled": value.cancelled
});
}),
"idempotenceReplay": summary.idempotence_replay.as_ref().map(|value| {
return serde_json::json!({
"campaignId": value.campaign_id,
"selected": value.selected,
"completed": value.completed,
"unmatched": value.unmatched,
"failedInputs": value.failed_inputs,
"cancelled": value.cancelled,
"materializedOutputs": value.processors.iter().map(|processor| {
return processor.materialized_outputs;
}).sum::<u64>(),
"materializationRefused": value.processors.iter().map(|processor| {
return processor.materialization_refused;
}).sum::<u64>()
});
}),
"materializations": summary.materializations.iter().map(|value| {
return serde_json::json!({
"processorName": value.processor_name,
"outputKey": value.output_key,
"family": value.materialized_family,
"signature": value.signature,
"slot": value.slot.to_string(),
"payload": value.payload_json
});
}).collect::<std::vec::Vec<_>>()
});
let plan_json = crate::pretty_json(&summary.plan);
let readiness_json = crate::pretty_json(&summary.stateful_readiness);
let simulation_json = crate::pretty_json(&summary.simulation);
let diagnostics_json = crate::pretty_json(&diagnostics);
return crate::DemoExecutionSplAtaSummaryPayload {
operation: summary.stateful_readiness.operation_code,
profile_name: summary.profile_name,
wallet_public_key: summary.wallet.public_key,
token_program_id,
associated_token_account,
balance_lamports: summary.balance_lamports.to_string(),
fee_lamports: summary.fee.fee_lamports.map(|value| return value.to_string()),
readiness_status: match summary.stateful_readiness.status {
kb_pipeline::SplAssociatedTokenAccountStatefulReadinessStatus::Ready => {
"ready".to_string()
},
kb_pipeline::SplAssociatedTokenAccountStatefulReadinessStatus::Blocked => {
"blocked".to_string()
},
},
simulation_success: summary.simulation.success,
simulation_error: summary.simulation.error,
transaction_signature,
confirmation_status,
materialization_count,
idempotence_validated,
plan_json,
readiness_json,
simulation_json,
diagnostics_json,
};
}
pub(crate) fn journal_matches(
payload: &serde_json::Value,
request: &crate::DemoSplAtaJournalRequest,
) -> bool {
for (expected, key) in [
(&request.operation, "operation"),
(&request.mint, "mint"),
(&request.associated_token_account, "associatedTokenAccount"),
] {
if expected.as_ref().is_some_and(|value| {
return payload.get(key).and_then(serde_json::Value::as_str)
!= std::option::Option::Some(value.as_str());
}) {
return false;
}
}
return true;
}
pub(crate) fn journal_row(row: kb_store::MaterializedEventQueryRow) -> crate::DemoSplAtaJournalRow {
let text = |key: &str| {
return row
.payload_json
.get(key)
.and_then(serde_json::Value::as_str)
.map(std::string::ToString::to_string);
};
let operation = text("operation");
let mint = text("mint");
let associated_token_account = text("associatedTokenAccount");
let payload_json = crate::pretty_json(&row.payload_json);
return crate::DemoSplAtaJournalRow {
signature: row.signature,
slot: row.slot.to_string(),
family: row.materialized_family,
operation,
mint,
associated_token_account,
payload_json,
};
}
#[cfg(test)]
mod tests {
#[test]
fn classic_and_token2022_derivations_are_distinct_and_canonical() {
let wallet = kb_program_ids::SYSTEM_PROGRAM_ID;
let mint = "So11111111111111111111111111111111111111112";
let classic = crate::derive_ata(wallet, mint, kb_program_ids::SPL_TOKEN_PROGRAM_ID)
.unwrap_or_else(|error| panic!("classic derivation failed: {error}"));
let token2022 = crate::derive_ata(wallet, mint, kb_program_ids::SPL_TOKEN2022_PROGRAM_ID)
.unwrap_or_else(|error| panic!("Token-2022 derivation failed: {error}"));
assert_eq!(classic, "aqxoAhCwpy3oB1BpNw9hL1HdLYLgPpbPjzxDrrQj3Fs");
assert_eq!(token2022, "2sZUUBGq1i6aE47ZoxCaCW89jmYm2EXLPPmNMgMDXHMS");
}
#[test]
fn lifecycle_journal_filters_are_exact() {
let request = crate::DemoSplAtaJournalRequest {
profile_name: "local_devnet".to_string(),
signature_contains: std::option::Option::None,
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,
};
assert!(crate::journal_matches(
&serde_json::json!({
"operation": "create_idempotent",
"mint": "mint111",
"associatedTokenAccount": "ata111"
}),
&request,
));
assert!(!crate::journal_matches(
&serde_json::json!({
"operation": "create",
"mint": "mint111",
"associatedTokenAccount": "ata111"
}),
&request,
));
}
}

View File

@@ -0,0 +1,493 @@
// file: kb-app-demo-desktop/src/demo_spl_token.rs
// version: 2
//! Thin Tauri adapter for classic SPL Token execution and materialized journals.
use ts_rs::TS; // rust-rules: derive-import
/// Request for one checked classic SPL Token transfer on Devnet.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token/DemoExecutionSplTokenRequest.ts"
)]
pub(crate) struct DemoExecutionSplTokenRequest {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Source token account.
pub(crate) source: std::string::String,
/// Exact mint account carried by `TransferChecked`.
pub(crate) mint: std::string::String,
/// Destination token account.
pub(crate) destination: std::string::String,
/// Simple authority resolved by the selected profile wallet.
pub(crate) authority: std::string::String,
/// Exact raw amount represented as a decimal string.
pub(crate) amount_raw: std::string::String,
/// Expected mint decimals carried by the wire.
pub(crate) decimals: u8,
/// Whether the transaction should be signed and submitted after simulation.
pub(crate) submit: bool,
/// Explicit operator confirmation for signed submission.
pub(crate) operator_confirmed: bool,
/// Whether post-execution core and decode outputs should be force-replayed.
pub(crate) force_post_validation_replay: bool,
}
/// UI-safe result of one checked SPL Token transfer orchestration.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token/DemoExecutionSplTokenSummaryPayload.ts"
)]
pub(crate) struct DemoExecutionSplTokenSummaryPayload {
/// Stable operation code.
pub(crate) operation: std::string::String,
/// Profile used by the orchestration.
pub(crate) profile_name: std::string::String,
/// Classified cluster code.
pub(crate) cluster: std::string::String,
/// Genesis hash returned by the endpoint.
pub(crate) genesis_hash: std::string::String,
/// Source wallet public key.
pub(crate) wallet_public_key: std::string::String,
/// Exact wallet balance rendered without JSON integer precision loss.
pub(crate) balance_lamports: std::string::String,
/// Estimated fee rendered without JSON integer precision loss.
pub(crate) fee_lamports: std::option::Option<std::string::String>,
/// Exact raw token amount.
pub(crate) amount_raw: std::string::String,
/// Expected mint decimals.
pub(crate) decimals: u8,
/// Aggregate stateful preflight status.
pub(crate) readiness_status: std::string::String,
/// Whether exact simulation succeeded.
pub(crate) simulation_success: bool,
/// Runtime simulation error when present.
pub(crate) simulation_error: std::option::Option<std::string::String>,
/// Submitted transaction signature.
pub(crate) transaction_signature: std::option::Option<std::string::String>,
/// Terminal confirmation status.
pub(crate) confirmation_status: std::option::Option<std::string::String>,
/// Whether canonical hydration was validated.
pub(crate) canonical_inserted: bool,
/// Whether core extraction was validated.
pub(crate) core_extracted: bool,
/// Whether SPL Token decode replay was validated.
pub(crate) decode_replayed: bool,
/// Number of materialized rows for the submitted instruction.
pub(crate) materialization_count: u32,
/// Whether the second replay produced no failure or new output.
pub(crate) idempotence_validated: bool,
/// Pretty JSON representation of the exact execution plan.
pub(crate) plan_json: std::string::String,
/// Pretty JSON representation of stateful readiness.
pub(crate) readiness_json: std::string::String,
/// Pretty JSON representation of the exact simulation result.
pub(crate) simulation_json: std::string::String,
/// Pretty JSON representation of confirmation and replay diagnostics.
pub(crate) diagnostics_json: std::string::String,
}
/// Bounded exact filters for the classic SPL Token materialized journal.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token/DemoSplTokenJournalRequest.ts"
)]
pub(crate) struct DemoSplTokenJournalRequest {
/// Devnet profile whose PostgreSQL store is queried.
pub(crate) profile_name: std::string::String,
/// Optional partial signature handled by the bounded store query.
pub(crate) signature_contains: std::option::Option<std::string::String>,
/// Optional exact mint account.
pub(crate) mint: std::option::Option<std::string::String>,
/// Optional exact account occurring in the ordered account list.
pub(crate) account: std::option::Option<std::string::String>,
/// Optional exact materialized family.
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,
}
/// UI-safe materialized classic SPL Token journal row.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token/DemoSplTokenJournalRow.ts"
)]
pub(crate) struct DemoSplTokenJournalRow {
/// Materializer processor name.
pub(crate) processor_name: std::string::String,
/// Materializer processor version.
pub(crate) processor_version: std::string::String,
/// Stable processor-owned output key.
pub(crate) output_key: std::string::String,
/// Transaction signature.
pub(crate) signature: std::string::String,
/// Decimal slot rendered as text to preserve JSON precision.
pub(crate) slot: std::string::String,
/// Materialized family code.
pub(crate) family: std::string::String,
/// Exact operation when present.
pub(crate) operation: std::option::Option<std::string::String>,
/// Exact mint account when explicitly available.
pub(crate) mint: std::option::Option<std::string::String>,
/// Exact raw amount when carried by the materialized fact.
pub(crate) amount_raw: std::option::Option<std::string::String>,
/// Stable outer or inner instruction path when present.
pub(crate) instruction_path: std::option::Option<std::string::String>,
/// Ordered account keys preserved by the decoder.
pub(crate) account_keys: std::vec::Vec<std::string::String>,
/// Complete bounded typed payload rendered as JSON text.
pub(crate) payload_json: std::string::String,
/// Database creation timestamp.
pub(crate) created_at: std::string::String,
/// Database replacement timestamp.
pub(crate) updated_at: std::string::String,
}
pub(crate) fn demo_spl_token_summary_payload(
summary: kb_pipeline_demo_scenarios::DevnetSplTokenExecutionSummary,
amount_raw: std::string::String,
decimals: u8,
) -> crate::DemoExecutionSplTokenSummaryPayload {
let plan_json = crate::pretty_json(&summary.plan);
let readiness_json = crate::pretty_json(&summary.stateful_readiness);
let simulation_json = crate::pretty_json(&summary.simulation);
let transaction_signature =
summary.send_result.as_ref().map(|value| return value.signature.0.clone());
let confirmation_status = summary.confirmation.as_ref().map(|value| {
return crate::confirmation_status_code(value.status);
});
let post_execution = summary.post_execution.as_ref();
let canonical_inserted = post_execution.is_some_and(|value| return value.canonical_inserted);
let core_extracted = post_execution.is_some_and(|value| return value.core_extracted);
let decode_replayed = post_execution.is_some_and(|value| return value.decode_replayed);
let idempotence_validated = summary.idempotence_replay.as_ref().is_some_and(|replay| {
return replay.failed_inputs == 0
&& !replay.cancelled
&& replay.processors.iter().all(|processor| {
return processor.failed == 0
&& processor.materialized_outputs == 0
&& processor.materialization_refused == 0;
});
});
let materialization_count = match u32::try_from(summary.materializations.len()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => u32::MAX,
};
let diagnostics = serde_json::json!({
"confirmation": summary.confirmation,
"postExecution": summary.post_execution,
"backfill": summary.backfill.as_ref().map(|value| {
return serde_json::json!({
"canonicalInserted": value.canonical_inserted,
"canonicalSkipped": value.canonical_skipped,
"existingSkipped": value.existing_skipped,
"missing": value.missing,
"failed": value.failed
});
}),
"coreExtraction": summary.core_extraction.as_ref().map(|value| {
return serde_json::json!({
"selected": value.selected,
"extracted": value.extracted,
"skipped": value.skipped,
"failed": value.failed,
"cancelled": value.cancelled
});
}),
"decodeReplay": summary.decode_replay.as_ref().map(|value| {
return replay_diagnostics(value);
}),
"idempotenceReplay": summary.idempotence_replay.as_ref().map(|value| {
return replay_diagnostics(value);
}),
"materializations": summary.materializations
});
return crate::DemoExecutionSplTokenSummaryPayload {
operation: summary.stateful_readiness.operation_code,
profile_name: summary.profile_name,
cluster: crate::execution_cluster_code(summary.cluster),
genesis_hash: summary.genesis_hash,
wallet_public_key: summary.wallet.public_key,
balance_lamports: summary.balance_lamports.to_string(),
fee_lamports: summary.fee.fee_lamports.map(|value| return value.to_string()),
amount_raw,
decimals,
readiness_status: match summary.stateful_readiness.status {
kb_pipeline::SplTokenStatefulReadinessStatus::Ready => "ready".to_string(),
kb_pipeline::SplTokenStatefulReadinessStatus::Blocked => "blocked".to_string(),
},
simulation_success: summary.simulation.success,
simulation_error: summary.simulation.error,
transaction_signature,
confirmation_status,
canonical_inserted,
core_extracted,
decode_replayed,
materialization_count,
idempotence_validated,
plan_json,
readiness_json,
simulation_json,
diagnostics_json: crate::pretty_json(&diagnostics),
};
}
fn replay_diagnostics(summary: &kb_pipeline::DecodeReplaySummary) -> serde_json::Value {
return serde_json::json!({
"campaignId": summary.campaign_id,
"selected": summary.selected,
"completed": summary.completed,
"failedInputs": summary.failed_inputs,
"cancelled": summary.cancelled,
"processors": summary.processors.iter().map(|processor| {
return serde_json::json!({
"name": processor.processor_name,
"version": processor.processor_version,
"decoded": processor.decoded,
"skipped": processor.skipped,
"failed": processor.failed,
"materializedOutputs": processor.materialized_outputs,
"materializationRefused": processor.materialization_refused
});
}).collect::<std::vec::Vec<_>>()
});
}
pub(crate) fn validate_journal_request(
request: crate::DemoSplTokenJournalRequest,
) -> std::result::Result<crate::DemoSplTokenJournalRequest, std::string::String> {
if request.limit == 0 || request.limit > kb_store::MAX_MATERIALIZED_EVENT_QUERY_ROWS {
return std::result::Result::Err(format!(
"journal limit must be between 1 and {}",
kb_store::MAX_MATERIALIZED_EVENT_QUERY_ROWS
));
}
if request.profile_name.trim().is_empty() {
return std::result::Result::Err("journal profile name must not be empty".to_string());
}
let signature_contains =
match bounded_optional(request.signature_contains, "signature filter", 128) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mint = match bounded_optional(request.mint, "mint filter", 64) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let account = match bounded_optional(request.account, "account filter", 64) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let operation = match bounded_optional(request.operation, "operation filter", 64) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let family = match bounded_optional(request.family, "family filter", 32) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
if family.as_ref().is_some_and(|value| {
return !matches!(value.as_str(), "token_account" | "admin" | "risk");
}) {
return std::result::Result::Err(
"journal family must be token_account, admin or risk".to_string(),
);
}
return std::result::Result::Ok(crate::DemoSplTokenJournalRequest {
profile_name: request.profile_name.trim().to_string(),
signature_contains,
mint,
account,
family,
operation,
limit: request.limit,
});
}
fn bounded_optional(
value: std::option::Option<std::string::String>,
label: &str,
maximum_length: usize,
) -> std::result::Result<std::option::Option<std::string::String>, std::string::String> {
let trimmed = value.map(|text| return text.trim().to_string());
let trimmed = trimmed.filter(|text| return !text.is_empty());
if trimmed.as_ref().is_some_and(|text| return text.len() > maximum_length) {
return std::result::Result::Err(format!("{label} must not exceed {maximum_length} bytes"));
}
return std::result::Result::Ok(trimmed);
}
pub(crate) fn payload_matches(
payload: &serde_json::Value,
request: &crate::DemoSplTokenJournalRequest,
) -> bool {
if request.operation.as_ref().is_some_and(|expected| {
return payload.get("operation").and_then(serde_json::Value::as_str)
!= std::option::Option::Some(expected.as_str());
}) {
return false;
}
if request.mint.as_ref().is_some_and(|expected| {
return payload_mint(payload).as_deref() != std::option::Option::Some(expected.as_str());
}) {
return false;
}
if request.account.as_ref().is_some_and(|expected| {
return !payload_account_keys(payload).iter().any(|value| return value == expected);
}) {
return false;
}
return true;
}
pub(crate) fn demo_spl_token_journal_row(
row: kb_store::MaterializedEventQueryRow,
) -> DemoSplTokenJournalRow {
let operation = row
.payload_json
.get("operation")
.and_then(serde_json::Value::as_str)
.map(std::string::ToString::to_string);
let amount_raw = row
.payload_json
.get("amountRaw")
.or_else(|| {
return row
.payload_json
.get("parameters")
.and_then(|value| return value.get("amountRaw"));
})
.and_then(serde_json::Value::as_str)
.map(std::string::ToString::to_string);
let instruction_path = row
.payload_json
.get("instructionPath")
.and_then(serde_json::Value::as_str)
.map(std::string::ToString::to_string);
let payload_json = crate::pretty_json(&row.payload_json);
return DemoSplTokenJournalRow {
processor_name: row.processor_name,
processor_version: row.processor_version,
output_key: row.output_key,
signature: row.signature,
slot: row.slot.to_string(),
family: row.materialized_family,
operation,
mint: payload_mint(&row.payload_json),
amount_raw,
instruction_path,
account_keys: payload_account_keys(&row.payload_json),
payload_json,
created_at: row.created_at,
updated_at: row.updated_at,
};
}
fn payload_mint(payload: &serde_json::Value) -> std::option::Option<std::string::String> {
let direct = payload.get("mint").and_then(serde_json::Value::as_str);
if let std::option::Option::Some(value) = direct {
return std::option::Option::Some(value.to_string());
}
return payload.get("accounts").and_then(serde_json::Value::as_array).and_then(|rows| {
return rows.iter().find_map(|row| {
if row.get("role").and_then(serde_json::Value::as_str)
!= std::option::Option::Some("mint")
{
return std::option::Option::None;
}
return row
.get("accountKey")
.and_then(serde_json::Value::as_str)
.map(std::string::ToString::to_string);
});
});
}
fn payload_account_keys(payload: &serde_json::Value) -> std::vec::Vec<std::string::String> {
let values = payload.get("accounts").and_then(serde_json::Value::as_array).map(|rows| {
return rows
.iter()
.filter_map(|row| {
return row
.get("accountKey")
.and_then(serde_json::Value::as_str)
.map(std::string::ToString::to_string);
})
.collect();
});
return match values {
std::option::Option::Some(values) => values,
std::option::Option::None => std::vec::Vec::new(),
};
}
#[cfg(test)]
mod tests {
#[test]
fn journal_filters_are_exact_bounded_and_preserve_raw_amounts() {
let request = crate::DemoSplTokenJournalRequest {
profile_name: "local_devnet".to_string(),
signature_contains: std::option::Option::None,
mint: std::option::Option::Some("mint111".to_string()),
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,
};
let payload = serde_json::json!({
"operation": "transfer_checked",
"mint": "mint111",
"amountRaw": "18446744073709551615",
"accounts": [
{"role": "source", "accountKey": "source111"},
{"role": "mint", "accountKey": "mint111"}
]
});
assert!(crate::payload_matches(&payload, &request));
assert_eq!(
payload.get("amountRaw").and_then(serde_json::Value::as_str),
std::option::Option::Some("18446744073709551615")
);
let row = crate::demo_spl_token_journal_row(kb_store::MaterializedEventQueryRow {
processor_name: "spl_token_accounts".to_string(),
processor_version: "0.4.4".to_string(),
input_key: "input".to_string(),
output_key: "output".to_string(),
source_event_key: "event".to_string(),
source_decoder_name: "spl_token".to_string(),
source_decoder_version: "0.4.4".to_string(),
signature: "signature".to_string(),
slot: u64::MAX,
materialized_family: "token_account".to_string(),
payload_json: payload,
created_at: "created".to_string(),
updated_at: "updated".to_string(),
});
assert_eq!(row.slot, u64::MAX.to_string());
assert_eq!(row.amount_raw, std::option::Option::Some(u64::MAX.to_string()));
}
#[test]
fn journal_rejects_unbounded_or_unknown_family_requests() {
let request = crate::DemoSplTokenJournalRequest {
profile_name: "local_devnet".to_string(),
signature_contains: std::option::Option::None,
mint: std::option::Option::None,
account: std::option::Option::None,
family: std::option::Option::Some("fee".to_string()),
operation: std::option::Option::None,
limit: 501,
};
assert!(crate::validate_journal_request(request).is_err());
}
}

View File

@@ -0,0 +1,399 @@
// file: kb-app-demo-desktop/src/demo_spl_token2022.rs
// version: 4
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
use ts_rs::TS; // rust-rules: derive-import
/// Public values loaded from one persisted Token-2022 validation fixture.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token2022/DemoSplToken2022FixturePayload.ts"
)]
pub(crate) struct DemoSplToken2022FixturePayload {
/// Fixture file used by the application.
pub(crate) fixture_path: std::string::String,
/// Token-2022 program ID.
pub(crate) program_id: std::string::String,
/// Mint account.
pub(crate) mint: std::string::String,
/// Source token account.
pub(crate) source: std::string::String,
/// Destination token account.
pub(crate) destination: std::string::String,
/// Dedicated empty account reserved for CloseAccount validation.
pub(crate) close_account: std::string::String,
/// Delegate account.
pub(crate) delegate: std::string::String,
/// Profile-wallet authority.
pub(crate) authority: std::string::String,
/// Freeze authority when configured on the mint.
pub(crate) freeze_authority: std::string::String,
/// Mint decimals.
pub(crate) decimals: u8,
/// Default raw amount for the selected scenario.
pub(crate) default_amount_raw: std::string::String,
}
/// Request for one independent public Token-2022 Devnet scenario.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token2022/DemoExecutionSplToken2022Request.ts"
)]
pub(crate) struct DemoExecutionSplToken2022Request {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Stable scenario identifier.
pub(crate) scenario_id: std::string::String,
/// Source or target token account depending on the selected operation.
pub(crate) source: std::string::String,
/// Exact mint account.
pub(crate) mint: std::string::String,
/// Destination token account or close-account lamport destination.
pub(crate) destination: std::string::String,
/// Delegate account used by `ApproveChecked`.
pub(crate) delegate: std::string::String,
/// Owner or mint authority resolved by the selected profile wallet.
pub(crate) authority: std::string::String,
/// Freeze authority used by freeze and thaw scenarios.
pub(crate) freeze_authority: std::string::String,
/// Exact raw amount represented as a decimal string.
pub(crate) amount_raw: std::string::String,
/// Expected mint decimals carried by checked instructions.
pub(crate) decimals: u8,
/// Whether the transaction should be signed and submitted after simulation.
pub(crate) submit: bool,
/// Explicit operator confirmation for signed submission.
pub(crate) operator_confirmed: bool,
/// Whether post-execution core and decode outputs should be force-replayed.
pub(crate) force_post_validation_replay: bool,
}
/// UI-safe result of one public Token-2022 Devnet orchestration.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token2022/DemoExecutionSplToken2022SummaryPayload.ts"
)]
pub(crate) struct DemoExecutionSplToken2022SummaryPayload {
/// Stable scenario identifier.
pub(crate) scenario_id: std::string::String,
/// Stable operation code.
pub(crate) operation: std::string::String,
/// Profile used by the orchestration.
pub(crate) profile_name: std::string::String,
/// Classified cluster code.
pub(crate) cluster: std::string::String,
/// Genesis hash returned by the endpoint.
pub(crate) genesis_hash: std::string::String,
/// Source wallet public key.
pub(crate) wallet_public_key: std::string::String,
/// Exact wallet balance rendered without JSON integer precision loss.
pub(crate) balance_lamports: std::string::String,
/// Estimated fee rendered without JSON integer precision loss.
pub(crate) fee_lamports: std::option::Option<std::string::String>,
/// Whether exact simulation succeeded.
pub(crate) simulation_success: bool,
/// Runtime simulation error when present.
pub(crate) simulation_error: std::option::Option<std::string::String>,
/// Submitted transaction signature.
pub(crate) transaction_signature: std::option::Option<std::string::String>,
/// Terminal confirmation status.
pub(crate) confirmation_status: std::option::Option<std::string::String>,
/// Whether canonical hydration was validated.
pub(crate) canonical_inserted: bool,
/// Whether core extraction was validated.
pub(crate) core_extracted: bool,
/// Whether Token-2022 decode replay was validated.
pub(crate) decode_replayed: bool,
/// Number of materialized rows for the submitted instruction.
pub(crate) materialization_count: u32,
/// Whether the second replay produced no failure or new output.
pub(crate) idempotence_validated: bool,
/// Pretty JSON representation of the exact execution plan.
pub(crate) plan_json: std::string::String,
/// Pretty JSON representation of stateful preflight.
pub(crate) preflight_json: std::string::String,
/// Pretty JSON representation of the exact simulation result.
pub(crate) simulation_json: std::string::String,
/// Pretty JSON representation of confirmation and replay diagnostics.
pub(crate) diagnostics_json: std::string::String,
}
pub(crate) fn operation_from_request(
request: &crate::DemoExecutionSplToken2022Request,
) -> std::result::Result<kb_lib::ExSplToken2022Operation, std::string::String> {
let authority = kb_lib::ExSplTokenAuthority {
authority: kb_lib::MdPubkey(request.authority.trim().to_string()),
multisig_signers: std::vec::Vec::new(),
};
let freeze_authority = kb_lib::ExSplTokenAuthority {
authority: kb_lib::MdPubkey(request.freeze_authority.trim().to_string()),
multisig_signers: std::vec::Vec::new(),
};
let value = match request.scenario_id.trim() {
"token2022_mint_to_checked" => kb_lib::ExSplTokenSingleOperation::MintToChecked {
mint: kb_lib::MdPubkey(request.mint.trim().to_string()),
destination: kb_lib::MdPubkey(request.source.trim().to_string()),
authority,
amount: kb_lib::ExSplTokenAmount(request.amount_raw.trim().to_string()),
decimals: request.decimals,
},
"token2022_transfer_checked" => kb_lib::ExSplTokenSingleOperation::TransferChecked {
source: kb_lib::MdPubkey(request.source.trim().to_string()),
mint: kb_lib::MdPubkey(request.mint.trim().to_string()),
destination: kb_lib::MdPubkey(request.destination.trim().to_string()),
authority,
amount: kb_lib::ExSplTokenAmount(request.amount_raw.trim().to_string()),
decimals: request.decimals,
},
"token2022_approve_checked" => kb_lib::ExSplTokenSingleOperation::ApproveChecked {
source: kb_lib::MdPubkey(request.source.trim().to_string()),
mint: kb_lib::MdPubkey(request.mint.trim().to_string()),
delegate: kb_lib::MdPubkey(request.delegate.trim().to_string()),
authority,
amount: kb_lib::ExSplTokenAmount(request.amount_raw.trim().to_string()),
decimals: request.decimals,
},
"token2022_revoke" => kb_lib::ExSplTokenSingleOperation::Revoke {
source: kb_lib::MdPubkey(request.source.trim().to_string()),
authority,
},
"token2022_burn_checked" => kb_lib::ExSplTokenSingleOperation::BurnChecked {
source: kb_lib::MdPubkey(request.source.trim().to_string()),
mint: kb_lib::MdPubkey(request.mint.trim().to_string()),
authority,
amount: kb_lib::ExSplTokenAmount(request.amount_raw.trim().to_string()),
decimals: request.decimals,
},
"token2022_freeze_account" => kb_lib::ExSplTokenSingleOperation::FreezeAccount {
account: kb_lib::MdPubkey(request.source.trim().to_string()),
mint: kb_lib::MdPubkey(request.mint.trim().to_string()),
authority: freeze_authority,
},
"token2022_thaw_account" => kb_lib::ExSplTokenSingleOperation::ThawAccount {
account: kb_lib::MdPubkey(request.source.trim().to_string()),
mint: kb_lib::MdPubkey(request.mint.trim().to_string()),
authority: freeze_authority,
},
"token2022_close_destination" => kb_lib::ExSplTokenSingleOperation::CloseAccount {
account: kb_lib::MdPubkey(request.source.trim().to_string()),
destination: kb_lib::MdPubkey(request.destination.trim().to_string()),
authority,
},
other => {
return std::result::Result::Err(format!(
"unsupported public Token-2022 Devnet scenario {other}"
));
},
};
return std::result::Result::Ok(kb_lib::ExSplToken2022Operation::Instruction {
value: std::boxed::Box::new(value),
});
}
pub(crate) fn demo_spl_token2022_summary_payload(
scenario_id: std::string::String,
operation: std::string::String,
summary: kb_pipeline_demo_scenarios::DevnetSplToken2022ExecutionSummary,
) -> crate::DemoExecutionSplToken2022SummaryPayload {
let plan_json = crate::pretty_json(&summary.plan);
let preflight_json = crate::pretty_json(&summary.stateful_preflight);
let simulation_json = crate::pretty_json(&summary.simulation);
let transaction_signature =
summary.send_result.as_ref().map(|value| return value.signature.0.clone());
let confirmation_status = summary.confirmation.as_ref().map(|value| {
return crate::confirmation_status_code(value.status);
});
let post_execution = summary.post_execution.as_ref();
let canonical_inserted = post_execution.is_some_and(|value| return value.canonical_inserted);
let core_extracted = post_execution.is_some_and(|value| return value.core_extracted);
let decode_replayed = post_execution.is_some_and(|value| return value.decode_replayed);
let idempotence_validated = summary.idempotence_replay.as_ref().is_some_and(|replay| {
return replay.failed_inputs == 0
&& !replay.cancelled
&& replay.processors.iter().all(|processor| {
return processor.failed == 0
&& processor.materialized_outputs == 0
&& processor.materialization_refused == 0;
});
});
let materialization_count = match u32::try_from(summary.materializations.len()) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => u32::MAX,
};
let diagnostics = serde_json::json!({
"confirmation": summary.confirmation,
"postExecution": summary.post_execution,
"backfill": summary.backfill.as_ref().map(backfill_summary_json),
"coreExtraction": summary.core_extraction.as_ref().map(core_extraction_summary_json),
"decodeReplay": summary.decode_replay.as_ref().map(decode_replay_summary_json),
"idempotenceReplay": summary.idempotence_replay.as_ref().map(decode_replay_summary_json),
"materializations": summary.materializations
});
return crate::DemoExecutionSplToken2022SummaryPayload {
scenario_id,
operation,
profile_name: summary.profile_name,
cluster: crate::execution_cluster_code(summary.cluster),
genesis_hash: summary.genesis_hash,
wallet_public_key: summary.wallet.public_key,
balance_lamports: summary.balance_lamports.to_string(),
fee_lamports: summary.fee.fee_lamports.map(|value| return value.to_string()),
simulation_success: summary.simulation.success,
simulation_error: summary.simulation.error,
transaction_signature,
confirmation_status,
canonical_inserted,
core_extracted,
decode_replayed,
materialization_count,
idempotence_validated,
plan_json,
preflight_json,
simulation_json,
diagnostics_json: crate::pretty_json(&diagnostics),
};
}
pub(crate) fn parse_fixture(
contents: &str,
) -> std::collections::BTreeMap<std::string::String, std::string::String> {
let mut values = std::collections::BTreeMap::new();
for line in contents.lines() {
let trimmed = line.trim();
let assignment = match trimmed.strip_prefix("export ") {
std::option::Option::Some(value) => value,
std::option::Option::None => continue,
};
let (name, raw_value) = match assignment.split_once('=') {
std::option::Option::Some(value) => value,
std::option::Option::None => continue,
};
let value = raw_value.trim().trim_matches('\'').trim_matches('"').to_string();
values.insert(name.trim().to_string(), value);
}
return values;
}
fn backfill_summary_json(summary: &kb_pipeline::BackfillSummary) -> serde_json::Value {
return serde_json::json!({
"captureSessionId": summary.capture_session_id,
"filterCode": summary.filter_code,
"role": summary.role,
"provider": summary.provider,
"endpointCode": summary.endpoint_code,
"pagesFetched": summary.pages_fetched,
"candidatesSelected": summary.candidates_selected,
"candidatesStarted": summary.candidates_started,
"candidatesCompleted": summary.candidates_completed,
"candidatesCancelled": summary.candidates_cancelled,
"candidatesNotStarted": summary.candidates_not_started,
"transactionsReceived": summary.transactions_received,
"canonicalInserted": summary.canonical_inserted,
"canonicalSkipped": summary.canonical_skipped,
"existingSkipped": summary.existing_skipped,
"missing": summary.missing,
"failed": summary.failed,
"observationsInserted": summary.observations_inserted,
"attempts": summary.attempts,
"cancelled": summary.cancelled,
"resumeBeforeSignature": summary.resume_before_signature,
"startedAt": summary.started_at,
"finishedAt": summary.finished_at
});
}
fn core_extraction_summary_json(summary: &kb_pipeline::CoreExtractionSummary) -> serde_json::Value {
return serde_json::json!({
"processorVersion": summary.processor_version,
"selected": summary.selected,
"started": summary.started,
"completed": summary.completed,
"skipped": summary.skipped,
"extracted": summary.extracted,
"failed": summary.failed,
"cancelledCandidates": summary.cancelled_candidates,
"notStarted": summary.not_started,
"cancelled": summary.cancelled,
"startedAt": summary.started_at,
"finishedAt": summary.finished_at
});
}
fn decode_replay_summary_json(summary: &kb_pipeline::DecodeReplaySummary) -> serde_json::Value {
let processors = summary
.processors
.iter()
.map(|processor| {
return serde_json::json!({
"name": processor.processor_name,
"version": processor.processor_version,
"dispatched": processor.dispatched,
"skipped": processor.skipped,
"decoded": processor.decoded,
"ignored": processor.ignored,
"unsupported": processor.unsupported,
"failed": processor.failed,
"materializedOutputs": processor.materialized_outputs,
"materializationRefused": processor.materialization_refused
});
})
.collect::<std::vec::Vec<serde_json::Value>>();
return serde_json::json!({
"campaignId": summary.campaign_id,
"pipelineVersion": summary.pipeline_version,
"selected": summary.selected,
"started": summary.started,
"completed": summary.completed,
"unmatched": summary.unmatched,
"notStarted": summary.not_started,
"failedInputs": summary.failed_inputs,
"cancelled": summary.cancelled,
"processors": processors,
"startedAt": summary.started_at,
"finishedAt": summary.finished_at
});
}
#[cfg(test)]
mod tests {
fn request(scenario_id: &str) -> crate::DemoExecutionSplToken2022Request {
return crate::DemoExecutionSplToken2022Request {
profile_name: "local_devnet".to_string(),
scenario_id: scenario_id.to_string(),
source: "source".to_string(),
mint: "mint".to_string(),
destination: "destination".to_string(),
delegate: "delegate".to_string(),
authority: "authority".to_string(),
freeze_authority: "freeze".to_string(),
amount_raw: "1".to_string(),
decimals: 9,
submit: false,
operator_confirmed: false,
force_post_validation_replay: true,
};
}
#[test]
fn every_public_scenario_builds_one_typed_operation() {
for scenario in [
"token2022_mint_to_checked",
"token2022_transfer_checked",
"token2022_approve_checked",
"token2022_revoke",
"token2022_burn_checked",
"token2022_freeze_account",
"token2022_thaw_account",
"token2022_close_destination",
] {
assert!(crate::operation_from_request(&request(scenario)).is_ok());
}
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/lib.rs
// version: 7
// version: 9
//! Tauri desktop demo application for `khadhroony-bot3`.
@@ -13,7 +13,12 @@ mod demo_backfill;
mod demo_config;
mod demo_core_extraction;
mod demo_decode_replay;
mod demo_execution_solana_core;
mod demo_execution_spl;
mod demo_http;
mod demo_spl_ata;
mod demo_spl_token;
mod demo_spl_token2022;
mod demo_sql_common;
mod demo_sql_diag;
mod demo_sql_pg_core;
@@ -54,6 +59,100 @@ pub(crate) use self::demo_backfill::demo_backfill_summary_payload;
pub(crate) use self::demo_config::DemoConfigPayload;
/// Builds the configuration payload from shared application state.
pub(crate) use self::demo_config::demo_config_payload;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionObserver;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionOptionsPayload;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionProgressPayload;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionRequest;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionRunGuard;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionSummaryPayload;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::build_demo_core_extraction_pipeline_request;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::demo_core_extraction_summary_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeCoverageSummaryPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeDiagnosticsPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeProcessorSummaryPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayDecoderOption;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayObserver;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayOptionsPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayProgressPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayRequest;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayRunGuard;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplaySummaryPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoTransactionAnnotationRequest;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoTransactionAnnotationRow;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::annotation_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::available_decoders;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::available_materializers;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::build_demo_decode_replay_pipeline_request;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::coverage_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::demo_decode_replay_summary_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::optional_line_count;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::register_active_campaign;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::text_sample;
/// Request sent by the Memo v4 Devnet execution panel.
pub(crate) use self::demo_execution_solana_core::DemoExecutionMemoRequest;
/// UI-safe result of one Memo v4 Devnet execution orchestration.
pub(crate) use self::demo_execution_solana_core::DemoExecutionMemoSummaryPayload;
/// Public key generated for a disposable Devnet recipient.
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreGeneratedRecipientPayload;
/// ????
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreObserver;
/// Initial options shown by the Solana Core execution demo.
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreOptionsPayload;
/// One Devnet execution profile exposed to the demo window.
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreProfileOption;
/// Progress event emitted during execution and post-validation.
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreProgressPayload;
/// Request sent by the execution demo.
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreRequest;
/// ????
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreRunGuard;
/// UI-safe result of one execution orchestration.
pub(crate) use self::demo_execution_solana_core::DemoExecutionSolanaCoreSummaryPayload;
/// ????
pub(crate) use self::demo_execution_solana_core::confirmation_status_code;
/// ????
pub(crate) use self::demo_execution_solana_core::demo_execution_solana_core_memo_summary_payload;
/// ????
pub(crate) use self::demo_execution_solana_core::demo_execution_solana_core_summary_payload;
/// ????
pub(crate) use self::demo_execution_solana_core::devnet_profile_options;
/// ????
pub(crate) use self::demo_execution_solana_core::execution_cluster_code;
/// ????
pub(crate) use self::demo_execution_solana_core::pretty_json;
/// ????
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;
/// HTTP demo response payload.
pub(crate) use self::demo_http::DemoHttpExecutionPayload;
/// One selectable HTTP JSON-RPC method.
@@ -70,12 +169,66 @@ pub(crate) use self::demo_http::build_http_method_options;
pub(crate) use self::demo_http::build_http_role_options;
/// Executes one raw HTTP JSON-RPC request.
pub(crate) use self::demo_http::demo_http_execute_request_inner;
/// Request for one representative ATA creation on Devnet.
pub(crate) use self::demo_spl_ata::DemoExecutionSplAtaRequest;
/// UI-safe ATA execution result.
pub(crate) use self::demo_spl_ata::DemoExecutionSplAtaSummaryPayload;
/// Readonly payer, wallet, Token Program and derived ATA values.
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;
/// Bounded ATA lifecycle journal request.
pub(crate) use self::demo_spl_ata::DemoSplAtaJournalRequest;
/// One UI-safe ATA lifecycle journal row.
pub(crate) use self::demo_spl_ata::DemoSplAtaJournalRow;
/// ????
pub(crate) use self::demo_spl_ata::demo_spl_ata_summary_payload;
/// ????
pub(crate) use self::demo_spl_ata::derive_ata;
/// ????
pub(crate) use self::demo_spl_ata::journal_matches;
/// ????
pub(crate) use self::demo_spl_ata::journal_row;
/// ????
pub(crate) use self::demo_spl_ata::load_profile_wallet;
/// ????
pub(crate) use self::demo_spl_ata::parse_token_program;
/// Request for one checked classic SPL Token transfer on Devnet.
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;
/// 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.
pub(crate) use self::demo_spl_token::DemoSplTokenJournalRow;
/// ????
pub(crate) use self::demo_spl_token::demo_spl_token_journal_row;
/// Executes one checked SPL Token simulation or explicitly authorized Devnet submission.
pub(crate) use self::demo_spl_token::demo_spl_token_summary_payload;
/// ????
pub(crate) use self::demo_spl_token::payload_matches;
/// Loads a bounded, typed journal of committed classic SPL Token projections.
pub(crate) use self::demo_spl_token::validate_journal_request;
/// Request for one independent public Token-2022 Devnet scenario.
pub(crate) use self::demo_spl_token2022::DemoExecutionSplToken2022Request;
/// UI-safe result of one public Token-2022 Devnet orchestration.
pub(crate) use self::demo_spl_token2022::DemoExecutionSplToken2022SummaryPayload;
/// Public values loaded from one persisted Token-2022 validation fixture.
pub(crate) use self::demo_spl_token2022::DemoSplToken2022FixturePayload;
/// ????
pub(crate) use self::demo_spl_token2022::demo_spl_token2022_summary_payload;
/// ????
pub(crate) use self::demo_spl_token2022::operation_from_request;
/// ????
pub(crate) use self::demo_spl_token2022::parse_fixture;
/// UI-safe SQL table diagnostic snapshot.
pub(crate) use self::demo_sql_common::DemoSqlTableSnapshot;
/// Connects to the configured PostgreSQL store.
pub(crate) use self::demo_sql_common::connect_postgres_store;
/// Formats diagnostic statuses.
pub(crate) use self::demo_sql_common::debug_status;
/// Initializes the PostgreSQL schema during startup.
pub(crate) use self::demo_sql_common::initialize_postgres_schema_for_startup;
/// Opens or focuses one SQL demo window.
pub(crate) use self::demo_sql_common::open_sql_demo_window;
/// Builds PostgreSQL options from the active profile.
@@ -154,6 +307,8 @@ pub(crate) use self::demo_ws::demo_ws_disconnect_inner;
pub(crate) use self::demo_ws::demo_ws_status_inner;
/// Unsubscribes one active WebSocket subscription.
pub(crate) use self::demo_ws::demo_ws_unsubscribe_inner;
/// Disconnects the persistent WebSocket session during application shutdown.
pub(crate) use self::demo_ws::disconnect_demo_ws_app_state;
/// Frontend logging payload.
pub(crate) use self::frontend_log::FrontendLogPayload;
/// Emits one normalized frontend log event.
@@ -175,64 +330,6 @@ pub(crate) use self::splash::emit_splash_order;
/// Waits for the minimum splash duration.
pub(crate) use self::splash::wait_until_minimum;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionObserver;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionOptionsPayload;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionProgressPayload;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionRequest;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionRunGuard;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::DemoCoreExtractionSummaryPayload;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::build_demo_core_extraction_pipeline_request;
/// Internal demo core extraction item.
pub(crate) use self::demo_core_extraction::demo_core_extraction_summary_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeCoverageSummaryPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeDiagnosticsPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeProcessorSummaryPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayDecoderOption;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayObserver;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayOptionsPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayProgressPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayRequest;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplayRunGuard;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoDecodeReplaySummaryPayload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoTransactionAnnotationRequest;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::DemoTransactionAnnotationRow;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::annotation_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::available_decoders;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::available_materializers;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::build_demo_decode_replay_pipeline_request;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::coverage_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::demo_decode_replay_summary_payload;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::optional_line_count;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::register_active_campaign;
/// Internal demo decode replay item.
pub(crate) use self::demo_decode_replay::text_sample;
// Keep the canonical tracing target as the final facade export.
/// Canonical tracing target for the desktop demo application.
pub(crate) use self::constants::TRACING_TARGET;

View File

@@ -64,6 +64,21 @@ pub fn run() -> kb_core::Result<()> {
load_demo_sql_replay_programs,
load_demo_sql_replay_entities,
export_demo_sql_replay_csv,
demo_execution_solana_core_options,
demo_execution_solana_core_generate_recipient,
demo_execution_solana_core_execute,
open_demo_execution_solana_core_window,
demo_execution_spl_memo_execute,
demo_execution_solana_core_cancel,
open_demo_execution_spl_window,
demo_execution_spl_validation_scenarios,
demo_execution_spl_token_execute,
demo_spl_token_journal,
demo_execution_spl_token2022_execute,
demo_spl_token2022_fixture,
demo_spl_ata_derive,
demo_execution_spl_ata_execute,
demo_spl_ata_journal,
open_demo_core_extraction_window,
demo_core_extraction_options,
demo_core_extraction_execute,
@@ -1307,3 +1322,867 @@ async fn load_demo_sql_replay_entities(
}
return std::result::Result::Ok(output);
}
/// Opens or focuses the Solana Core execution demo window.
#[tauri::command]
fn open_demo_execution_solana_core_window(
app_handle: tauri::AppHandle,
) -> std::result::Result<(), std::string::String> {
let existing_window = app_handle.get_webview_window("demo_execution_solana_core");
if let std::option::Option::Some(window) = existing_window {
let show_result = window.show();
if let std::result::Result::Err(error) = show_result {
return std::result::Result::Err(error.to_string());
}
let focus_result = window.set_focus();
if let std::result::Result::Err(error) = focus_result {
return std::result::Result::Err(error.to_string());
}
return std::result::Result::Ok(());
}
let build_result = tauri::WebviewWindowBuilder::new(
&app_handle,
"demo_execution_solana_core",
tauri::WebviewUrl::App("demo_execution_solana_core.html".into()),
)
.title("Khadhroony Bot3 - Exécution Solana Devnet")
.inner_size(1360.0, 920.0)
.min_inner_size(1040.0, 700.0)
.resizable(true)
.visible(true)
.build();
return match build_result {
std::result::Result::Ok(window) => {
let focus_result = window.set_focus();
if let std::result::Result::Err(error) = focus_result {
return std::result::Result::Err(error.to_string());
}
std::result::Result::Ok(())
},
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Returns compatible Devnet profiles and conservative defaults.
#[tauri::command]
fn demo_execution_solana_core_options(
state: tauri::State<'_, crate::AppState>,
) -> crate::DemoExecutionSolanaCoreOptionsPayload {
let profiles = crate::devnet_profile_options(state.app_config());
let default_profile_name = profiles.first().map(|profile| return profile.name.clone());
return crate::DemoExecutionSolanaCoreOptionsPayload {
profiles,
default_profile_name,
default_transfer_lamports: 1_000_000,
running: state
.demo_execution_solana_core_running()
.load(std::sync::atomic::Ordering::Acquire),
};
}
/// Generates a disposable recipient public key without exposing its private key.
#[tauri::command]
fn demo_execution_solana_core_generate_recipient()
-> std::result::Result<crate::DemoExecutionSolanaCoreGeneratedRecipientPayload, std::string::String>
{
let alias = match kb_wallet::WalletAlias::parse("demo-devnet-recipient") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let wallet = kb_wallet::TemporaryWallet::generate(alias);
return std::result::Result::Ok(crate::DemoExecutionSolanaCoreGeneratedRecipientPayload {
public_key: wallet.public_key(),
});
}
/// Executes one bounded System transfer simulation or Devnet submission.
#[tauri::command]
#[allow(clippy::question_mark_used)]
async fn demo_execution_solana_core_execute(
app_handle: tauri::AppHandle,
state: tauri::State<'_, crate::AppState>,
request: crate::DemoExecutionSolanaCoreRequest,
) -> std::result::Result<crate::DemoExecutionSolanaCoreSummaryPayload, std::string::String> {
let acquire_result = state.demo_execution_solana_core_running().compare_exchange(
false,
true,
std::sync::atomic::Ordering::AcqRel,
std::sync::atomic::Ordering::Acquire,
);
if acquire_result.is_err() {
return std::result::Result::Err("a Solana Core execution is already running".to_string());
}
let _run_guard = crate::DemoExecutionSolanaCoreRunGuard {
running: state.demo_execution_solana_core_running(),
};
state
.demo_execution_solana_core_cancel_requested()
.store(false, std::sync::atomic::Ordering::Release);
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 http_pool = match kb_onchain_transport::HttpEndpointPool::from_profile(&profile) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let initialize_result = store.initialize_store_schema().await;
if let std::result::Result::Err(error) = initialize_result {
return std::result::Result::Err(error.to_string());
}
let mut pipeline_request = kb_pipeline_demo_scenarios::DevnetSystemTransferRequest::new(
format!("demo-execution-{}", chrono::Utc::now().timestamp_micros()),
kb_lib::MdPubkey(request.recipient.trim().to_string()),
request.lamports,
);
pipeline_request.airdrop_lamports = request.airdrop_lamports;
pipeline_request.submit = request.submit;
pipeline_request.operator_confirmed = request.operator_confirmed;
pipeline_request.post_validation_max_retries = 20;
pipeline_request.force_post_validation_replay = request.force_post_validation_replay;
pipeline_request.materialize_after_decode = request.materialize_after_decode;
let decoders: std::vec::Vec<std::sync::Arc<dyn kb_lib::DcApiInstructionDecoder>> =
std::vec![std::sync::Arc::new(kb_lib::DcSolanaCoreDecoder)];
let materializers: std::vec::Vec<std::sync::Arc<dyn kb_lib::MtApiEventMaterializer>> =
if request.materialize_after_decode {
std::vec![
std::sync::Arc::new(kb_lib::MtAdminMaterializer),
std::sync::Arc::new(kb_lib::MtComplianceAuditMaterializer,),
std::sync::Arc::new(kb_lib::MtLifecycleMaterializer),
std::sync::Arc::new(kb_lib::MtStakingMaterializer),
]
} else {
std::vec::Vec::new()
};
let observer = crate::DemoExecutionSolanaCoreObserver {
app_handle,
cancel_requested: state.demo_execution_solana_core_cancel_requested(),
};
let workspace_root = crate::workspace_root_dir();
let summary = match kb_pipeline_demo_scenarios::execute_devnet_system_transfer(
&http_pool,
&store,
&profile,
workspace_root.as_path(),
&pipeline_request,
decoders.as_slice(),
materializers.as_slice(),
&observer,
)
.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::demo_execution_solana_core_summary_payload(summary));
}
/// Executes one Memo v4 simulation or explicitly authorized Devnet submission.
#[tauri::command]
#[allow(clippy::question_mark_used)]
async fn demo_execution_spl_memo_execute(
app_handle: tauri::AppHandle,
state: tauri::State<'_, crate::AppState>,
request: crate::DemoExecutionMemoRequest,
) -> std::result::Result<crate::DemoExecutionMemoSummaryPayload, std::string::String> {
let acquire_result = state.demo_execution_solana_core_running().compare_exchange(
false,
true,
std::sync::atomic::Ordering::AcqRel,
std::sync::atomic::Ordering::Acquire,
);
if acquire_result.is_err() {
return std::result::Result::Err("a Devnet execution is already running".to_string());
}
let _run_guard = crate::DemoExecutionSolanaCoreRunGuard {
running: state.demo_execution_solana_core_running(),
};
state
.demo_execution_solana_core_cancel_requested()
.store(false, std::sync::atomic::Ordering::Release);
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 http_pool = match kb_onchain_transport::HttpEndpointPool::from_profile(&profile) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let mut pipeline_request = kb_pipeline_demo_scenarios::DevnetMemoExecutionRequest::new(
format!("demo-memo-execution-{}", chrono::Utc::now().timestamp_micros()),
request.message,
);
pipeline_request.include_wallet_as_memo_signer = request.include_wallet_as_memo_signer;
pipeline_request.submit = request.submit;
pipeline_request.operator_confirmed = request.operator_confirmed;
pipeline_request.post_validation_max_retries = 20;
pipeline_request.force_post_validation_replay = request.force_post_validation_replay;
let decoders: std::vec::Vec<std::sync::Arc<dyn kb_lib::DcApiInstructionDecoder>> =
std::vec![std::sync::Arc::new(kb_lib::DcSplMemoDecoder)];
let materializers: std::vec::Vec<std::sync::Arc<dyn kb_lib::MtApiEventMaterializer>> =
std::vec![std::sync::Arc::new(kb_lib::MtTransactionAnnotationMaterializer,)];
let observer = crate::DemoExecutionSolanaCoreObserver {
app_handle,
cancel_requested: state.demo_execution_solana_core_cancel_requested(),
};
let workspace_root = crate::workspace_root_dir();
let summary = match kb_pipeline_demo_scenarios::execute_devnet_memo(
&http_pool,
&store,
&profile,
workspace_root.as_path(),
&pipeline_request,
decoders.as_slice(),
materializers.as_slice(),
&observer,
)
.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::demo_execution_solana_core_memo_summary_payload(
summary,
));
}
/// Requests cooperative cancellation before the next execution stage.
#[tauri::command]
fn demo_execution_solana_core_cancel(state: tauri::State<'_, crate::AppState>) -> bool {
let running = state
.demo_execution_solana_core_running()
.load(std::sync::atomic::Ordering::Acquire);
if !running {
return false;
}
state
.demo_execution_solana_core_cancel_requested()
.store(true, std::sync::atomic::Ordering::Release);
return true;
}
/// Returns the complete ordered Devnet SPL validation inventory for milestone 0.4.6.
#[tauri::command]
fn demo_execution_spl_validation_scenarios()
-> std::vec::Vec<crate::DevnetSplValidationScenarioPayload> {
return kb_pipeline_demo_scenarios::devnet_spl_validation_scenarios()
.into_iter()
.map(|scenario| {
return crate::DevnetSplValidationScenarioPayload {
id: scenario.id,
label: scenario.label,
family: match scenario.family {
kb_pipeline_demo_scenarios::DevnetSplValidationFamily::Token2022Public => {
"token2022_public".to_string()
},
kb_pipeline_demo_scenarios::DevnetSplValidationFamily::ElGamalRegistry => {
"elgamal_registry".to_string()
},
kb_pipeline_demo_scenarios::DevnetSplValidationFamily::Token2022Confidential => {
"token2022_confidential".to_string()
},
},
operation_code: scenario.operation_code,
implementation_status: match scenario.implementation_status {
kb_pipeline_demo_scenarios::DevnetSplValidationImplementationStatus::Executable => {
"executable".to_string()
},
kb_pipeline_demo_scenarios::DevnetSplValidationImplementationStatus::BackendReady => {
"backend_ready".to_string()
},
kb_pipeline_demo_scenarios::DevnetSplValidationImplementationStatus::ProofFixtureRequired => {
"proof_fixture_required".to_string()
},
},
proof_required: scenario.proof_required,
required_fixture_variables: scenario.required_fixture_variables,
};
})
.collect();
}
/// Opens or focuses the dedicated SPL execution window.
#[tauri::command]
fn open_demo_execution_spl_window(
app_handle: tauri::AppHandle,
) -> std::result::Result<(), std::string::String> {
tracing::info!(target: crate::TRACING_TARGET, "open SPL Devnet execution window");
let existing_window = app_handle.get_webview_window("demo_execution_spl");
if let std::option::Option::Some(window) = existing_window {
let show_result = window.show();
if let std::result::Result::Err(error) = show_result {
return std::result::Result::Err(error.to_string());
}
let focus_result = window.set_focus();
if let std::result::Result::Err(error) = focus_result {
return std::result::Result::Err(error.to_string());
}
return std::result::Result::Ok(());
}
let build_result = tauri::WebviewWindowBuilder::new(
&app_handle,
"demo_execution_spl",
tauri::WebviewUrl::App("demo_execution_spl.html".into()),
)
.title("Khadhroony Bot3 - Exécution SPL Devnet")
.inner_size(1500.0, 960.0)
.min_inner_size(1120.0, 720.0)
.resizable(true)
.visible(true)
.build();
return match build_result {
std::result::Result::Ok(window) => {
let focus_result = window.set_focus();
if let std::result::Result::Err(error) = focus_result {
return std::result::Result::Err(error.to_string());
}
std::result::Result::Ok(())
},
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Executes one checked SPL Token simulation or explicitly authorized Devnet submission.
#[tauri::command]
#[allow(clippy::question_mark_used)]
async fn demo_execution_spl_token_execute(
app_handle: tauri::AppHandle,
state: tauri::State<'_, crate::AppState>,
request: crate::DemoExecutionSplTokenRequest,
) -> std::result::Result<crate::DemoExecutionSplTokenSummaryPayload, std::string::String> {
let acquire_result = state.demo_execution_solana_core_running().compare_exchange(
false,
true,
std::sync::atomic::Ordering::AcqRel,
std::sync::atomic::Ordering::Acquire,
);
if acquire_result.is_err() {
return std::result::Result::Err("a Devnet execution is already running".to_string());
}
let _run_guard = crate::DemoExecutionSolanaCoreRunGuard {
running: state.demo_execution_solana_core_running(),
};
state
.demo_execution_solana_core_cancel_requested()
.store(false, std::sync::atomic::Ordering::Release);
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 http_pool = match kb_onchain_transport::HttpEndpointPool::from_profile(&profile) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let amount_raw = request.amount_raw.trim().to_string();
let operation = kb_lib::ExSplClassicTokenOperation::Instruction {
value: kb_lib::ExSplClassicTokenSingleOperation::TransferChecked {
source: kb_lib::MdPubkey(request.source.trim().to_string()),
mint: kb_lib::MdPubkey(request.mint.trim().to_string()),
destination: kb_lib::MdPubkey(request.destination.trim().to_string()),
authority: kb_lib::ExSplClassicTokenAuthority {
authority: kb_lib::MdPubkey(request.authority.trim().to_string()),
multisig_signers: std::vec::Vec::new(),
},
amount: kb_lib::ExSplClassicTokenAmount(amount_raw.clone()),
decimals: request.decimals,
},
};
let mut pipeline_request = kb_pipeline_demo_scenarios::DevnetSplTokenExecutionRequest::new(
format!("demo-spl-token-execution-{}", chrono::Utc::now().timestamp_micros()),
operation,
);
pipeline_request.submit = request.submit;
pipeline_request.operator_confirmed = request.operator_confirmed;
pipeline_request.post_validation_max_retries = 20;
pipeline_request.force_post_validation_replay = request.force_post_validation_replay;
let decoders: std::vec::Vec<std::sync::Arc<dyn kb_lib::DcApiInstructionDecoder>> =
std::vec![std::sync::Arc::new(kb_lib::DcSplTokenDecoder)];
let materializers: std::vec::Vec<std::sync::Arc<dyn kb_lib::MtApiEventMaterializer>> = std::vec![
std::sync::Arc::new(kb_lib::MtTokenAccountsMaterializer),
std::sync::Arc::new(kb_lib::MtAdminMaterializer),
std::sync::Arc::new(kb_lib::MtRiskMaterializer),
];
let observer = crate::DemoExecutionSolanaCoreObserver {
app_handle,
cancel_requested: state.demo_execution_solana_core_cancel_requested(),
};
let workspace_root = crate::workspace_root_dir();
let summary = match kb_pipeline_demo_scenarios::execute_devnet_spl_token(
&http_pool,
&store,
&profile,
workspace_root.as_path(),
&pipeline_request,
decoders.as_slice(),
materializers.as_slice(),
&observer,
)
.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::demo_spl_token_summary_payload(
summary,
amount_raw,
request.decimals,
));
}
/// Loads a bounded, typed journal of committed classic SPL Token projections.
#[tauri::command]
#[allow(clippy::question_mark_used)]
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> {
let validated = match crate::validate_journal_request(request) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let profile =
match crate::select_devnet_profile(state.app_config(), validated.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::connect_postgres_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
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 {
kb_store::MAX_MATERIALIZED_EVENT_QUERY_ROWS
} else {
validated.limit
};
let filter = match kb_store::MaterializedEventFilter::new(
std::option::Option::None,
validated.family.clone(),
validated.signature_contains.clone(),
query_limit,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let rows = match kb_store::DecodePipelineStore::list_materialized_events(&store, &filter).await
{
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::new();
for row in rows {
if row.source_decoder_name != "spl_token"
|| !crate::payload_matches(&row.payload_json, &validated)
{
continue;
}
output.push(crate::demo_spl_token_journal_row(row));
if output.len() >= validated.limit as usize {
break;
}
}
return std::result::Result::Ok(output);
}
/// Derives the representative profile wallet ATA without exposing private key material.
#[tauri::command]
#[allow(clippy::question_mark_used)]
async fn demo_spl_ata_derive(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSplAtaDerivationRequest,
) -> std::result::Result<crate::DemoSplAtaDerivationPayload, 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 wallet = match crate::load_profile_wallet(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let wallet_owner = wallet.public_key();
let token_program = match crate::parse_token_program(&request.token_program) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let associated_token_account = match crate::derive_ata(
wallet_owner.as_str(),
request.mint.trim(),
token_program.program_id(),
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(crate::DemoSplAtaDerivationPayload {
payer: wallet_owner.clone(),
wallet_owner,
token_program_id: token_program.program_id().to_string(),
associated_token_account,
});
}
/// Executes one representative Create or CreateIdempotent ATA flow.
#[tauri::command]
#[allow(clippy::question_mark_used)]
async fn demo_execution_spl_ata_execute(
app_handle: tauri::AppHandle,
state: tauri::State<'_, crate::AppState>,
request: crate::DemoExecutionSplAtaRequest,
) -> std::result::Result<crate::DemoExecutionSplAtaSummaryPayload, std::string::String> {
let acquired = state.demo_execution_solana_core_running().compare_exchange(
false,
true,
std::sync::atomic::Ordering::AcqRel,
std::sync::atomic::Ordering::Acquire,
);
if acquired.is_err() {
return std::result::Result::Err("a Devnet execution is already running".to_string());
}
let _run_guard = crate::DemoExecutionSolanaCoreRunGuard {
running: state.demo_execution_solana_core_running(),
};
state
.demo_execution_solana_core_cancel_requested()
.store(false, std::sync::atomic::Ordering::Release);
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 profile_wallet = match crate::load_profile_wallet(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
if request.wallet_owner.trim() != profile_wallet.public_key() {
return std::result::Result::Err(
"the representative ATA panel requires the profile wallet as wallet owner".to_string(),
);
}
let token_program = match crate::parse_token_program(&request.token_program) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let wallet_owner = kb_lib::MdPubkey(request.wallet_owner.trim().to_string());
let mint = kb_lib::MdPubkey(request.mint.trim().to_string());
let operation = match request.mode.as_str() {
"create" => kb_lib::ExSplAssociatedTokenAccountOperation::Create {
wallet_owner,
mint,
token_program,
},
"create_idempotent" => kb_lib::ExSplAssociatedTokenAccountOperation::CreateIdempotent {
wallet_owner,
mint,
token_program,
},
_ => {
return std::result::Result::Err(
"ATA mode must be create or create_idempotent".to_string(),
);
},
};
let mut pipeline_request =
kb_pipeline_demo_scenarios::DevnetSplAssociatedTokenAccountExecutionRequest::new(
format!("demo-spl-ata-execution-{}", chrono::Utc::now().timestamp_micros()),
operation,
);
pipeline_request.submit = request.submit;
pipeline_request.operator_confirmed = request.operator_confirmed;
pipeline_request.post_validation_max_retries = 20;
pipeline_request.force_post_validation_replay = request.force_post_validation_replay;
let http_pool = match kb_onchain_transport::HttpEndpointPool::from_profile(&profile) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let decoders: std::vec::Vec<std::sync::Arc<dyn kb_lib::DcApiInstructionDecoder>> = std::vec![
std::sync::Arc::new(kb_lib::DcSplAssociatedTokenAccountDecoder),
std::sync::Arc::new(kb_lib::DcSplTokenDecoder),
];
let materializers: std::vec::Vec<std::sync::Arc<dyn kb_lib::MtApiEventMaterializer>> = std::vec![
std::sync::Arc::new(kb_lib::MtTokenAccountsMaterializer),
std::sync::Arc::new(kb_lib::MtRiskMaterializer),
];
let observer = crate::DemoExecutionSolanaCoreObserver {
app_handle,
cancel_requested: state.demo_execution_solana_core_cancel_requested(),
};
let summary = match kb_pipeline_demo_scenarios::execute_devnet_spl_associated_token_account(
&http_pool,
&store,
&profile,
crate::workspace_root_dir().as_path(),
&pipeline_request,
decoders.as_slice(),
materializers.as_slice(),
&observer,
)
.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::demo_spl_ata_summary_payload(summary));
}
/// Loads a bounded journal of ATA-owned lifecycle facts.
#[tauri::command]
#[allow(clippy::question_mark_used)]
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());
}
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::connect_postgres_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let filter = match kb_store::MaterializedEventFilter::new(
std::option::Option::Some("spl_token_accounts".to_string()),
std::option::Option::None,
request.signature_contains.clone(),
500,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let rows = match kb_store::DecodePipelineStore::list_materialized_events(&store, &filter).await
{
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::new();
for row in rows {
if row.source_decoder_name != "spl_associated_token_account"
|| !crate::journal_matches(&row.payload_json, &request)
{
continue;
}
output.push(crate::journal_row(row));
if output.len() >= request.limit as usize {
break;
}
}
return std::result::Result::Ok(output);
}
/// Executes one public Token-2022 simulation or explicitly authorized Devnet submission.
#[tauri::command]
#[allow(clippy::question_mark_used)]
async fn demo_execution_spl_token2022_execute(
app_handle: tauri::AppHandle,
state: tauri::State<'_, crate::AppState>,
request: crate::DemoExecutionSplToken2022Request,
) -> std::result::Result<crate::DemoExecutionSplToken2022SummaryPayload, std::string::String> {
let acquire_result = state.demo_execution_solana_core_running().compare_exchange(
false,
true,
std::sync::atomic::Ordering::AcqRel,
std::sync::atomic::Ordering::Acquire,
);
if acquire_result.is_err() {
return std::result::Result::Err("a Devnet execution is already running".to_string());
}
let _run_guard = crate::DemoExecutionSolanaCoreRunGuard {
running: state.demo_execution_solana_core_running(),
};
state
.demo_execution_solana_core_cancel_requested()
.store(false, std::sync::atomic::Ordering::Release);
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 http_pool = match kb_onchain_transport::HttpEndpointPool::from_profile(&profile) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let operation = match crate::operation_from_request(&request) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let operation_code = operation.operation_code().to_string();
let mut pipeline_request = kb_pipeline_demo_scenarios::DevnetSplToken2022ExecutionRequest::new(
format!("demo-spl-token-2022-execution-{}", chrono::Utc::now().timestamp_micros()),
operation,
);
pipeline_request.submit = request.submit;
pipeline_request.operator_confirmed = request.operator_confirmed;
pipeline_request.post_validation_max_retries = 20;
pipeline_request.force_post_validation_replay = request.force_post_validation_replay;
let decoders: std::vec::Vec<std::sync::Arc<dyn kb_lib::DcApiInstructionDecoder>> =
std::vec![std::sync::Arc::new(kb_lib::DcSplToken2022Decoder)];
let materializers: std::vec::Vec<std::sync::Arc<dyn kb_lib::MtApiEventMaterializer>> = std::vec![
std::sync::Arc::new(kb_lib::MtTokenAccountsMaterializer),
std::sync::Arc::new(kb_lib::MtAdminMaterializer),
std::sync::Arc::new(kb_lib::MtRiskMaterializer),
std::sync::Arc::new(kb_lib::MtFeesMaterializer),
std::sync::Arc::new(kb_lib::MtComplianceAuditMaterializer),
];
let observer = crate::DemoExecutionSolanaCoreObserver {
app_handle,
cancel_requested: state.demo_execution_solana_core_cancel_requested(),
};
let workspace_root = crate::workspace_root_dir();
let summary = match kb_pipeline_demo_scenarios::execute_devnet_spl_token2022(
&http_pool,
&store,
&profile,
workspace_root.as_path(),
&pipeline_request,
decoders.as_slice(),
materializers.as_slice(),
&observer,
)
.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::demo_spl_token2022_summary_payload(
request.scenario_id,
operation_code,
summary,
));
}
/// Loads public Token-2022 fixture values without reading private key bytes.
#[tauri::command]
fn demo_spl_token2022_fixture(
state: tauri::State<'_, crate::AppState>,
profile_name: std::string::String,
) -> std::result::Result<crate::DemoSplToken2022FixturePayload, 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 configured = std::path::PathBuf::from(profile.wallet.wallet_dir.as_str());
let wallet_dir = if configured.is_absolute() {
configured
} else {
crate::workspace_root_dir().join(configured)
};
let fixture_path = wallet_dir.join("spl_token2022_validation").join("fixture.env");
let contents = match std::fs::read_to_string(&fixture_path) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(format!(
"unable to read Token-2022 fixture {}: {error}",
fixture_path.display()
));
},
};
let values = crate::parse_fixture(contents.as_str());
let required = |name: &str| -> std::result::Result<std::string::String, std::string::String> {
return match values.get(name) {
std::option::Option::Some(value) if !value.trim().is_empty() => {
std::result::Result::Ok(value.clone())
},
_ => std::result::Result::Err(format!("Token-2022 fixture is missing {name}")),
};
};
let program_id = match required("TOKEN_2022_PROGRAM") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mint = match required("TOKEN_2022_MINT") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let source = match required("TOKEN_2022_SOURCE") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let destination = match required("TOKEN_2022_DESTINATION") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let close_account = match required("TOKEN_2022_CLOSE_ACCOUNT") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let delegate = match required("TOKEN_2022_DELEGATE") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let authority = match required("TOKEN_2022_AUTHORITY") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let freeze_authority = match required("TOKEN_2022_FREEZE_AUTHORITY") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let decimals_text = match required("TOKEN_2022_DECIMALS") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let decimals = match decimals_text.parse::<u8>() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(format!("invalid TOKEN_2022_DECIMALS value: {error}"));
},
};
return std::result::Result::Ok(crate::DemoSplToken2022FixturePayload {
fixture_path: fixture_path.display().to_string(),
program_id,
mint,
source,
destination,
close_account,
delegate,
authority,
freeze_authority,
decimals,
default_amount_raw: values
.get("TOKEN_2022_TRANSFER_AMOUNT_RAW")
.cloned()
.unwrap_or_else(|| return "1".to_string()),
});
}