v0.3.8-pre.008
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-store-desk/src/app_state.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
//! Shared backend state owned by the Store Desk Tauri application.
|
||||
|
||||
@@ -105,7 +105,7 @@ impl crate::AppState {
|
||||
application_version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||
config_document_count: document_count,
|
||||
fallback_logging_active: runtime.fallback_active,
|
||||
shell_phase: "pre.007-raw-transactions".to_owned(),
|
||||
shell_phase: "pre.008-raw-accounts".to_owned(),
|
||||
startup_diagnostic: runtime.startup_diagnostic.clone(),
|
||||
});
|
||||
}
|
||||
@@ -115,6 +115,16 @@ impl crate::AppState {
|
||||
return self.store_startup.status().await;
|
||||
}
|
||||
|
||||
/// Executes one bounded RAW account-state inspection query through the retained Store facade.
|
||||
pub(crate) async fn query_accounts(&self, request: crate::StoreAccountQueryRequestDto) -> ksp_core_lib::Result<crate::StoreAccountQueryResponseDto> {
|
||||
return self.store_startup.query_accounts(request).await;
|
||||
}
|
||||
|
||||
/// Loads one explicit RAW account-state detail through the retained Store facade.
|
||||
pub(crate) async fn account_detail(&self, request: crate::StoreAccountDetailRequestDto) -> ksp_core_lib::Result<crate::StoreAccountDetailDto> {
|
||||
return self.store_startup.account_detail(request).await;
|
||||
}
|
||||
|
||||
/// Executes one bounded RAW transaction inspection query through the retained Store facade.
|
||||
pub(crate) async fn query_transactions(
|
||||
&self,
|
||||
|
||||
105
crates/ksp-app-store-desk/src/dto_account.rs
Normal file
105
crates/ksp-app-store-desk/src/dto_account.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
// file: crates/ksp-app-store-desk/src/dto_account.rs
|
||||
// version: 1
|
||||
|
||||
//! Application-owned DTOs for RAW account-state inspection and detail commands.
|
||||
|
||||
use ts_rs::TS; // rust-rules: trait-import
|
||||
|
||||
/// Bounded Store-owned query request projected from one DataTables page request.
|
||||
#[derive(Debug, serde::Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_store_desk/dto_account/StoreAccountQueryRequestDto.ts")]
|
||||
pub(crate) struct StoreAccountQueryRequestDto {
|
||||
/// Stable Store sort direction code (`ascending` or `descending`).
|
||||
pub(crate) direction: String,
|
||||
/// Whitelisted page size (`25`, `50`, or `100`).
|
||||
pub(crate) limit: u32,
|
||||
/// Absolute zero-based inspection offset encoded as exact decimal text.
|
||||
pub(crate) offset: String,
|
||||
/// Optional exact account public key in canonical base58 text.
|
||||
pub(crate) pubkey: std::option::Option<String>,
|
||||
/// Optional inclusive maximum slot encoded as decimal text.
|
||||
pub(crate) slot_max: std::option::Option<String>,
|
||||
/// Optional inclusive minimum slot encoded as decimal text.
|
||||
pub(crate) slot_min: std::option::Option<String>,
|
||||
}
|
||||
|
||||
/// Data-free RAW account-state row returned to the server-side DataTables adapter.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_store_desk/dto_account/StoreAccountRowDto.ts")]
|
||||
pub(crate) struct StoreAccountRowDto {
|
||||
/// Exact complete account-data length encoded as decimal text.
|
||||
pub(crate) data_length_decimal: String,
|
||||
/// Whether the account is executable.
|
||||
pub(crate) executable: bool,
|
||||
/// Exact lamport balance encoded as decimal text.
|
||||
pub(crate) lamports_decimal: String,
|
||||
/// Account owner program public key in canonical base58 text.
|
||||
pub(crate) owner: String,
|
||||
/// Account public key in canonical base58 text.
|
||||
pub(crate) pubkey: String,
|
||||
/// Exact rent epoch encoded as decimal text.
|
||||
pub(crate) rent_epoch_decimal: String,
|
||||
/// Solana slot encoded as exact decimal text.
|
||||
pub(crate) slot_decimal: String,
|
||||
/// Canonical account-state hash encoded as lower-case hexadecimal text.
|
||||
pub(crate) state_hash: String,
|
||||
}
|
||||
|
||||
/// Server-side account-state table result using exact decimal counts.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_store_desk/dto_account/StoreAccountQueryResponseDto.ts")]
|
||||
pub(crate) struct StoreAccountQueryResponseDto {
|
||||
/// Exact count after optional Store filters.
|
||||
pub(crate) records_filtered_decimal: String,
|
||||
/// Exact count in the mandatory Store network scope before optional filters.
|
||||
pub(crate) records_total_decimal: String,
|
||||
/// Data-free inspection rows for the requested random-access page.
|
||||
pub(crate) rows: std::vec::Vec<crate::StoreAccountRowDto>,
|
||||
}
|
||||
|
||||
/// App-owned identity request for one explicit RAW account-state detail load.
|
||||
#[derive(Debug, serde::Deserialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_store_desk/dto_account/StoreAccountDetailRequestDto.ts")]
|
||||
pub(crate) struct StoreAccountDetailRequestDto {
|
||||
/// Account public key in canonical base58 text.
|
||||
pub(crate) pubkey: String,
|
||||
/// Solana slot encoded as exact decimal text.
|
||||
pub(crate) slot: String,
|
||||
/// Canonical account-state hash encoded as lower-case hexadecimal text.
|
||||
pub(crate) state_hash: String,
|
||||
}
|
||||
|
||||
/// Bounded detail projection for one complete RAW account state.
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_store_desk/dto_account/StoreAccountDetailDto.ts")]
|
||||
pub(crate) struct StoreAccountDetailDto {
|
||||
/// Exact complete account-data length encoded as decimal text.
|
||||
pub(crate) data_length_decimal: String,
|
||||
/// Bounded lower-case hexadecimal preview of complete canonical account data.
|
||||
pub(crate) data_preview_hex: String,
|
||||
/// Whether complete account data is larger than the returned preview.
|
||||
pub(crate) data_preview_truncated: bool,
|
||||
/// Whether the account is executable.
|
||||
pub(crate) executable: bool,
|
||||
/// Exact lamport balance encoded as decimal text.
|
||||
pub(crate) lamports_decimal: String,
|
||||
/// Account owner program public key in canonical base58 text.
|
||||
pub(crate) owner: String,
|
||||
/// Account public key in canonical base58 text.
|
||||
pub(crate) pubkey: String,
|
||||
/// Exact rent epoch encoded as decimal text.
|
||||
pub(crate) rent_epoch_decimal: String,
|
||||
/// Solana slot encoded as exact decimal text.
|
||||
pub(crate) slot_decimal: String,
|
||||
/// Canonical account-state hash encoded as lower-case hexadecimal text.
|
||||
pub(crate) state_hash: String,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "../unit_tests/dto_account.rs"]
|
||||
mod tests;
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-store-desk/src/errors.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
//! Application-local error codes for Store Desk desktop runtime surfaces.
|
||||
|
||||
@@ -19,7 +19,9 @@ pub(crate) const ERROR_CODE_LOGGING_BOOTSTRAP_FAILED: ksp_core_lib::ErrorCode =
|
||||
pub(crate) const ERROR_CODE_SPLASH_ORIGIN_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("store_desk", "splash_origin_invalid");
|
||||
/// A KSP desk splash environment duration is malformed or exceeds its safety bound.
|
||||
pub(crate) const ERROR_CODE_SPLASH_SETTING_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("store_desk", "splash_setting_invalid");
|
||||
/// Store Desk received an invalid transaction inspection/detail request.
|
||||
/// Store Desk could not resolve the requested RAW account-state identity to a coherent Store entity.
|
||||
pub(crate) const ERROR_CODE_STORE_ACCOUNT_NOT_FOUND: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("store_desk", "store_account_not_found");
|
||||
/// Store Desk received an invalid RAW inspection/detail request.
|
||||
pub(crate) const ERROR_CODE_STORE_QUERY_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("store_desk", "store_query_invalid");
|
||||
/// Store Desk cannot serve a Store command because the runtime is unavailable or already closed.
|
||||
pub(crate) const ERROR_CODE_STORE_RUNTIME_UNAVAILABLE: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("store_desk", "store_runtime_unavailable");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-store-desk/src/lib.rs
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
//! Tauri desktop scaffold for backend-neutral KSP Store inspection.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
mod app_state;
|
||||
mod bootstrap;
|
||||
mod constants;
|
||||
mod dto_account;
|
||||
mod dto_common;
|
||||
mod dto_transaction;
|
||||
mod errors;
|
||||
@@ -60,6 +61,16 @@ pub(crate) use self::constants::TRACING_TARGET_FRONTEND;
|
||||
pub(crate) use self::constants::TRACING_TARGET_FRONTEND_MAIN;
|
||||
/// Owning target for splash-window frontend events.
|
||||
pub(crate) use self::constants::TRACING_TARGET_FRONTEND_SPLASH;
|
||||
/// Bounded detail projection for one complete RAW account state.
|
||||
pub(crate) use self::dto_account::StoreAccountDetailDto;
|
||||
/// App-owned identity request for one explicit RAW account-state detail load.
|
||||
pub(crate) use self::dto_account::StoreAccountDetailRequestDto;
|
||||
/// Bounded Store-owned account query request projected from one DataTables page request.
|
||||
pub(crate) use self::dto_account::StoreAccountQueryRequestDto;
|
||||
/// Server-side account-state table result using exact decimal counts.
|
||||
pub(crate) use self::dto_account::StoreAccountQueryResponseDto;
|
||||
/// Data-free RAW account-state row returned to the server-side DataTables adapter.
|
||||
pub(crate) use self::dto_account::StoreAccountRowDto;
|
||||
/// Safe command error projection exposed to Tauri commands.
|
||||
pub(crate) use self::dto_common::CommandErrorDto;
|
||||
/// Safe shell/Config/Logging snapshot exposed to the shell.
|
||||
@@ -92,6 +103,8 @@ pub(crate) use self::errors::ERROR_CODE_LOGGING_BOOTSTRAP_FAILED;
|
||||
pub(crate) use self::errors::ERROR_CODE_SPLASH_ORIGIN_INVALID;
|
||||
/// A KSP desk splash environment duration is malformed or exceeds its safety bound.
|
||||
pub(crate) use self::errors::ERROR_CODE_SPLASH_SETTING_INVALID;
|
||||
/// Store Desk could not resolve the requested RAW account-state identity to a coherent Store entity.
|
||||
pub(crate) use self::errors::ERROR_CODE_STORE_ACCOUNT_NOT_FOUND;
|
||||
/// Store Desk received an invalid transaction inspection/detail request.
|
||||
pub(crate) use self::errors::ERROR_CODE_STORE_QUERY_INVALID;
|
||||
/// Store Desk cannot serve a Store command because the runtime is unavailable or already closed.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-store-desk/src/store_runtime.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
//! Composite-selected Store readiness, status and bounded shutdown lifecycle owned by Store Desk.
|
||||
|
||||
@@ -35,6 +35,24 @@ impl crate::StoreStartup {
|
||||
};
|
||||
}
|
||||
|
||||
/// Executes one bounded server-side RAW account-state inspection query.
|
||||
pub(crate) async fn query_accounts(&self, request: crate::StoreAccountQueryRequestDto) -> ksp_core_lib::Result<crate::StoreAccountQueryResponseDto> {
|
||||
let runtime = self.runtime.as_ref();
|
||||
return match runtime {
|
||||
std::option::Option::Some(value) => value.query_accounts(request).await,
|
||||
std::option::Option::None => std::result::Result::Err(store_runtime_unavailable()),
|
||||
};
|
||||
}
|
||||
|
||||
/// Loads one explicit bounded RAW account-state detail projection.
|
||||
pub(crate) async fn account_detail(&self, request: crate::StoreAccountDetailRequestDto) -> ksp_core_lib::Result<crate::StoreAccountDetailDto> {
|
||||
let runtime = self.runtime.as_ref();
|
||||
return match runtime {
|
||||
std::option::Option::Some(value) => value.account_detail(request).await,
|
||||
std::option::Option::None => std::result::Result::Err(store_runtime_unavailable()),
|
||||
};
|
||||
}
|
||||
|
||||
/// Executes one bounded server-side RAW transaction inspection query.
|
||||
pub(crate) async fn query_transactions(
|
||||
&self,
|
||||
@@ -116,6 +134,56 @@ impl crate::StoreRuntime {
|
||||
};
|
||||
}
|
||||
|
||||
/// Executes one validated random-access account-state inspection query while retaining the Store read guard.
|
||||
pub(crate) async fn query_accounts(&self, request: crate::StoreAccountQueryRequestDto) -> ksp_core_lib::Result<crate::StoreAccountQueryResponseDto> {
|
||||
let locked = self.store.read().await;
|
||||
let store = locked.as_ref();
|
||||
let store = match store {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return std::result::Result::Err(store_runtime_unavailable()),
|
||||
};
|
||||
let query = account_query_from_request(store, &request);
|
||||
let query = match query {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let page = ksp_store_lib::RawAccountStateInspectionRead::inspect_raw_account_states(store, &query).await;
|
||||
let page = match page {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let records_total_decimal = page.total_items().to_string();
|
||||
let records_filtered_decimal = page.filtered_items().to_string();
|
||||
let items = page.into_items();
|
||||
let mut rows = std::vec::Vec::with_capacity(items.len());
|
||||
for item in items {
|
||||
rows.push(account_row_dto(&item));
|
||||
}
|
||||
return std::result::Result::Ok(crate::StoreAccountQueryResponseDto { records_filtered_decimal, records_total_decimal, rows });
|
||||
}
|
||||
|
||||
/// Loads one account-state detail by application-owned row identity without exposing Store network selection to the frontend.
|
||||
pub(crate) async fn account_detail(&self, request: crate::StoreAccountDetailRequestDto) -> ksp_core_lib::Result<crate::StoreAccountDetailDto> {
|
||||
let locked = self.store.read().await;
|
||||
let store = locked.as_ref();
|
||||
let store = match store {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return std::result::Result::Err(store_runtime_unavailable()),
|
||||
};
|
||||
let reference = account_reference_from_request(store, &request);
|
||||
let reference = match reference {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let state = ksp_store_lib::RawAccountStateRead::get_raw_account_state(store, &reference).await;
|
||||
let state = match state {
|
||||
std::result::Result::Ok(std::option::Option::Some(value)) => value,
|
||||
std::result::Result::Ok(std::option::Option::None) => return std::result::Result::Err(store_account_not_found()),
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
return std::result::Result::Ok(account_detail_dto(&state));
|
||||
}
|
||||
|
||||
/// Executes one validated random-access transaction inspection query while retaining the Store read guard.
|
||||
pub(crate) async fn query_transactions(
|
||||
&self,
|
||||
@@ -210,8 +278,111 @@ impl crate::StoreRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
const ACCOUNT_DETAIL_PREVIEW_BYTES: usize = 512;
|
||||
const TRANSACTION_DETAIL_PREVIEW_BYTES: usize = 512;
|
||||
|
||||
fn account_query_from_request(
|
||||
store: &ksp_store_lib::Store,
|
||||
request: &crate::StoreAccountQueryRequestDto,
|
||||
) -> ksp_core_lib::Result<ksp_store_lib::RawAccountStateInspectionQuery> {
|
||||
let limit = match request.limit {
|
||||
25 | 50 | 100 => ksp_store_lib::RawPageLimit::new(u64::from(request.limit)),
|
||||
_ => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
let limit = match limit {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
let offset = request.offset.parse::<u64>();
|
||||
let offset = match offset {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
let pubkey = parse_optional_pubkey(request.pubkey.as_deref());
|
||||
let pubkey = match pubkey {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let slot_min = parse_optional_decimal_u64(request.slot_min.as_deref());
|
||||
let slot_min = match slot_min {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let slot_max = parse_optional_decimal_u64(request.slot_max.as_deref());
|
||||
let slot_max = match slot_max {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let slots = ksp_store_lib::RawSlotRange::new(slot_min, slot_max);
|
||||
let slots = match slots {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
let direction = match request.direction.as_str() {
|
||||
"ascending" => ksp_store_lib::RawSortDirection::Ascending,
|
||||
"descending" => ksp_store_lib::RawSortDirection::Descending,
|
||||
_ => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
let network = store.runtime_snapshot().network().clone();
|
||||
let page = ksp_store_lib::RawInspectionPageRequest::new(offset, limit);
|
||||
return std::result::Result::Ok(ksp_store_lib::RawAccountStateInspectionQuery::new(network, pubkey, slots, direction, page));
|
||||
}
|
||||
|
||||
fn account_reference_from_request(
|
||||
store: &ksp_store_lib::Store,
|
||||
request: &crate::StoreAccountDetailRequestDto,
|
||||
) -> ksp_core_lib::Result<ksp_store_lib::RawAccountStateReference> {
|
||||
let pubkey = request.pubkey.parse::<ksp_store_lib::Pubkey>();
|
||||
let pubkey = match pubkey {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
let slot = request.slot.parse::<u64>();
|
||||
let slot = match slot {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
let state_hash = decode_hex_32(request.state_hash.as_str());
|
||||
let state_hash = match state_hash {
|
||||
std::result::Result::Ok(value) => ksp_store_lib::RawContentHash::new(value),
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let network = store.runtime_snapshot().network().clone();
|
||||
return std::result::Result::Ok(ksp_store_lib::RawAccountStateReference::new(network, pubkey, slot, state_hash));
|
||||
}
|
||||
|
||||
fn account_detail_dto(state: &ksp_store_lib::RawAccountState) -> crate::StoreAccountDetailDto {
|
||||
let data = state.data();
|
||||
let preview_len = std::cmp::min(data.len(), ACCOUNT_DETAIL_PREVIEW_BYTES);
|
||||
let state_hash = state.reference().state_hash();
|
||||
return crate::StoreAccountDetailDto {
|
||||
data_length_decimal: state.data_len().to_string(),
|
||||
data_preview_hex: encode_hex(&data[..preview_len]),
|
||||
data_preview_truncated: data.len() > preview_len,
|
||||
executable: state.executable(),
|
||||
lamports_decimal: state.lamports().to_string(),
|
||||
owner: state.owner().to_string(),
|
||||
pubkey: state.reference().pubkey().to_string(),
|
||||
rent_epoch_decimal: state.rent_epoch().to_string(),
|
||||
slot_decimal: state.reference().slot().to_string(),
|
||||
state_hash: encode_hex(state_hash.as_bytes()),
|
||||
};
|
||||
}
|
||||
|
||||
fn account_row_dto(summary: &ksp_store_lib::RawAccountStateSummary) -> crate::StoreAccountRowDto {
|
||||
let state_hash = summary.reference().state_hash();
|
||||
return crate::StoreAccountRowDto {
|
||||
data_length_decimal: summary.data_length_bytes().to_string(),
|
||||
executable: summary.executable(),
|
||||
lamports_decimal: summary.lamports().to_string(),
|
||||
owner: summary.owner().to_string(),
|
||||
pubkey: summary.reference().pubkey().to_string(),
|
||||
rent_epoch_decimal: summary.rent_epoch().to_string(),
|
||||
slot_decimal: summary.reference().slot().to_string(),
|
||||
state_hash: encode_hex(state_hash.as_bytes()),
|
||||
};
|
||||
}
|
||||
|
||||
fn transaction_query_from_request(
|
||||
store: &ksp_store_lib::Store,
|
||||
request: &crate::StoreTransactionQueryRequestDto,
|
||||
@@ -350,6 +521,16 @@ fn retention_state_code(state: ksp_store_lib::RawRetentionState) -> &'static str
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_optional_pubkey(value: std::option::Option<&str>) -> ksp_core_lib::Result<std::option::Option<ksp_store_lib::Pubkey>> {
|
||||
return match value {
|
||||
std::option::Option::Some(text) => match text.parse::<ksp_store_lib::Pubkey>() {
|
||||
std::result::Result::Ok(parsed) => std::result::Result::Ok(std::option::Option::Some(parsed)),
|
||||
std::result::Result::Err(_) => std::result::Result::Err(store_query_invalid()),
|
||||
},
|
||||
std::option::Option::None => std::result::Result::Ok(std::option::Option::None),
|
||||
};
|
||||
}
|
||||
|
||||
fn parse_optional_decimal_u64(value: std::option::Option<&str>) -> ksp_core_lib::Result<std::option::Option<u64>> {
|
||||
return match value {
|
||||
std::option::Option::Some(text) => match text.parse::<u64>() {
|
||||
@@ -360,6 +541,24 @@ fn parse_optional_decimal_u64(value: std::option::Option<&str>) -> ksp_core_lib:
|
||||
};
|
||||
}
|
||||
|
||||
fn decode_hex_32(value: &str) -> ksp_core_lib::Result<[u8; 32]> {
|
||||
if value.len() != 64 || !value.is_ascii() {
|
||||
return std::result::Result::Err(store_query_invalid());
|
||||
}
|
||||
let source = value.as_bytes();
|
||||
let mut decoded = [0_u8; 32];
|
||||
for index in 0..32 {
|
||||
let high = decode_hex_nibble(source[index * 2]);
|
||||
let low = decode_hex_nibble(source[index * 2 + 1]);
|
||||
let (high, low) = match (high, low) {
|
||||
(std::option::Option::Some(high), std::option::Option::Some(low)) => (high, low),
|
||||
_ => return std::result::Result::Err(store_query_invalid()),
|
||||
};
|
||||
decoded[index] = (high << 4) | low;
|
||||
}
|
||||
return std::result::Result::Ok(decoded);
|
||||
}
|
||||
|
||||
fn decode_hex_64(value: &str) -> ksp_core_lib::Result<[u8; 64]> {
|
||||
if value.len() != 128 || !value.is_ascii() {
|
||||
return std::result::Result::Err(store_query_invalid());
|
||||
@@ -398,8 +597,12 @@ fn encode_hex(bytes: &[u8]) -> String {
|
||||
return encoded;
|
||||
}
|
||||
|
||||
fn store_account_not_found() -> ksp_core_lib::Error {
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_STORE_ACCOUNT_NOT_FOUND, "Store Desk account state was not found");
|
||||
}
|
||||
|
||||
fn store_query_invalid() -> ksp_core_lib::Error {
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_STORE_QUERY_INVALID, "Store Desk transaction query is invalid");
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_STORE_QUERY_INVALID, "Store Desk RAW inspection/detail request is invalid");
|
||||
}
|
||||
|
||||
fn store_runtime_unavailable() -> ksp_core_lib::Error {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-store-desk/src/tauri.rs
|
||||
// version: 3
|
||||
// version: 4
|
||||
|
||||
//! Tauri runtime assembly for the KSP Store desktop application.
|
||||
|
||||
@@ -79,7 +79,9 @@ fn configure_commands(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tau
|
||||
emit_frontend_log,
|
||||
get_shell_status,
|
||||
splash_frontend_ready,
|
||||
store_get_account_detail,
|
||||
store_get_transaction_detail,
|
||||
store_query_accounts,
|
||||
store_query_transactions,
|
||||
store_runtime_status,
|
||||
]);
|
||||
@@ -174,6 +176,30 @@ fn get_shell_status(state: tauri::State<'_, crate::AppState>) -> std::result::Re
|
||||
};
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn store_query_accounts(
|
||||
request: crate::StoreAccountQueryRequestDto,
|
||||
state: tauri::State<'_, crate::AppState>,
|
||||
) -> std::result::Result<crate::StoreAccountQueryResponseDto, crate::CommandErrorDto> {
|
||||
let result = state.query_accounts(request).await;
|
||||
return match result {
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(project_command_error("store_query_accounts", crate::TRACING_DOMAIN_STORE, &error)),
|
||||
};
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn store_get_account_detail(
|
||||
request: crate::StoreAccountDetailRequestDto,
|
||||
state: tauri::State<'_, crate::AppState>,
|
||||
) -> std::result::Result<crate::StoreAccountDetailDto, crate::CommandErrorDto> {
|
||||
let result = state.account_detail(request).await;
|
||||
return match result {
|
||||
std::result::Result::Ok(value) => std::result::Result::Ok(value),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(project_command_error("store_get_account_detail", crate::TRACING_DOMAIN_STORE, &error)),
|
||||
};
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn store_query_transactions(
|
||||
request: crate::StoreTransactionQueryRequestDto,
|
||||
|
||||
Reference in New Issue
Block a user