mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-06-29 10:29:32 +00:00
feat(wallet-ffi): add path-free wallet create/open and default-path helpers
Wallet consumers (e.g. the Qt module and apps built on it) currently have to reconstruct LEZ's wallet path layout themselves to call create/open, which duplicates the logic in `wallet::helperfunctions` and silently drifts if the default home or filenames change. Add functions that resolve everything from LEZ's canonical home (`LEE_WALLET_HOME_DIR` or `~/.lee/wallet`): - `wallet_ffi_create_new_default(password)` — create at the default home (resolves paths, creates the directory), path-free `wallet_ffi_create_new`. - `wallet_ffi_open_default()` — open the default wallet via `WalletCore::from_env`. - `wallet_ffi_default_config_path()` / `wallet_ffi_default_storage_path()` — return the resolved paths (caller frees with `wallet_ffi_free_string`). - `wallet_ffi_wallet_exists_default()` — whether a wallet already exists at the default home, for choosing between an open and a create flow. Together these let consumers drop their own path handling entirely. The C header (`wallet_ffi.h`) is regenerated by the cbindgen build step.
This commit is contained in:
parent
64f8444a67
commit
e2d73820cf
@ -178,6 +178,192 @@ pub unsafe extern "C" fn wallet_ffi_open(
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve LEZ's canonical wallet paths (`LEE_WALLET_HOME_DIR` or `~/.lee/wallet`)
|
||||
/// and ensure the home directory exists. Centralizes the path layout so callers
|
||||
/// don't have to reconstruct it.
|
||||
fn default_wallet_paths() -> Result<(PathBuf, PathBuf), WalletFfiError> {
|
||||
let home = wallet::helperfunctions::get_home().map_err(|e| {
|
||||
print_error(format!("Failed to resolve wallet home: {e}"));
|
||||
WalletFfiError::InternalError
|
||||
})?;
|
||||
|
||||
if let Err(e) = std::fs::create_dir_all(&home) {
|
||||
print_error(format!(
|
||||
"Failed to create wallet home {}: {e}",
|
||||
home.display()
|
||||
));
|
||||
return Err(WalletFfiError::StorageError);
|
||||
}
|
||||
|
||||
let config_path = wallet::helperfunctions::fetch_config_path().map_err(|e| {
|
||||
print_error(format!("Failed to resolve config path: {e}"));
|
||||
WalletFfiError::InternalError
|
||||
})?;
|
||||
let storage_path = wallet::helperfunctions::fetch_persistent_storage_path().map_err(|e| {
|
||||
print_error(format!("Failed to resolve storage path: {e}"));
|
||||
WalletFfiError::InternalError
|
||||
})?;
|
||||
|
||||
Ok((config_path, storage_path))
|
||||
}
|
||||
|
||||
/// Create a new wallet at LEZ's canonical home, deriving the paths from the
|
||||
/// environment (`LEE_WALLET_HOME_DIR` or `~/.lee/wallet`) and creating the
|
||||
/// directory if needed.
|
||||
///
|
||||
/// This is the path-free equivalent of [`wallet_ffi_create_new`]: callers that
|
||||
/// just want the default location don't have to reconstruct LEZ's path layout.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `password`: Password for encrypting the wallet seed
|
||||
///
|
||||
/// # Returns
|
||||
/// - Result, which contains opaque wallet handle and mnemonic words on success
|
||||
/// - Result with null pointers on error (call `wallet_ffi_get_last_error()` for details)
|
||||
///
|
||||
/// # Safety
|
||||
/// `password` must be a valid null-terminated UTF-8 string.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_create_new_default(
|
||||
password: *const c_char,
|
||||
) -> FfiCreateWalletOutput {
|
||||
let Ok(password) = c_str_to_string(password, "password") else {
|
||||
return FfiCreateWalletOutput::default();
|
||||
};
|
||||
|
||||
let Ok((config_path, storage_path)) = default_wallet_paths() else {
|
||||
return FfiCreateWalletOutput::default();
|
||||
};
|
||||
|
||||
match WalletCore::new_init_storage(config_path, storage_path, None, &password) {
|
||||
Ok((core, mnemonic)) => {
|
||||
let wrapper = Box::new(WalletWrapper {
|
||||
core: Mutex::new(core),
|
||||
});
|
||||
let handle = Box::into_raw(wrapper).cast::<WalletHandle>();
|
||||
|
||||
let Ok(c_mnemonic_string) = CString::new(mnemonic.to_string()) else {
|
||||
return FfiCreateWalletOutput::default();
|
||||
};
|
||||
|
||||
let raw_pointer = CString::into_raw(c_mnemonic_string);
|
||||
|
||||
FfiCreateWalletOutput {
|
||||
wallet: handle,
|
||||
mnemonic: raw_pointer,
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to create wallet: {e}"));
|
||||
FfiCreateWalletOutput::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Open the existing wallet at LEZ's canonical home, deriving the paths from the
|
||||
/// environment (`LEE_WALLET_HOME_DIR` or `~/.lee/wallet`).
|
||||
///
|
||||
/// This is the path-free equivalent of [`wallet_ffi_open`].
|
||||
///
|
||||
/// # Returns
|
||||
/// - Opaque wallet handle on success
|
||||
/// - Null pointer on error (call `wallet_ffi_get_last_error()` for details)
|
||||
///
|
||||
/// # Safety
|
||||
/// This function takes no pointer arguments and is always safe to call.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_open_default() -> *mut WalletHandle {
|
||||
match WalletCore::from_env() {
|
||||
Ok(core) => {
|
||||
let wrapper = Box::new(WalletWrapper {
|
||||
core: Mutex::new(core),
|
||||
});
|
||||
Box::into_raw(wrapper).cast::<WalletHandle>()
|
||||
}
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to open wallet: {e}"));
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a resolved path into an owned C string for return across the FFI.
|
||||
fn path_to_c_string(path: PathBuf) -> *mut c_char {
|
||||
match CString::new(path.to_string_lossy().into_owned()) {
|
||||
Ok(s) => s.into_raw(),
|
||||
Err(e) => {
|
||||
print_error(format!("Invalid path string: {e}"));
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return LEZ's canonical wallet config path (`LEE_WALLET_HOME_DIR` or
|
||||
/// `~/.lee/wallet`, plus `wallet_config.json`).
|
||||
///
|
||||
/// Lets callers display or inspect the default location without reconstructing
|
||||
/// LEZ's path layout themselves.
|
||||
///
|
||||
/// # Returns
|
||||
/// - Pointer to null-terminated string on success (caller must free with
|
||||
/// `wallet_ffi_free_string()`)
|
||||
/// - Null pointer on error
|
||||
///
|
||||
/// # Safety
|
||||
/// This function takes no pointer arguments and is always safe to call.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_default_config_path() -> *mut c_char {
|
||||
match wallet::helperfunctions::fetch_config_path() {
|
||||
Ok(path) => path_to_c_string(path),
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to resolve config path: {e}"));
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return LEZ's canonical wallet storage path (`LEE_WALLET_HOME_DIR` or
|
||||
/// `~/.lee/wallet`, plus `storage.json`).
|
||||
///
|
||||
/// # Returns
|
||||
/// - Pointer to null-terminated string on success (caller must free with
|
||||
/// `wallet_ffi_free_string()`)
|
||||
/// - Null pointer on error
|
||||
///
|
||||
/// # Safety
|
||||
/// This function takes no pointer arguments and is always safe to call.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_default_storage_path() -> *mut c_char {
|
||||
match wallet::helperfunctions::fetch_persistent_storage_path() {
|
||||
Ok(path) => path_to_c_string(path),
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to resolve storage path: {e}"));
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether a wallet already exists at LEZ's canonical home (i.e. its
|
||||
/// `storage.json` is present). Lets callers decide between an open and a
|
||||
/// create flow without touching the filesystem or knowing the path.
|
||||
///
|
||||
/// # Returns
|
||||
/// - `true` if the default storage file exists, `false` otherwise (including
|
||||
/// when the path can't be resolved)
|
||||
///
|
||||
/// # Safety
|
||||
/// This function takes no pointer arguments and is always safe to call.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wallet_ffi_wallet_exists_default() -> bool {
|
||||
match wallet::helperfunctions::fetch_persistent_storage_path() {
|
||||
Ok(path) => path.exists(),
|
||||
Err(e) => {
|
||||
print_error(format!("Failed to resolve storage path: {e}"));
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Destroy a wallet handle and free its resources.
|
||||
///
|
||||
/// After calling this function, the handle is invalid and must not be used.
|
||||
|
||||
@ -1488,6 +1488,86 @@ struct FfiCreateWalletOutput wallet_ffi_create_new(const char *config_path,
|
||||
*/
|
||||
struct WalletHandle *wallet_ffi_open(const char *config_path, const char *storage_path);
|
||||
|
||||
/**
|
||||
* Create a new wallet at LEZ's canonical home, deriving the paths from the
|
||||
* environment (`LEE_WALLET_HOME_DIR` or `~/.lee/wallet`) and creating the
|
||||
* directory if needed.
|
||||
*
|
||||
* This is the path-free equivalent of [`wallet_ffi_create_new`]: callers that
|
||||
* just want the default location don't have to reconstruct LEZ's path layout.
|
||||
*
|
||||
* # Parameters
|
||||
* - `password`: Password for encrypting the wallet seed
|
||||
*
|
||||
* # Returns
|
||||
* - Result, which contains opaque wallet handle and mnemonic words on success
|
||||
* - Result with null pointers on error (call `wallet_ffi_get_last_error()` for details)
|
||||
*
|
||||
* # Safety
|
||||
* `password` must be a valid null-terminated UTF-8 string.
|
||||
*/
|
||||
struct FfiCreateWalletOutput wallet_ffi_create_new_default(const char *password);
|
||||
|
||||
/**
|
||||
* Open the existing wallet at LEZ's canonical home, deriving the paths from the
|
||||
* environment (`LEE_WALLET_HOME_DIR` or `~/.lee/wallet`).
|
||||
*
|
||||
* This is the path-free equivalent of [`wallet_ffi_open`].
|
||||
*
|
||||
* # Returns
|
||||
* - Opaque wallet handle on success
|
||||
* - Null pointer on error (call `wallet_ffi_get_last_error()` for details)
|
||||
*
|
||||
* # Safety
|
||||
* This function takes no pointer arguments and is always safe to call.
|
||||
*/
|
||||
struct WalletHandle *wallet_ffi_open_default(void);
|
||||
|
||||
/**
|
||||
* Return LEZ's canonical wallet config path (`LEE_WALLET_HOME_DIR` or
|
||||
* `~/.lee/wallet`, plus `wallet_config.json`).
|
||||
*
|
||||
* Lets callers display or inspect the default location without reconstructing
|
||||
* LEZ's path layout themselves.
|
||||
*
|
||||
* # Returns
|
||||
* - Pointer to null-terminated string on success (caller must free with
|
||||
* `wallet_ffi_free_string()`)
|
||||
* - Null pointer on error
|
||||
*
|
||||
* # Safety
|
||||
* This function takes no pointer arguments and is always safe to call.
|
||||
*/
|
||||
char *wallet_ffi_default_config_path(void);
|
||||
|
||||
/**
|
||||
* Return LEZ's canonical wallet storage path (`LEE_WALLET_HOME_DIR` or
|
||||
* `~/.lee/wallet`, plus `storage.json`).
|
||||
*
|
||||
* # Returns
|
||||
* - Pointer to null-terminated string on success (caller must free with
|
||||
* `wallet_ffi_free_string()`)
|
||||
* - Null pointer on error
|
||||
*
|
||||
* # Safety
|
||||
* This function takes no pointer arguments and is always safe to call.
|
||||
*/
|
||||
char *wallet_ffi_default_storage_path(void);
|
||||
|
||||
/**
|
||||
* Whether a wallet already exists at LEZ's canonical home (i.e. its
|
||||
* `storage.json` is present). Lets callers decide between an open and a
|
||||
* create flow without touching the filesystem or knowing the path.
|
||||
*
|
||||
* # Returns
|
||||
* - `true` if the default storage file exists, `false` otherwise (including
|
||||
* when the path can't be resolved)
|
||||
*
|
||||
* # Safety
|
||||
* This function takes no pointer arguments and is always safe to call.
|
||||
*/
|
||||
bool wallet_ffi_wallet_exists_default(void);
|
||||
|
||||
/**
|
||||
* Destroy a wallet handle and free its resources.
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user