From 4694bb913f7709c2b2fa568f065cc56f92f09555 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 10 Oct 2024 20:52:31 -0500 Subject: convert to lib --- impls/monero_rust/Cargo.lock | 1 + impls/monero_rust/Cargo.toml | 7 +- impls/monero_rust/src/lib.rs | 170 ++++++++++++++++++++++++++++++++++++++++++ impls/monero_rust/src/main.rs | 102 ++++++------------------- 4 files changed, 199 insertions(+), 81 deletions(-) create mode 100644 impls/monero_rust/src/lib.rs (limited to 'impls') diff --git a/impls/monero_rust/Cargo.lock b/impls/monero_rust/Cargo.lock index 6c98d95..2d20545 100644 --- a/impls/monero_rust/Cargo.lock +++ b/impls/monero_rust/Cargo.lock @@ -123,6 +123,7 @@ name = "monero_rust" version = "0.0.1" dependencies = [ "bindgen", + "libc", ] [[package]] diff --git a/impls/monero_rust/Cargo.toml b/impls/monero_rust/Cargo.toml index 53ff56e..548823e 100644 --- a/impls/monero_rust/Cargo.toml +++ b/impls/monero_rust/Cargo.toml @@ -7,11 +7,14 @@ repository = "https://github.com/ManyMath/monero_rust" license = "MIT" build = "build.rs" -[[bin]] +[lib] name = "monero_rust" -path = "src/main.rs" +path = "src/lib.rs" +crate-type = ["lib", "cdylib"] [dependencies] +libc = "0.2" [build-dependencies] bindgen = "0.70.1" + diff --git a/impls/monero_rust/src/lib.rs b/impls/monero_rust/src/lib.rs new file mode 100644 index 0000000..d576ea6 --- /dev/null +++ b/impls/monero_rust/src/lib.rs @@ -0,0 +1,170 @@ +use std::ffi::{CStr, CString}; +use std::os::raw::{c_char, c_int, c_void}; +use std::ptr::NonNull; + +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), +} + +type WalletResult = Result; + +pub struct WalletManager { + ptr: NonNull, +} + +impl WalletManager { + pub fn new() -> WalletResult { + unsafe { + let ptr = MONERO_WalletManagerFactory_getWalletManager(); + NonNull::new(ptr) + .map(|nn_ptr| WalletManager { ptr: nn_ptr }) + .ok_or(WalletError::NullPointer) + } + } + + pub fn create_wallet( + &self, + path: &str, + password: &str, + language: &str, + network_type: c_int, + ) -> WalletResult { + let c_path = CString::new(path).expect("CString::new failed"); + let c_password = CString::new(password).expect("CString::new failed"); + let c_language = CString::new(language).expect("CString::new failed"); + + unsafe { + let wallet_ptr = MONERO_WalletManager_createWallet( + self.ptr.as_ptr(), + c_path.as_ptr(), + c_password.as_ptr(), + c_language.as_ptr(), + network_type, + ); + + if wallet_ptr.is_null() { + Err(WalletError::NullPointer) + } else { + Ok(Wallet { + ptr: NonNull::new_unchecked(wallet_ptr), + manager_ptr: self.ptr, + }) + } + } + } +} + +pub struct Wallet { + ptr: NonNull, + manager_ptr: NonNull, +} + +impl Wallet { + pub fn get_seed(&self, seed_offset: &str) -> WalletResult { + 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()); + + if seed_ptr.is_null() { + Err(self.get_last_error()) + } else { + let seed = CStr::from_ptr(seed_ptr) + .to_string_lossy() + .into_owned(); + if seed.is_empty() { + Err(WalletError::FfiError("Received empty seed".to_string())) + } else { + Ok(seed) + } + } + } + } + + pub fn get_address(&self, account_index: u64, address_index: u64) -> WalletResult { + unsafe { + let address_ptr = MONERO_Wallet_address( + self.ptr.as_ptr(), + account_index, + address_index, + ); + + if address_ptr.is_null() { + Err(self.get_last_error()) + } else { + let address = CStr::from_ptr(address_ptr) + .to_string_lossy() + .into_owned(); + Ok(address) + } + } + } + + pub fn is_deterministic(&self) -> bool { + unsafe { MONERO_Wallet_isDeterministic(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_msg = if error_ptr.is_null() { + "Unknown error".to_string() + } else { + CStr::from_ptr(error_ptr) + .to_string_lossy() + .into_owned() + }; + + WalletError::WalletErrorCode(status, error_msg) + } + } +} + +impl Drop for Wallet { + fn drop(&mut self) { + unsafe { + MONERO_WalletManager_closeWallet(self.manager_ptr.as_ptr(), self.ptr.as_ptr(), false); + } + } +} diff --git a/impls/monero_rust/src/main.rs b/impls/monero_rust/src/main.rs index a51e542..eb9e148 100644 --- a/impls/monero_rust/src/main.rs +++ b/impls/monero_rust/src/main.rs @@ -1,83 +1,27 @@ -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -use std::ffi::{CStr, CString}; -use std::os::raw::{c_char, c_int, c_void}; - -const NetworkType_MAINNET: c_int = 0; -// const NetworkType_TESTNET: c_int = 1; -// const NetworkType_STAGENET: c_int = 2; - -extern "C" { - // Get the wallet manager instance. - pub fn MONERO_WalletManagerFactory_getWalletManager() -> *mut c_void; - - // Create a new wallet. - 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; - - // Retrieve the seed from the wallet. - pub fn MONERO_Wallet_seed( - wallet_ptr: *mut c_void, - seed_offset: *const c_char, - ) -> *const c_char; - - // Close the wallet. - pub fn MONERO_WalletManager_closeWallet( - wm_ptr: *mut c_void, - wallet_ptr: *mut c_void, - store: bool, - ) -> bool; -} - -fn main() { - unsafe { - // Initialize the Wallet Manager. - let wm_ptr = MONERO_WalletManagerFactory_getWalletManager(); - if wm_ptr.is_null() { - eprintln!("Failed to get WalletManager"); - return; +use monero_rust::{ + WalletError, WalletManager, NETWORK_TYPE_MAINNET, +}; + +fn main() -> Result<(), WalletError> { + let wallet_manager = WalletManager::new()?; + + let wallet = wallet_manager.create_wallet( + "wallet", + "password", + "English", + NETWORK_TYPE_MAINNET, + )?; + + match wallet.get_seed("") { + Ok(seed) => println!("Seed: {}", seed), + Err(e) => { + eprintln!("Failed to get seed: {:?}", e); + return Err(e); } + } - // Set up parameters for the new wallet. - let path = CString::new("my_wallet").expect("CString::new failed"); - let password = CString::new("password").expect("CString::new failed"); - let language = CString::new("English").expect("CString::new failed"); - let network_type = NetworkType_MAINNET; - - // Create a new wallet. - let wallet_ptr = MONERO_WalletManager_createWallet( - wm_ptr, - path.as_ptr(), - password.as_ptr(), - language.as_ptr(), - network_type, - ); - if wallet_ptr.is_null() { - eprintln!("Failed to create wallet"); - return; - } + let address = wallet.get_address(0, 0)?; + println!("Wallet Address: {}", address); - // Get the seed. - let seed_offset = CString::new("").expect("CString::new failed"); - let seed_cstr = MONERO_Wallet_seed(wallet_ptr, seed_offset.as_ptr()); - if seed_cstr.is_null() { - eprintln!("Failed to get seed"); - } else { - let seed = CStr::from_ptr(seed_cstr).to_string_lossy().into_owned(); - println!("Seed: {}", seed); - } - - // Close the wallet. - let result = MONERO_WalletManager_closeWallet(wm_ptr, wallet_ptr, false); - if !result { - eprintln!("Failed to close wallet"); - } - } + Ok(()) } -- cgit v1.2.3