summaryrefslogtreecommitdiff
path: root/impls/monero_rust/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'impls/monero_rust/src/lib.rs')
-rw-r--r--impls/monero_rust/src/lib.rs147
1 files changed, 100 insertions, 47 deletions
diff --git a/impls/monero_rust/src/lib.rs b/impls/monero_rust/src/lib.rs
index d576ea6..2175083 100644
--- a/impls/monero_rust/src/lib.rs
+++ b/impls/monero_rust/src/lib.rs
@@ -1,62 +1,69 @@
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int, c_void};
use std::ptr::NonNull;
+use std::sync::Arc;
+
+use libloading::{Library, Symbol};
pub const NETWORK_TYPE_MAINNET: c_int = 0;
pub const NETWORK_TYPE_TESTNET: c_int = 1;
pub const NETWORK_TYPE_STAGENET: c_int = 2;
-extern "C" {
- pub fn MONERO_WalletManagerFactory_getWalletManager() -> *mut c_void;
- pub fn MONERO_WalletManager_createWallet(
- wm_ptr: *mut c_void,
- path: *const c_char,
- password: *const c_char,
- language: *const c_char,
- networkType: c_int,
- ) -> *mut c_void;
- pub fn MONERO_Wallet_seed(
- wallet_ptr: *mut c_void,
- seed_offset: *const c_char,
- ) -> *const c_char;
- pub fn MONERO_WalletManager_closeWallet(
- wm_ptr: *mut c_void,
- wallet_ptr: *mut c_void,
- store: bool,
- ) -> bool;
- pub fn MONERO_Wallet_errorString(wallet_ptr: *mut c_void) -> *const c_char;
- pub fn MONERO_Wallet_status(wallet_ptr: *mut c_void) -> c_int;
- pub fn MONERO_Wallet_address(
- wallet_ptr: *mut c_void,
- account_index: u64,
- address_index: u64,
- ) -> *const c_char;
- pub fn MONERO_Wallet_isDeterministic(wallet_ptr: *mut c_void) -> bool;
- pub fn MONERO_WalletManager_walletExists(
- wm_ptr: *mut c_void,
- path: *const c_char,
- ) -> bool;
-}
-
#[derive(Debug)]
pub enum WalletError {
NullPointer,
FfiError(String),
WalletErrorCode(c_int, String),
+ LibraryLoadError(String),
}
-type WalletResult<T> = Result<T, WalletError>;
+pub type WalletResult<T> = Result<T, WalletError>;
pub struct WalletManager {
ptr: NonNull<c_void>,
+ library: Arc<Library>,
}
impl WalletManager {
- pub fn new() -> WalletResult<Self> {
+ /// Create a new WalletManager, optionally specifying the path to the shared library.
+ pub fn new(lib_path: Option<&str>) -> WalletResult<Self> {
+ let lib = match lib_path {
+ Some(path) => {
+ unsafe {
+ Library::new(path).map_err(|e| WalletError::LibraryLoadError(e.to_string()))?
+ }
+ }
+ None => {
+ // Attempt to load from the same directory as the executable.
+ let exe_path = std::env::current_exe()
+ .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?;
+ let exe_dir = exe_path.parent().ok_or_else(|| {
+ WalletError::LibraryLoadError("Failed to get executable directory".to_string())
+ })?;
+ let lib_path = exe_dir.join("libwallet2_api_c.so");
+
+ unsafe {
+ if lib_path.exists() {
+ Library::new(lib_path)
+ .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?
+ } else {
+ // Fallback to standard locations.
+ Library::new("libwallet2_api_c.so")
+ .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?
+ }
+ }
+ }
+ };
+
+ let library = Arc::new(lib);
+
unsafe {
- let ptr = MONERO_WalletManagerFactory_getWalletManager();
+ let func: Symbol<unsafe extern "C" fn() -> *mut c_void> =
+ library.get(b"MONERO_WalletManagerFactory_getWalletManager\0")
+ .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?;
+ let ptr = func();
NonNull::new(ptr)
- .map(|nn_ptr| WalletManager { ptr: nn_ptr })
+ .map(|nn_ptr| WalletManager { ptr: nn_ptr, library })
.ok_or(WalletError::NullPointer)
}
}
@@ -73,7 +80,19 @@ impl WalletManager {
let c_language = CString::new(language).expect("CString::new failed");
unsafe {
- let wallet_ptr = MONERO_WalletManager_createWallet(
+ let func: Symbol<
+ unsafe extern "C" fn(
+ *mut c_void,
+ *const c_char,
+ *const c_char,
+ *const c_char,
+ c_int,
+ ) -> *mut c_void,
+ > = self
+ .library
+ .get(b"MONERO_WalletManager_createWallet\0")
+ .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?;
+ let wallet_ptr = func(
self.ptr.as_ptr(),
c_path.as_ptr(),
c_password.as_ptr(),
@@ -87,15 +106,24 @@ impl WalletManager {
Ok(Wallet {
ptr: NonNull::new_unchecked(wallet_ptr),
manager_ptr: self.ptr,
+ library: Arc::clone(&self.library), // Keep the library alive.
})
}
}
}
}
+impl Drop for WalletManager {
+ fn drop(&mut self) {
+ // The library will be dropped automatically when all references are gone.
+ }
+}
+
+#[derive(Clone)]
pub struct Wallet {
ptr: NonNull<c_void>,
manager_ptr: NonNull<c_void>,
+ library: Arc<Library>,
}
impl Wallet {
@@ -103,7 +131,11 @@ impl Wallet {
let c_seed_offset = CString::new(seed_offset).expect("CString::new failed");
unsafe {
- let seed_ptr = MONERO_Wallet_seed(self.ptr.as_ptr(), c_seed_offset.as_ptr());
+ let func: Symbol<unsafe extern "C" fn(*mut c_void, *const c_char) -> *const c_char> =
+ self.library
+ .get(b"MONERO_Wallet_seed\0")
+ .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?;
+ let seed_ptr = func(self.ptr.as_ptr(), c_seed_offset.as_ptr());
if seed_ptr.is_null() {
Err(self.get_last_error())
@@ -122,11 +154,11 @@ impl Wallet {
pub fn get_address(&self, account_index: u64, address_index: u64) -> WalletResult<String> {
unsafe {
- let address_ptr = MONERO_Wallet_address(
- self.ptr.as_ptr(),
- account_index,
- address_index,
- );
+ let func: Symbol<unsafe extern "C" fn(*mut c_void, u64, u64) -> *const c_char> =
+ self.library
+ .get(b"MONERO_Wallet_address\0")
+ .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?;
+ let address_ptr = func(self.ptr.as_ptr(), account_index, address_index);
if address_ptr.is_null() {
Err(self.get_last_error())
@@ -140,13 +172,28 @@ impl Wallet {
}
pub fn is_deterministic(&self) -> bool {
- unsafe { MONERO_Wallet_isDeterministic(self.ptr.as_ptr()) }
+ unsafe {
+ let func: Symbol<unsafe extern "C" fn(*mut c_void) -> bool> = self
+ .library
+ .get(b"MONERO_Wallet_isDeterministic\0")
+ .expect("Failed to load MONERO_Wallet_isDeterministic");
+ func(self.ptr.as_ptr())
+ }
}
fn get_last_error(&self) -> WalletError {
unsafe {
- let error_ptr = MONERO_Wallet_errorString(self.ptr.as_ptr());
- let status = MONERO_Wallet_status(self.ptr.as_ptr());
+ let error_func: Symbol<unsafe extern "C" fn(*mut c_void) -> *const c_char> = self
+ .library
+ .get(b"MONERO_Wallet_errorString\0")
+ .expect("Failed to load MONERO_Wallet_errorString");
+ let status_func: Symbol<unsafe extern "C" fn(*mut c_void) -> c_int> = self
+ .library
+ .get(b"MONERO_Wallet_status\0")
+ .expect("Failed to load MONERO_Wallet_status");
+
+ let error_ptr = error_func(self.ptr.as_ptr());
+ let status = status_func(self.ptr.as_ptr());
let error_msg = if error_ptr.is_null() {
"Unknown error".to_string()
@@ -164,7 +211,13 @@ impl Wallet {
impl Drop for Wallet {
fn drop(&mut self) {
unsafe {
- MONERO_WalletManager_closeWallet(self.manager_ptr.as_ptr(), self.ptr.as_ptr(), false);
+ let func: Symbol<
+ unsafe extern "C" fn(*mut c_void, *mut c_void, bool) -> bool,
+ > = self
+ .library
+ .get(b"MONERO_WalletManager_closeWallet\0")
+ .expect("Failed to load MONERO_WalletManager_closeWallet");
+ func(self.manager_ptr.as_ptr(), self.ptr.as_ptr(), false);
}
}
}