v0.2.6-pre.008
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/src/app_state.rs
|
||||
// version: 8
|
||||
// version: 9
|
||||
|
||||
//! Shared backend state owned by the Wallet Desk Tauri application.
|
||||
|
||||
@@ -11,6 +11,7 @@ pub(crate) struct AppState {
|
||||
splash_sequence_started: std::sync::atomic::AtomicBool,
|
||||
transport_runtime: crate::TransportRuntime,
|
||||
wallet_config_startup: crate::WalletConfigStartup,
|
||||
wallet_import_source: std::sync::Mutex<std::option::Option<crate::PendingWalletImport>>,
|
||||
wallet_session: std::sync::Mutex<crate::WalletSession>,
|
||||
}
|
||||
|
||||
@@ -69,6 +70,7 @@ impl AppState {
|
||||
splash_sequence_started: std::sync::atomic::AtomicBool::new(false),
|
||||
transport_runtime,
|
||||
wallet_config_startup,
|
||||
wallet_import_source: std::sync::Mutex::new(std::option::Option::None),
|
||||
wallet_session: std::sync::Mutex::new(crate::WalletSession::no_selection()),
|
||||
});
|
||||
}
|
||||
@@ -124,7 +126,7 @@ impl AppState {
|
||||
effective_wallets_directory_created_on_startup: self.wallet_config_startup.effective_directory_created_on_startup(),
|
||||
fallback_logging_active: runtime.fallback_active,
|
||||
root_wallets_directory_created_on_startup: self.wallet_config_startup.root_directory_created_on_startup(),
|
||||
shell_phase: "pre.007-wallet-balance".to_owned(),
|
||||
shell_phase: "pre.008-wallet-import".to_owned(),
|
||||
startup_diagnostic: runtime.startup_diagnostic.clone(),
|
||||
transport_available_endpoint_count,
|
||||
transport_clusters: self.transport_runtime.clusters(),
|
||||
@@ -220,6 +222,102 @@ impl AppState {
|
||||
return std::result::Result::Ok(dto);
|
||||
}
|
||||
|
||||
/// Replaces any previous native-picker transfer source with one newly validated bounded Rust-only source.
|
||||
pub(crate) async fn stage_import_source(
|
||||
&self,
|
||||
source: std::path::PathBuf,
|
||||
format: crate::WalletTransferFormatDto,
|
||||
) -> ksp_core_lib::Result<crate::WalletTransferInspectionDto> {
|
||||
let staged = crate::stage_wallet_import_source(source, format).await;
|
||||
let staged = match staged {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let dto = staged.safe_projection();
|
||||
let slot = self.wallet_import_source.lock();
|
||||
let mut slot = match slot {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(import_source_lock_error()),
|
||||
};
|
||||
let previous = std::mem::replace(&mut *slot, std::option::Option::Some(staged));
|
||||
drop(previous);
|
||||
ksp_logging_lib::info!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WALLET_IMPORT, transfer_format = dto.format.code(), "Wallet transfer source inspected and staged in Rust-only memory");
|
||||
return std::result::Result::Ok(dto);
|
||||
}
|
||||
|
||||
/// Clears any staged external transfer source and zeroizes its bounded secret bytes.
|
||||
pub(crate) fn clear_import_source(&self) -> ksp_core_lib::Result<()> {
|
||||
let slot = self.wallet_import_source.lock();
|
||||
let mut slot = match slot {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(import_source_lock_error()),
|
||||
};
|
||||
let previous = slot.take();
|
||||
drop(previous);
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
/// Imports the staged Solana transfer bytes into a new root-scoped native Wallet and retains the returned OWNER handle only in Rust.
|
||||
pub(crate) async fn import_wallet(&self, request: crate::WalletImportRequestDto) -> ksp_core_lib::Result<crate::WalletAuthorizedDto> {
|
||||
let pending = {
|
||||
let slot = self.wallet_import_source.lock();
|
||||
let mut slot = match slot {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(import_source_lock_error()),
|
||||
};
|
||||
slot.take()
|
||||
};
|
||||
let pending = match pending {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => {
|
||||
return std::result::Result::Err(ksp_core_lib::Error::new(
|
||||
crate::ERROR_CODE_WALLET_IMPORT_SOURCE_MISSING,
|
||||
"Wallet import requires one inspected native-picker transfer source",
|
||||
));
|
||||
},
|
||||
};
|
||||
let deselected = self.deselect_wallet();
|
||||
if let std::result::Result::Err(error) = deselected {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let crate::WalletImportRequestDto { alias, filename, initial_note, owner_password, view_password } = request;
|
||||
let root = self.wallet_inventory_root().to_path_buf();
|
||||
let destination = crate::new_wallet_destination(root.as_path(), filename.as_str());
|
||||
let destination = match destination {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let view_enabled = view_password.is_some();
|
||||
let owner_password = ksp_wallet_lib::OwnerPassword::new(owner_password);
|
||||
let view_password = view_password.map(ksp_wallet_lib::ViewPassword::new);
|
||||
let alias = normalize_optional_text(alias);
|
||||
let note = normalize_optional_text(initial_note);
|
||||
let note_texts = note.into_iter().collect::<std::vec::Vec<_>>();
|
||||
let metadata = ksp_wallet_lib::WalletCreateMetadataV1::new(alias, note_texts);
|
||||
let transfer_format = pending.wallet_format();
|
||||
ksp_logging_lib::debug!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WALLET_IMPORT, wallet_id = filename.as_str(), transfer_format = transfer_format.code(), view_enabled, "Wallet transfer import requested under effective Config root");
|
||||
let imported =
|
||||
ksp_wallet_lib::import_wallet_transfer_v1(destination.as_path(), pending.source_bytes(), transfer_format, owner_password, view_password, metadata)
|
||||
.await;
|
||||
let owner = match imported {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => {
|
||||
ksp_logging_lib::warn!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WALLET_IMPORT, wallet_id = filename.as_str(), transfer_format = transfer_format.code(), error_domain = error.code().domain(), error_code = error.code().code(), "Wallet transfer import failed");
|
||||
return std::result::Result::Err(error);
|
||||
},
|
||||
};
|
||||
let configured_secret_candidate_count = self.secret_candidate_count_or_zero(filename.as_str());
|
||||
let dto = crate::owner_projection(filename.as_str(), view_enabled, configured_secret_candidate_count, &owner);
|
||||
let session = self.wallet_session.lock();
|
||||
let mut session = match session {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(session_lock_error()),
|
||||
};
|
||||
*session = crate::WalletSession::Owner { wallet_id: filename.clone(), path: destination, wallet: std::boxed::Box::new(owner) };
|
||||
ksp_logging_lib::info!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_WALLET_IMPORT, wallet_id = filename.as_str(), transfer_format = transfer_format.code(), view_enabled, "Wallet transfer imported and OWNER session opened");
|
||||
return std::result::Result::Ok(dto);
|
||||
}
|
||||
|
||||
/// Opens the selected locked Wallet with one manual VIEW password supplied frontend -> Rust.
|
||||
pub(crate) async fn unlock_wallet_view_manual(&self, request: crate::WalletUnlockRequestDto) -> ksp_core_lib::Result<crate::WalletAuthorizedDto> {
|
||||
let context = self.begin_unlock_operation(crate::WalletUnlockCapability::View);
|
||||
@@ -656,6 +754,10 @@ fn normalize_optional_text(value: std::option::Option<String>) -> std::option::O
|
||||
});
|
||||
}
|
||||
|
||||
fn import_source_lock_error() -> ksp_core_lib::Error {
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_APP_STATE_LOCK_FAILED, "Wallet Desk staged import source lock is poisoned");
|
||||
}
|
||||
|
||||
fn session_lock_error() -> ksp_core_lib::Error {
|
||||
return ksp_core_lib::Error::new(crate::ERROR_CODE_APP_STATE_LOCK_FAILED, "Wallet Desk Wallet session state lock is poisoned");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user