From 98571709996b020b8f2746de1f43f9fda1082417 Mon Sep 17 00:00:00 2001 From: shamardy Date: Wed, 28 Aug 2024 06:06:18 +0300 Subject: [PATCH 01/11] add `get_wallet_names` rpc --- mm2src/mm2_core/src/mm_ctx.rs | 6 +- mm2src/mm2_io/src/fs.rs | 55 ++++++++++++++++--- mm2src/mm2_main/src/lp_wallet.rs | 53 +++++++++++++++++- .../src/lp_wallet/mnemonics_storage.rs | 9 ++- .../src/lp_wallet/mnemonics_wasm_db.rs | 13 +++++ .../mm2_main/src/rpc/dispatcher/dispatcher.rs | 3 +- mm2src/proxy_signature/src/lib.rs | 4 +- 7 files changed, 127 insertions(+), 16 deletions(-) diff --git a/mm2src/mm2_core/src/mm_ctx.rs b/mm2src/mm2_core/src/mm_ctx.rs index e891f0b649..4b58cc3839 100644 --- a/mm2src/mm2_core/src/mm_ctx.rs +++ b/mm2src/mm2_core/src/mm_ctx.rs @@ -287,10 +287,12 @@ impl MmCtx { }) } + #[cfg(not(target_arch = "wasm32"))] + pub fn db_root(&self) -> PathBuf { path_to_db_root(self.conf["dbdir"].as_str()) } + #[cfg(not(target_arch = "wasm32"))] pub fn wallet_file_path(&self, wallet_name: &str) -> PathBuf { - let db_root = path_to_db_root(self.conf["dbdir"].as_str()); - db_root.join(wallet_name.to_string() + ".dat") + self.db_root().join(wallet_name.to_string() + ".dat") } /// MM database path. diff --git a/mm2src/mm2_io/src/fs.rs b/mm2src/mm2_io/src/fs.rs index 94a323c0b8..e34158b5c0 100644 --- a/mm2src/mm2_io/src/fs.rs +++ b/mm2src/mm2_io/src/fs.rs @@ -192,19 +192,49 @@ where json::from_slice(&content).map_to_mm(FsJsonError::Deserializing) } -/// Read the `dir_path` entries trying to deserialize each as the `T` type. +async fn filter_files_with_extension(dir_path: &Path, extension: &str) -> IoResult> { + let ext = Some(OsStr::new(extension)); + let entries = read_dir_async(dir_path) + .await? + .into_iter() + .filter(|path| path.extension() == ext) + .collect(); + Ok(entries) +} + +/// Reads the file names with the specified extension from the given directory path. +pub async fn read_file_names_with_extension(dir_path: &Path, extension: &str) -> IoResult> { + let entries = filter_files_with_extension(dir_path, extension).await?; + let file_names: Vec = entries + .into_iter() + .filter_map(|path| path.file_name().and_then(|name| name.to_str().map(|s| s.to_string()))) + .collect(); + + Ok(file_names) +} + +/// Reads the file stems with the specified extension from the given directory path. +/// The stem is the file name without the extension. +pub async fn read_file_stems_with_extension(dir_path: &Path, extension: &str) -> IoResult> { + let entries = filter_files_with_extension(dir_path, extension).await?; + let file_names: Vec = entries + .into_iter() + .filter_map(|path| path.file_stem().and_then(|stem| stem.to_str().map(|s| s.to_string()))) + .collect(); + + Ok(file_names) +} + +/// Read the `dir_path` entries trying to deserialize each as the `T` type, +/// filtering by the specified extension. /// Please note that files that couldn't be deserialized are skipped. -pub async fn read_dir_json(dir_path: &Path) -> FsJsonResult> +pub async fn read_files_with_extension(dir_path: &Path, extension: &str) -> FsJsonResult> where T: DeserializeOwned, { - let json_ext = Some(OsStr::new("json")); - let entries: Vec<_> = read_dir_async(dir_path) + let entries = filter_files_with_extension(dir_path, extension) .await - .mm_err(FsJsonError::IoReading)? - .into_iter() - .filter(|path| path.extension() == json_ext) - .collect(); + .mm_err(FsJsonError::IoReading)?; let type_name = std::any::type_name::(); let mut result = Vec::new(); @@ -233,6 +263,15 @@ where Ok(result) } +/// Read the `dir_path` entries trying to deserialize each as the `T` type from JSON files. +/// Please note that files that couldn't be deserialized are skipped. +pub async fn read_dir_json(dir_path: &Path) -> FsJsonResult> +where + T: DeserializeOwned, +{ + read_files_with_extension(dir_path, "json").await +} + pub async fn write_json(t: &T, path: &Path, use_tmp_file: bool) -> FsJsonResult<()> where T: Serialize, diff --git a/mm2src/mm2_main/src/lp_wallet.rs b/mm2src/mm2_main/src/lp_wallet.rs index 19ac357cab..e24d5b6fbd 100644 --- a/mm2src/mm2_main/src/lp_wallet.rs +++ b/mm2src/mm2_main/src/lp_wallet.rs @@ -5,20 +5,20 @@ use http::StatusCode; use mm2_core::mm_ctx::MmArc; use mm2_err_handle::prelude::*; use serde::de::DeserializeOwned; -use serde_json::{self as json}; +use serde_json::{self as json, Value as Json}; cfg_wasm32! { use crate::lp_wallet::mnemonics_wasm_db::{WalletsDb, WalletsDBError}; use mm2_core::mm_ctx::from_ctx; use mm2_db::indexed_db::{ConstructibleDb, DbLocked, InitDbResult}; - use mnemonics_wasm_db::{read_encrypted_passphrase_if_available, save_encrypted_passphrase}; + use mnemonics_wasm_db::{read_all_wallet_names, read_encrypted_passphrase_if_available, save_encrypted_passphrase}; use std::sync::Arc; type WalletsDbLocked<'a> = DbLocked<'a, WalletsDb>; } cfg_native! { - use mnemonics_storage::{read_encrypted_passphrase_if_available, save_encrypted_passphrase, WalletsStorageError}; + use mnemonics_storage::{read_all_wallet_names, read_encrypted_passphrase_if_available, save_encrypted_passphrase, WalletsStorageError}; } #[cfg(not(target_arch = "wasm32"))] mod mnemonics_storage; @@ -499,3 +499,50 @@ pub async fn get_mnemonic_rpc(ctx: MmArc, req: GetMnemonicRequest) -> MmResult, + activated_wallet: Option, +} + +#[derive(Debug, Display, Serialize, SerializeErrorType)] +#[serde(tag = "error_type", content = "error_data")] +pub enum GetWalletsError { + #[display(fmt = "Wallets storage error: {}", _0)] + WalletsStorageError(String), + #[display(fmt = "Internal error: {}", _0)] + Internal(String), +} + +impl HttpStatusCode for GetWalletsError { + fn status_code(&self) -> StatusCode { + match self { + GetWalletsError::WalletsStorageError(_) | GetWalletsError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR, + } + } +} + +#[cfg(not(target_arch = "wasm32"))] +impl From for GetWalletsError { + fn from(e: WalletsStorageError) -> Self { GetWalletsError::WalletsStorageError(e.to_string()) } +} + +#[cfg(target_arch = "wasm32")] +impl From for GetWalletsError { + fn from(e: WalletsDBError) -> Self { GetWalletsError::WalletsStorageError(e.to_string()) } +} + +/// Retrieves all created wallets and the currently activated wallet. +pub async fn get_wallet_names_rpc(ctx: MmArc, _req: Json) -> MmResult { + let wallets = read_all_wallet_names(&ctx).await?; + let activated_wallet = ctx.wallet_name.ok_or(GetWalletsError::Internal( + "`wallet_name` not initialized yet!".to_string(), + ))?; + + Ok(GetWalletNamesResponse { + wallet_names: wallets, + activated_wallet: activated_wallet.clone(), + }) +} diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs index 3cf40e61fb..5e0e49214e 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs @@ -1,7 +1,7 @@ use crypto::EncryptedData; use mm2_core::mm_ctx::MmArc; use mm2_err_handle::prelude::*; -use mm2_io::fs::ensure_file_is_writable; +use mm2_io::fs::{ensure_file_is_writable, read_file_stems_with_extension}; type WalletsStorageResult = Result>; @@ -61,3 +61,10 @@ pub(super) async fn read_encrypted_passphrase_if_available(ctx: &MmArc) -> Walle )) }) } + +pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsStorageResult> { + let wallet_names = read_file_stems_with_extension(&ctx.db_root(), "dat") + .await + .mm_err(|e| WalletsStorageError::FsReadError(format!("Error reading wallets directory: {}", e)))?; + Ok(wallet_names) +} diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs index 40daa62029..06dd565ce5 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs @@ -144,3 +144,16 @@ pub(super) async fn read_encrypted_passphrase_if_available(ctx: &MmArc) -> Walle }) .transpose() } + +pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsDBResult> { + let wallets_ctx = WalletsContext::from_ctx(ctx).map_to_mm(WalletsDBError::Internal)?; + + let db = wallets_ctx.wallets_db().await?; + let transaction = db.transaction().await?; + let table = transaction.table::().await?; + + let all_items = table.get_all_items().await?; + let wallet_names = all_items.into_iter().map(|(_, item)| item.wallet_name).collect(); + + Ok(wallet_names) +} diff --git a/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs b/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs index 5403392240..c12465181f 100644 --- a/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs +++ b/mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs @@ -5,7 +5,7 @@ use crate::lp_native_dex::init_metamask::{cancel_connect_metamask, connect_metam use crate::lp_ordermatch::{best_orders_rpc_v2, orderbook_rpc_v2, start_simple_market_maker_bot, stop_simple_market_maker_bot}; use crate::lp_swap::swap_v2_rpcs::{active_swaps_rpc, my_recent_swaps_rpc, my_swap_status_rpc}; -use crate::lp_wallet::get_mnemonic_rpc; +use crate::lp_wallet::{get_mnemonic_rpc, get_wallet_names_rpc}; use crate::rpc::rate_limiter::{process_rate_limit, RateLimitContext}; use crate::{lp_stats::{add_node_to_version_stat, remove_node_from_version_stat, start_version_stat_collection, stop_version_stat_collection, update_version_stat_collection}, @@ -190,6 +190,7 @@ async fn dispatcher_v2(request: MmRpcRequest, ctx: MmArc) -> DispatcherResult handle_mmrpc(ctx, request, get_raw_transaction).await, "get_shared_db_id" => handle_mmrpc(ctx, request, get_shared_db_id).await, "get_staking_infos" => handle_mmrpc(ctx, request, get_staking_infos).await, + "get_wallet_names" => handle_mmrpc(ctx, request, get_wallet_names_rpc).await, "max_maker_vol" => handle_mmrpc(ctx, request, max_maker_vol).await, "my_recent_swaps" => handle_mmrpc(ctx, request, my_recent_swaps_rpc).await, "my_swap_status" => handle_mmrpc(ctx, request, my_swap_status_rpc).await, diff --git a/mm2src/proxy_signature/src/lib.rs b/mm2src/proxy_signature/src/lib.rs index 86f57a3431..f4ae2393a0 100644 --- a/mm2src/proxy_signature/src/lib.rs +++ b/mm2src/proxy_signature/src/lib.rs @@ -74,7 +74,9 @@ impl ProxySign { return false; } - let Ok(public_key) = PublicKey::try_decode_protobuf(&self.raw_message.public_key_encoded) else { return false }; + let Ok(public_key) = PublicKey::try_decode_protobuf(&self.raw_message.public_key_encoded) else { + return false; + }; if self.address != public_key.to_peer_id().to_string() { return false; From 1de62ac1a8a8fc0b600def03f00a5dac8d8d7791 Mon Sep 17 00:00:00 2001 From: shamardy Date: Fri, 6 Sep 2024 21:32:43 +0300 Subject: [PATCH 02/11] review fix: allow filter_files_with_extension to work with case-sensitive extensions --- mm2src/mm2_io/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm2src/mm2_io/src/fs.rs b/mm2src/mm2_io/src/fs.rs index e34158b5c0..fbb3529d82 100644 --- a/mm2src/mm2_io/src/fs.rs +++ b/mm2src/mm2_io/src/fs.rs @@ -193,11 +193,11 @@ where } async fn filter_files_with_extension(dir_path: &Path, extension: &str) -> IoResult> { - let ext = Some(OsStr::new(extension)); + let ext = Some(OsStr::new(extension).to_ascii_lowercase()); let entries = read_dir_async(dir_path) .await? .into_iter() - .filter(|path| path.extension() == ext) + .filter(|path| path.extension().map(|ext| ext.to_ascii_lowercase()) == ext) .collect(); Ok(entries) } From f4162b8b61a6f50c43bdce7b3dabf053553c01e8 Mon Sep 17 00:00:00 2001 From: shamardy Date: Fri, 6 Sep 2024 21:36:35 +0300 Subject: [PATCH 03/11] review fix: reduce duplication by extracting it to extract_file_identifiers function --- mm2src/mm2_io/src/fs.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/mm2src/mm2_io/src/fs.rs b/mm2src/mm2_io/src/fs.rs index fbb3529d82..ca3dea83f9 100644 --- a/mm2src/mm2_io/src/fs.rs +++ b/mm2src/mm2_io/src/fs.rs @@ -202,27 +202,28 @@ async fn filter_files_with_extension(dir_path: &Path, extension: &str) -> IoResu Ok(entries) } +/// Helper function to extract file names or stems based on the provided extraction function. +fn extract_file_identifiers(entries: Vec, extractor: F) -> Vec +where + F: Fn(&Path) -> Option<&OsStr>, +{ + entries + .into_iter() + .filter_map(|path| extractor(&path).and_then(OsStr::to_str).map(ToOwned::to_owned)) + .collect() +} + /// Reads the file names with the specified extension from the given directory path. pub async fn read_file_names_with_extension(dir_path: &Path, extension: &str) -> IoResult> { let entries = filter_files_with_extension(dir_path, extension).await?; - let file_names: Vec = entries - .into_iter() - .filter_map(|path| path.file_name().and_then(|name| name.to_str().map(|s| s.to_string()))) - .collect(); - - Ok(file_names) + Ok(extract_file_identifiers(entries, Path::file_name)) } /// Reads the file stems with the specified extension from the given directory path. /// The stem is the file name without the extension. pub async fn read_file_stems_with_extension(dir_path: &Path, extension: &str) -> IoResult> { let entries = filter_files_with_extension(dir_path, extension).await?; - let file_names: Vec = entries - .into_iter() - .filter_map(|path| path.file_stem().and_then(|stem| stem.to_str().map(|s| s.to_string()))) - .collect(); - - Ok(file_names) + Ok(extract_file_identifiers(entries, Path::file_stem)) } /// Read the `dir_path` entries trying to deserialize each as the `T` type, From 704305d3a07031f31926786d7e767a4792aee172 Mon Sep 17 00:00:00 2001 From: shamardy Date: Thu, 19 Sep 2024 04:24:28 +0300 Subject: [PATCH 04/11] review fix: add note about `ok_or` usage for `Constructible` --- mm2src/mm2_main/src/lp_wallet.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm2src/mm2_main/src/lp_wallet.rs b/mm2src/mm2_main/src/lp_wallet.rs index e24d5b6fbd..d4546ffb72 100644 --- a/mm2src/mm2_main/src/lp_wallet.rs +++ b/mm2src/mm2_main/src/lp_wallet.rs @@ -537,6 +537,8 @@ impl From for GetWalletsError { /// Retrieves all created wallets and the currently activated wallet. pub async fn get_wallet_names_rpc(ctx: MmArc, _req: Json) -> MmResult { let wallets = read_all_wallet_names(&ctx).await?; + // Note: `ok_or` is used here on `Constructible>` to handle the case where the wallet name is not set. + // `wallet_name` can be `None` in the case of no-login mode. let activated_wallet = ctx.wallet_name.ok_or(GetWalletsError::Internal( "`wallet_name` not initialized yet!".to_string(), ))?; From 1a7c003c49607b8f99b6d1dc47deb3ffabf194ab Mon Sep 17 00:00:00 2001 From: shamardy Date: Thu, 19 Sep 2024 11:45:13 +0300 Subject: [PATCH 05/11] review fix: add tests --- mm2src/mm2_core/src/lib.rs | 2 + mm2src/mm2_core/src/mm_ctx.rs | 6 ++ mm2src/mm2_main/src/lp_wallet.rs | 4 +- mm2src/mm2_main/src/wasm_tests.rs | 67 +++++++++++---- .../tests/mm2_tests/mm2_tests_inner.rs | 53 ++++++++++-- mm2src/mm2_test_helpers/src/for_tests.rs | 86 +++++++++++++++++-- mm2src/mm2_test_helpers/src/structs.rs | 7 ++ 7 files changed, 189 insertions(+), 36 deletions(-) diff --git a/mm2src/mm2_core/src/lib.rs b/mm2src/mm2_core/src/lib.rs index 62e4bef09c..3c0a118430 100644 --- a/mm2src/mm2_core/src/lib.rs +++ b/mm2src/mm2_core/src/lib.rs @@ -19,4 +19,6 @@ impl DbNamespaceId { let mut rng = thread_rng(); DbNamespaceId::Test(rng.gen()) } + + pub fn for_test_with_id(id: u64) -> DbNamespaceId { DbNamespaceId::Test(id) } } diff --git a/mm2src/mm2_core/src/mm_ctx.rs b/mm2src/mm2_core/src/mm_ctx.rs index 4b58cc3839..e3b484002f 100644 --- a/mm2src/mm2_core/src/mm_ctx.rs +++ b/mm2src/mm2_core/src/mm_ctx.rs @@ -739,6 +739,12 @@ impl MmCtxBuilder { self } + #[cfg(target_arch = "wasm32")] + pub fn with_test_db_namespace_with_id(mut self, id: u64) -> Self { + self.db_namespace = DbNamespaceId::for_test_with_id(id); + self + } + pub fn into_mm_arc(self) -> MmArc { // NB: We avoid recreating LogState // in order not to interfere with the integration tests checking LogState drop on shutdown. diff --git a/mm2src/mm2_main/src/lp_wallet.rs b/mm2src/mm2_main/src/lp_wallet.rs index d4546ffb72..0efc631643 100644 --- a/mm2src/mm2_main/src/lp_wallet.rs +++ b/mm2src/mm2_main/src/lp_wallet.rs @@ -2,6 +2,7 @@ use common::HttpStatusCode; use crypto::{decrypt_mnemonic, encrypt_mnemonic, generate_mnemonic, CryptoCtx, CryptoInitError, EncryptedData, MnemonicError}; use http::StatusCode; +use itertools::Itertools; use mm2_core::mm_ctx::MmArc; use mm2_err_handle::prelude::*; use serde::de::DeserializeOwned; @@ -536,7 +537,8 @@ impl From for GetWalletsError { /// Retrieves all created wallets and the currently activated wallet. pub async fn get_wallet_names_rpc(ctx: MmArc, _req: Json) -> MmResult { - let wallets = read_all_wallet_names(&ctx).await?; + // We want to return wallet names in the same order for both native and wasm32 targets. + let wallets = read_all_wallet_names(&ctx).await?.into_iter().sorted().collect(); // Note: `ok_or` is used here on `Constructible>` to handle the case where the wallet name is not set. // `wallet_name` can be `None` in the case of no-login mode. let activated_wallet = ctx.wallet_name.ok_or(GetWalletsError::Internal( diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index fbf37ca545..c73047cb20 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -1,14 +1,14 @@ use crate::lp_init; -use common::executor::{spawn, Timer}; +use common::executor::{spawn, spawn_abortable, spawn_local_abortable, AbortOnDropHandle, Timer}; use common::log::wasm_log::register_wasm_log; use mm2_core::mm_ctx::MmArc; use mm2_number::BigDecimal; use mm2_rpc::data::legacy::OrderbookResponse; use mm2_test_helpers::electrums::{doc_electrums, marty_electrums}; use mm2_test_helpers::for_tests::{check_recent_swaps, enable_electrum_json, enable_utxo_v2_electrum, - enable_z_coin_light, morty_conf, pirate_conf, rick_conf, start_swaps, - test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, MarketMakerIt, - Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, + enable_z_coin_light, get_wallet_names, morty_conf, pirate_conf, rick_conf, + start_swaps, test_qrc20_history_impl, wait_for_swaps_finish_and_check_status, + MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, ARRR, MORTY, PIRATE_ELECTRUMS, PIRATE_LIGHTWALLETD_URLS, RICK}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::{Bip44Chain, EnableCoinBalance, HDAccountAddressId}; @@ -16,6 +16,7 @@ use serde_json::json; use wasm_bindgen_test::wasm_bindgen_test; const PIRATE_TEST_BALANCE_SEED: &str = "pirate test seed"; +const STOP_TIMEOUT_MS: u64 = 1000; /// Starts the WASM version of MM. fn wasm_start(ctx: MmArc) { @@ -26,13 +27,7 @@ fn wasm_start(ctx: MmArc) { /// This function runs Alice and Bob nodes, activates coins, starts swaps, /// and then immediately stops the nodes to check if `MmArc` is dropped in a short period. -async fn test_mm2_stops_impl( - pairs: &[(&'static str, &'static str)], - maker_price: f64, - taker_price: f64, - volume: f64, - stop_timeout_ms: u64, -) { +async fn test_mm2_stops_impl(pairs: &[(&'static str, &'static str)], maker_price: f64, taker_price: f64, volume: f64) { let coins = json!([rick_conf(), morty_conf()]); let bob_passphrase = get_passphrase!(".env.seed", "BOB_PASSPHRASE").unwrap(); @@ -69,20 +64,18 @@ async fn test_mm2_stops_impl( start_swaps(&mut mm_bob, &mut mm_alice, pairs, maker_price, taker_price, volume).await; mm_alice - .stop_and_wait_for_ctx_is_dropped(stop_timeout_ms) + .stop_and_wait_for_ctx_is_dropped(STOP_TIMEOUT_MS) .await .unwrap(); - mm_bob.stop_and_wait_for_ctx_is_dropped(stop_timeout_ms).await.unwrap(); + mm_bob.stop_and_wait_for_ctx_is_dropped(STOP_TIMEOUT_MS).await.unwrap(); } #[wasm_bindgen_test] async fn test_mm2_stops_immediately() { - const STOP_TIMEOUT_MS: u64 = 1000; - register_wasm_log(); let pairs: &[_] = &[("RICK", "MORTY")]; - test_mm2_stops_impl(pairs, 1., 1., 0.0001, STOP_TIMEOUT_MS).await; + test_mm2_stops_impl(pairs, 1., 1., 0.0001).await; } #[wasm_bindgen_test] @@ -147,8 +140,6 @@ async fn trade_base_rel_electrum( assert_eq!(0, bob_orderbook.asks.len(), "{} {} asks must be empty", base, rel); } - const STOP_TIMEOUT_MS: u64 = 1000; - mm_bob.stop_and_wait_for_ctx_is_dropped(STOP_TIMEOUT_MS).await.unwrap(); mm_alice .stop_and_wait_for_ctx_is_dropped(STOP_TIMEOUT_MS) @@ -266,3 +257,43 @@ async fn activate_z_coin_light() { }; assert_eq!(balance.balance.spendable, BigDecimal::default()); } + +#[wasm_bindgen_test] +async fn test_get_wallet_names() { + const DB_NAMESPACE_NUM: u64 = 1; + + let coins = json!([]); + + // Initialize the first wallet with a specific name + let wallet_1 = Mm2TestConf::seednode_with_wallet_name(&coins, "wallet_1", "pass"); + let mm_wallet_1 = + MarketMakerIt::start_with_db(wallet_1.conf, wallet_1.rpc_password, Some(wasm_start), DB_NAMESPACE_NUM) + .await + .unwrap(); + + // Retrieve and verify the wallet names for the first wallet + let get_wallet_names_1 = get_wallet_names(&mm_wallet_1).await; + assert_eq!(get_wallet_names_1.wallet_names, vec!["wallet_1"]); + assert_eq!(get_wallet_names_1.activated_wallet.unwrap(), "wallet_1"); + + // Stop the first wallet before starting the second one + mm_wallet_1 + .stop_and_wait_for_ctx_is_dropped(STOP_TIMEOUT_MS) + .await + .unwrap(); + + // Initialize the second wallet with a different name + let wallet_2 = Mm2TestConf::seednode_with_wallet_name(&coins, "wallet_2", "pass"); + let mm_wallet_2 = + MarketMakerIt::start_with_db(wallet_2.conf, wallet_2.rpc_password, Some(wasm_start), DB_NAMESPACE_NUM) + .await + .unwrap(); + + // Retrieve and verify the wallet names for the second wallet + let get_wallet_names_2 = get_wallet_names(&mm_wallet_2).await; + assert_eq!(get_wallet_names_2.wallet_names, vec!["wallet_1", "wallet_2"]); + assert_eq!(get_wallet_names_2.activated_wallet.unwrap(), "wallet_2"); + + // Stop the second wallet + mm_wallet_2.stop_and_wait_for_ctx_is_dropped(1000).await.unwrap(); +} diff --git a/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs b/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs index 137eb6ef09..fd6ad69dd8 100644 --- a/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs +++ b/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs @@ -14,15 +14,15 @@ use mm2_test_helpers::electrums::*; use mm2_test_helpers::for_tests::wait_check_stats_swap_status; use mm2_test_helpers::for_tests::{account_balance, btc_segwit_conf, btc_with_spv_conf, btc_with_sync_starting_header, check_recent_swaps, enable_qrc20, enable_utxo_v2_electrum, eth_dev_conf, - find_metrics_in_json, from_env_file, get_new_address, get_shared_db_id, mm_spat, - morty_conf, my_balance, rick_conf, sign_message, start_swaps, tbtc_conf, - tbtc_segwit_conf, tbtc_with_spv_conf, test_qrc20_history_impl, tqrc20_conf, - verify_message, wait_for_swaps_finish_and_check_status, - wait_till_history_has_records, MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, - Mm2TestConfForSwap, RaiiDump, DOC_ELECTRUM_ADDRS, ETH_MAINNET_NODE, - ETH_MAINNET_SWAP_CONTRACT, ETH_SEPOLIA_NODES, ETH_SEPOLIA_SWAP_CONTRACT, - MARTY_ELECTRUM_ADDRS, MORTY, QRC20_ELECTRUMS, RICK, RICK_ELECTRUM_ADDRS, - TBTC_ELECTRUMS, T_BCH_ELECTRUMS}; + find_metrics_in_json, from_env_file, get_new_address, get_shared_db_id, + get_wallet_names, mm_spat, morty_conf, my_balance, rick_conf, sign_message, + start_swaps, tbtc_conf, tbtc_segwit_conf, tbtc_with_spv_conf, + test_qrc20_history_impl, tqrc20_conf, verify_message, + wait_for_swaps_finish_and_check_status, wait_till_history_has_records, + MarketMakerIt, Mm2InitPrivKeyPolicy, Mm2TestConf, Mm2TestConfForSwap, RaiiDump, + DOC_ELECTRUM_ADDRS, ETH_MAINNET_NODE, ETH_MAINNET_SWAP_CONTRACT, ETH_SEPOLIA_NODES, + ETH_SEPOLIA_SWAP_CONTRACT, MARTY_ELECTRUM_ADDRS, MORTY, QRC20_ELECTRUMS, RICK, + RICK_ELECTRUM_ADDRS, TBTC_ELECTRUMS, T_BCH_ELECTRUMS}; use mm2_test_helpers::get_passphrase; use mm2_test_helpers::structs::*; use serde_json::{self as json, json, Value as Json}; @@ -5809,6 +5809,41 @@ fn test_get_shared_db_id() { ); } +#[test] +#[cfg(not(target_arch = "wasm32"))] +fn test_get_wallet_names() { + let coins = json!([]); + + // Initialize the first wallet with a specific name + let wallet_1 = Mm2TestConf::seednode_with_wallet_name(&coins, "wallet_1", "pass"); + let mm_wallet_1 = MarketMakerIt::start(wallet_1.conf, wallet_1.rpc_password, None).unwrap(); + + // Retrieve and verify the wallet names for the first wallet + let get_wallet_names_1 = block_on(get_wallet_names(&mm_wallet_1)); + assert_eq!(get_wallet_names_1.wallet_names, vec!["wallet_1"]); + assert_eq!(get_wallet_names_1.activated_wallet.unwrap(), "wallet_1"); + + // Initialize the second wallet with a different name + let mut wallet_2 = Mm2TestConf::seednode_with_wallet_name(&coins, "wallet_2", "pass"); + + // Set the database directory for the second wallet to the same as the first wallet + wallet_2.conf["dbdir"] = mm_wallet_1.folder.join("DB").to_str().unwrap().into(); + + // Stop the first wallet before starting the second one + block_on(mm_wallet_1.stop()).unwrap(); + + // Start the second wallet + let mm_wallet_2 = MarketMakerIt::start(wallet_2.conf, wallet_2.rpc_password, None).unwrap(); + + // Retrieve and verify the wallet names for the second wallet + let get_wallet_names_2 = block_on(get_wallet_names(&mm_wallet_2)); + assert_eq!(get_wallet_names_2.wallet_names, vec!["wallet_1", "wallet_2"]); + assert_eq!(get_wallet_names_2.activated_wallet.unwrap(), "wallet_2"); + + // Stop the second wallet + block_on(mm_wallet_2.stop()).unwrap(); +} + #[test] #[cfg(not(target_arch = "wasm32"))] fn test_sign_raw_transaction_rick() { diff --git a/mm2src/mm2_test_helpers/src/for_tests.rs b/mm2src/mm2_test_helpers/src/for_tests.rs index e650ef4293..f57586ccf1 100644 --- a/mm2src/mm2_test_helpers/src/for_tests.rs +++ b/mm2src/mm2_test_helpers/src/for_tests.rs @@ -310,6 +310,21 @@ impl Mm2TestConf { } } + pub fn seednode_with_wallet_name(coins: &Json, wallet_name: &str, wallet_password: &str) -> Self { + Mm2TestConf { + conf: json!({ + "gui": "nogui", + "netid": 9998, + "coins": coins, + "rpc_password": DEFAULT_RPC_PASSWORD, + "i_am_seed": true, + "wallet_name": wallet_name, + "wallet_password": wallet_password, + }), + rpc_password: DEFAULT_RPC_PASSWORD.into(), + } + } + pub fn light_node(passphrase: &str, coins: &Json, seednodes: &[&str]) -> Self { Mm2TestConf { conf: json!({ @@ -1357,17 +1372,49 @@ impl MarketMakerIt { /// Start a new MarketMaker locally. /// /// * `conf` - The command-line configuration passed to the MarketMaker. + /// * `userpass` - RPC API key. + /// * `local` - Function to start the MarketMaker locally. + /// * `envs` - The environment variables passed to the process. + /// The argument is ignored for nodes running in a browser. + #[cfg(target_arch = "wasm32")] + pub async fn start_with_envs( + conf: Json, + userpass: String, + local: Option, + _envs: &[(&str, &str)], + ) -> Result { + MarketMakerIt::start_market_maker(conf, userpass, local, None).await + } + + /// Start a new MarketMaker locally with a specific database namespace. + /// + /// * `conf` - The command-line configuration passed to the MarketMaker. + /// * `userpass` - RPC API key. + /// * `local` - Function to start the MarketMaker locally. + /// * `db_namespace_id` - The test database namespace identifier. + #[cfg(target_arch = "wasm32")] + pub async fn start_with_db( + conf: Json, + userpass: String, + local: Option, + db_namespace_id: u64, + ) -> Result { + MarketMakerIt::start_market_maker(conf, userpass, local, Some(db_namespace_id)).await + } + + /// Common helper function to start the MarketMaker. + /// + /// * `conf` - The command-line configuration passed to the MarketMaker. /// Unique P2P in-memory port is injected as `p2p_in_memory_port` unless this field is already present. /// * `userpass` - RPC API key. We should probably extract it automatically from the MM log. /// * `local` - Function to start the MarketMaker locally. Required for nodes running in a browser. - /// * `envs` - The enviroment variables passed to the process. - /// The argument is ignore for nodes running in a browser. + /// * `db_namespace_id` - Optional test database namespace identifier. #[cfg(target_arch = "wasm32")] - pub async fn start_with_envs( + async fn start_market_maker( mut conf: Json, userpass: String, local: Option, - _envs: &[(&str, &str)], + db_namespace_id: Option, ) -> Result { if conf["p2p_in_memory"].is_null() { conf["p2p_in_memory"] = Json::Bool(true); @@ -1383,10 +1430,19 @@ impl MarketMakerIt { conf["p2p_in_memory_port"] = Json::Number(new_p2p_port.into()); } - let ctx = mm2_core::mm_ctx::MmCtxBuilder::new() - .with_conf(conf.clone()) - .with_test_db_namespace() - .into_mm_arc(); + let ctx = { + let builder = MmCtxBuilder::new() + .with_conf(conf.clone()); + + let builder = if let Some(ns) = db_namespace_id { + builder.with_test_db_namespace_with_id(ns) + } else { + builder.with_test_db_namespace() + }; + + builder.into_mm_arc() + }; + let local = try_s!(local.ok_or("!local")); local(ctx.clone()); @@ -2844,6 +2900,20 @@ pub async fn get_shared_db_id(mm: &MarketMakerIt) -> GetSharedDbIdResult { res.result } +pub async fn get_wallet_names(mm: &MarketMakerIt) -> GetWalletNamesResult { + let request = mm + .rpc(&json!({ + "userpass": mm.userpass, + "method": "get_wallet_names", + "mmrpc": "2.0", + })) + .await + .unwrap(); + assert_eq!(request.0, StatusCode::OK, "'get_wallet_names' failed: {}", request.1); + let res: RpcSuccessResponse<_> = json::from_str(&request.1).unwrap(); + res.result +} + pub async fn max_maker_vol(mm: &MarketMakerIt, coin: &str) -> RpcResponse { let rc = mm .rpc(&json!({ diff --git a/mm2src/mm2_test_helpers/src/structs.rs b/mm2src/mm2_test_helpers/src/structs.rs index aa2246186c..8bdcfec722 100644 --- a/mm2src/mm2_test_helpers/src/structs.rs +++ b/mm2src/mm2_test_helpers/src/structs.rs @@ -827,6 +827,13 @@ pub struct GetSharedDbIdResult { pub shared_db_id: String, } +#[derive(Debug, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct GetWalletNamesResult { + pub wallet_names: Vec, + pub activated_wallet: Option, +} + #[derive(Debug, Deserialize)] #[serde(deny_unknown_fields)] pub struct RpcV2Response { From 874b294e54041a498910e39a444007b379c4b0f1 Mon Sep 17 00:00:00 2001 From: shamardy Date: Thu, 19 Sep 2024 11:47:03 +0300 Subject: [PATCH 06/11] use STOP_TIMEOUT_MS const --- mm2src/mm2_main/src/wasm_tests.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mm2src/mm2_main/src/wasm_tests.rs b/mm2src/mm2_main/src/wasm_tests.rs index c73047cb20..bd24bf4a4c 100644 --- a/mm2src/mm2_main/src/wasm_tests.rs +++ b/mm2src/mm2_main/src/wasm_tests.rs @@ -295,5 +295,8 @@ async fn test_get_wallet_names() { assert_eq!(get_wallet_names_2.activated_wallet.unwrap(), "wallet_2"); // Stop the second wallet - mm_wallet_2.stop_and_wait_for_ctx_is_dropped(1000).await.unwrap(); + mm_wallet_2 + .stop_and_wait_for_ctx_is_dropped(STOP_TIMEOUT_MS) + .await + .unwrap(); } From bea5479fdb189b278c12911d8be284303ef2973a Mon Sep 17 00:00:00 2001 From: shamardy Date: Fri, 20 Sep 2024 02:38:59 +0300 Subject: [PATCH 07/11] review fix: refactor `read_file_names_with_extension` and `read_file_stems_with_extension` into a single `list_files_by_extension` function --- mm2src/mm2_io/src/fs.rs | 29 ++++++++++--------- .../src/lp_wallet/mnemonics_storage.rs | 4 +-- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/mm2src/mm2_io/src/fs.rs b/mm2src/mm2_io/src/fs.rs index ca3dea83f9..b51204b026 100644 --- a/mm2src/mm2_io/src/fs.rs +++ b/mm2src/mm2_io/src/fs.rs @@ -192,7 +192,7 @@ where json::from_slice(&content).map_to_mm(FsJsonError::Deserializing) } -async fn filter_files_with_extension(dir_path: &Path, extension: &str) -> IoResult> { +async fn filter_files_by_extension(dir_path: &Path, extension: &str) -> IoResult> { let ext = Some(OsStr::new(extension).to_ascii_lowercase()); let entries = read_dir_async(dir_path) .await? @@ -213,17 +213,20 @@ where .collect() } -/// Reads the file names with the specified extension from the given directory path. -pub async fn read_file_names_with_extension(dir_path: &Path, extension: &str) -> IoResult> { - let entries = filter_files_with_extension(dir_path, extension).await?; - Ok(extract_file_identifiers(entries, Path::file_name)) -} - -/// Reads the file stems with the specified extension from the given directory path. -/// The stem is the file name without the extension. -pub async fn read_file_stems_with_extension(dir_path: &Path, extension: &str) -> IoResult> { - let entries = filter_files_with_extension(dir_path, extension).await?; - Ok(extract_file_identifiers(entries, Path::file_stem)) +/// Lists files by the specified extension from the given directory path. +/// If include_extension is true, returns full file names; otherwise, returns file stems. +pub async fn list_files_by_extension( + dir_path: &Path, + extension: &str, + include_extension: bool, +) -> IoResult> { + let entries = filter_files_by_extension(dir_path, extension).await?; + let extractor = if include_extension { + Path::file_name + } else { + Path::file_stem + }; + Ok(extract_file_identifiers(entries, extractor)) } /// Read the `dir_path` entries trying to deserialize each as the `T` type, @@ -233,7 +236,7 @@ pub async fn read_files_with_extension(dir_path: &Path, extension: &str) -> F where T: DeserializeOwned, { - let entries = filter_files_with_extension(dir_path, extension) + let entries = filter_files_by_extension(dir_path, extension) .await .mm_err(FsJsonError::IoReading)?; let type_name = std::any::type_name::(); diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs index 5e0e49214e..97a745facf 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs @@ -1,7 +1,7 @@ use crypto::EncryptedData; use mm2_core::mm_ctx::MmArc; use mm2_err_handle::prelude::*; -use mm2_io::fs::{ensure_file_is_writable, read_file_stems_with_extension}; +use mm2_io::fs::{ensure_file_is_writable, list_files_by_extension}; type WalletsStorageResult = Result>; @@ -63,7 +63,7 @@ pub(super) async fn read_encrypted_passphrase_if_available(ctx: &MmArc) -> Walle } pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsStorageResult> { - let wallet_names = read_file_stems_with_extension(&ctx.db_root(), "dat") + let wallet_names = list_files_by_extension(&ctx.db_root(), "dat", false) .await .mm_err(|e| WalletsStorageError::FsReadError(format!("Error reading wallets directory: {}", e)))?; Ok(wallet_names) From e1dbb67da0d66aff783ab63a8449896b8d8f9728 Mon Sep 17 00:00:00 2001 From: shamardy Date: Fri, 20 Sep 2024 02:41:08 +0300 Subject: [PATCH 08/11] review fix: add `#[inline(always)]` to `read_dir_json` --- mm2src/mm2_io/src/fs.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/mm2src/mm2_io/src/fs.rs b/mm2src/mm2_io/src/fs.rs index b51204b026..00838ae1cc 100644 --- a/mm2src/mm2_io/src/fs.rs +++ b/mm2src/mm2_io/src/fs.rs @@ -269,6 +269,7 @@ where /// Read the `dir_path` entries trying to deserialize each as the `T` type from JSON files. /// Please note that files that couldn't be deserialized are skipped. +#[inline(always)] pub async fn read_dir_json(dir_path: &Path) -> FsJsonResult> where T: DeserializeOwned, From aaf9d196f76339c190188e99d588e32dfaba53bb Mon Sep 17 00:00:00 2001 From: shamardy Date: Fri, 20 Sep 2024 04:42:53 +0300 Subject: [PATCH 09/11] try to fix test_electrum_tx_history --- .../tests/mm2_tests/mm2_tests_inner.rs | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs b/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs index fd6ad69dd8..57a4709758 100644 --- a/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs +++ b/mm2src/mm2_main/tests/mm2_tests/mm2_tests_inner.rs @@ -2351,7 +2351,7 @@ fn test_electrum_tx_history() { {"coin":"RICK","asset":"RICK","rpcport":8923,"txversion":4,"overwintered":1,"protocol":{"type":"UTXO"}}, ]); - let mut mm = MarketMakerIt::start( + let mm_bob = MarketMakerIt::start( json! ({ "gui": "nogui", "netid": 9998, @@ -2367,14 +2367,26 @@ fn test_electrum_tx_history() { None, ) .unwrap(); + let (_dump_log, _dump_dashboard) = mm_bob.mm_dump(); + log!("log path: {}", mm_bob.log_path.display()); + + let bob_electrum = block_on(enable_electrum(&mm_bob, "RICK", false, DOC_ELECTRUM_ADDRS)); + let mut enable_res_bob = HashMap::new(); + enable_res_bob.insert("RICK", bob_electrum); + log!("enable_coins_bob: {:?}", enable_res_bob); + + let mmconf = Mm2TestConf::seednode_with_wallet_name(&coins, "wallet", "pass"); + let mut mm = MarketMakerIt::start(mmconf.conf, mmconf.rpc_password, None).unwrap(); let (_dump_log, _dump_dashboard) = mm.mm_dump(); log!("log path: {}", mm.log_path.display()); // Enable RICK electrum client with tx_history loop. let electrum = block_on(enable_electrum(&mm, "RICK", true, DOC_ELECTRUM_ADDRS)); + log!("enable_coins: {:?}", electrum); + let receiving_address = electrum.address; // Wait till tx_history will not be loaded - block_on(mm.wait_for_log(500., |log| log.contains("history has been loaded successfully"))).unwrap(); + block_on(mm.wait_for_log(5., |log| log.contains("history has been loaded successfully"))).unwrap(); // tx_history is requested every 30 seconds, wait another iteration thread::sleep(Duration::from_secs(31)); @@ -2384,16 +2396,13 @@ fn test_electrum_tx_history() { assert_eq!(get_tx_history_request_count(&mm), 1); // make a transaction to change balance - let mut enable_res = HashMap::new(); - enable_res.insert("RICK", electrum); - log!("enable_coins: {:?}", enable_res); withdraw_and_send( - &mm, + &mm_bob, "RICK", None, - "RRYmiZSDo3UdHHqj1rLKf8cbJroyv9NxXw", - &enable_res, - "-0.00001", + &receiving_address, + &enable_res_bob, + "-0.00101", 0.001, ); From de645bdd394c6090d84a6812f4580ff51f0df91d Mon Sep 17 00:00:00 2001 From: shamardy Date: Mon, 23 Sep 2024 12:26:15 +0300 Subject: [PATCH 10/11] review fix: use impl iterator where appropriate --- mm2src/mm2_io/src/fs.rs | 9 ++++----- mm2src/mm2_main/src/lp_wallet.rs | 2 +- mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs | 2 +- mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mm2src/mm2_io/src/fs.rs b/mm2src/mm2_io/src/fs.rs index 00838ae1cc..489b3bad8b 100644 --- a/mm2src/mm2_io/src/fs.rs +++ b/mm2src/mm2_io/src/fs.rs @@ -203,14 +203,13 @@ async fn filter_files_by_extension(dir_path: &Path, extension: &str) -> IoResult } /// Helper function to extract file names or stems based on the provided extraction function. -fn extract_file_identifiers(entries: Vec, extractor: F) -> Vec +fn extract_file_identifiers<'a, F>(entries: Vec, extractor: F) -> impl Iterator + 'a where - F: Fn(&Path) -> Option<&OsStr>, + F: Fn(&Path) -> Option<&OsStr> + 'a, { entries .into_iter() - .filter_map(|path| extractor(&path).and_then(OsStr::to_str).map(ToOwned::to_owned)) - .collect() + .filter_map(move |path| extractor(&path).and_then(OsStr::to_str).map(ToOwned::to_owned)) } /// Lists files by the specified extension from the given directory path. @@ -219,7 +218,7 @@ pub async fn list_files_by_extension( dir_path: &Path, extension: &str, include_extension: bool, -) -> IoResult> { +) -> IoResult> { let entries = filter_files_by_extension(dir_path, extension).await?; let extractor = if include_extension { Path::file_name diff --git a/mm2src/mm2_main/src/lp_wallet.rs b/mm2src/mm2_main/src/lp_wallet.rs index 0efc631643..559821a26a 100644 --- a/mm2src/mm2_main/src/lp_wallet.rs +++ b/mm2src/mm2_main/src/lp_wallet.rs @@ -538,7 +538,7 @@ impl From for GetWalletsError { /// Retrieves all created wallets and the currently activated wallet. pub async fn get_wallet_names_rpc(ctx: MmArc, _req: Json) -> MmResult { // We want to return wallet names in the same order for both native and wasm32 targets. - let wallets = read_all_wallet_names(&ctx).await?.into_iter().sorted().collect(); + let wallets = read_all_wallet_names(&ctx).await?.sorted().collect(); // Note: `ok_or` is used here on `Constructible>` to handle the case where the wallet name is not set. // `wallet_name` can be `None` in the case of no-login mode. let activated_wallet = ctx.wallet_name.ok_or(GetWalletsError::Internal( diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs index 97a745facf..c873b2d5ff 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs @@ -62,7 +62,7 @@ pub(super) async fn read_encrypted_passphrase_if_available(ctx: &MmArc) -> Walle }) } -pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsStorageResult> { +pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsStorageResult> { let wallet_names = list_files_by_extension(&ctx.db_root(), "dat", false) .await .mm_err(|e| WalletsStorageError::FsReadError(format!("Error reading wallets directory: {}", e)))?; diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs index 06dd565ce5..a815bfcca1 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs @@ -145,7 +145,7 @@ pub(super) async fn read_encrypted_passphrase_if_available(ctx: &MmArc) -> Walle .transpose() } -pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsDBResult> { +pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsDBResult> { let wallets_ctx = WalletsContext::from_ctx(ctx).map_to_mm(WalletsDBError::Internal)?; let db = wallets_ctx.wallets_db().await?; @@ -153,7 +153,7 @@ pub(super) async fn read_all_wallet_names(ctx: &MmArc) -> WalletsDBResult().await?; let all_items = table.get_all_items().await?; - let wallet_names = all_items.into_iter().map(|(_, item)| item.wallet_name).collect(); + let wallet_names = all_items.into_iter().map(|(_, item)| item.wallet_name); Ok(wallet_names) } From 4e46c358ca4d742c3829e327cdd640de17f77e98 Mon Sep 17 00:00:00 2001 From: shamardy Date: Wed, 25 Sep 2024 15:37:37 +0300 Subject: [PATCH 11/11] review fix: fix `DbNamespaceId` enum to be wasm only and inline `for_test_with_id` --- mm2src/mm2_core/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mm2src/mm2_core/src/lib.rs b/mm2src/mm2_core/src/lib.rs index 3c0a118430..88b0fd5c81 100644 --- a/mm2src/mm2_core/src/lib.rs +++ b/mm2src/mm2_core/src/lib.rs @@ -1,10 +1,11 @@ -use derive_more::Display; -use rand::{thread_rng, Rng}; +#[cfg(target_arch = "wasm32")] use derive_more::Display; +#[cfg(target_arch = "wasm32")] use rand::{thread_rng, Rng}; pub mod data_asker; pub mod event_dispatcher; pub mod mm_ctx; +#[cfg(target_arch = "wasm32")] #[derive(Clone, Copy, Display, PartialEq, Default)] pub enum DbNamespaceId { #[display(fmt = "MAIN")] @@ -14,11 +15,13 @@ pub enum DbNamespaceId { Test(u64), } +#[cfg(target_arch = "wasm32")] impl DbNamespaceId { pub fn for_test() -> DbNamespaceId { let mut rng = thread_rng(); DbNamespaceId::Test(rng.gen()) } + #[inline(always)] pub fn for_test_with_id(id: u64) -> DbNamespaceId { DbNamespaceId::Test(id) } }