diff --git a/Cargo.lock b/Cargo.lock index 04d065e..2c33380 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3796,7 +3796,7 @@ dependencies = [ [[package]] name = "grim" -version = "0.1.0" +version = "0.1.2" dependencies = [ "android-activity 0.6.0", "android_logger", diff --git a/Cargo.toml b/Cargo.toml index e8df5e6..73bb59c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "grim" -version = "0.1.0" +version = "0.1.2" authors = ["Ardocrat "] description = "Cross-platform GUI for Grin with focus on usability and availability to be used by anyone, anywhere." license = "Apache-2.0" diff --git a/src/gui/views/wallets/content.rs b/src/gui/views/wallets/content.rs index a98097b..61b34c0 100644 --- a/src/gui/views/wallets/content.rs +++ b/src/gui/views/wallets/content.rs @@ -589,7 +589,7 @@ impl WalletsContent { if self.pass_edit.is_empty() { return; } - match self.wallets.open_selected(self.pass_edit.clone()) { + match self.wallets.open_selected(&self.pass_edit) { Ok(_) => { // Clear values. self.pass_edit = "".to_string(); diff --git a/src/gui/views/wallets/creation/creation.rs b/src/gui/views/wallets/creation/creation.rs index b638b90..b44f091 100644 --- a/src/gui/views/wallets/creation/creation.rs +++ b/src/gui/views/wallets/creation/creation.rs @@ -43,7 +43,10 @@ pub struct WalletCreation { /// Mnemonic phrase setup content. pub(crate) mnemonic_setup: MnemonicSetup, /// Network setup content. - pub(crate) network_setup: ConnectionSettings + pub(crate) network_setup: ConnectionSettings, + + /// Flag to check if an error occurred during wallet creation. + creation_error: Option, } impl Default for WalletCreation { @@ -54,7 +57,8 @@ impl Default for WalletCreation { name_edit: String::from(""), pass_edit: String::from(""), mnemonic_setup: MnemonicSetup::default(), - network_setup: ConnectionSettings::default() + network_setup: ConnectionSettings::default(), + creation_error: None, } } } @@ -160,20 +164,32 @@ impl WalletCreation { .confirm_words .contains(&String::from("")); (text, available) - }, - Step::SetupConnection => (t!("wallets.setup_conn_desc"), true) + } + Step::SetupConnection => { + (t!("wallets.setup_conn_desc"), self.creation_error.is_none()) + } }; - // Show step description. - ui.add_space(2.0); - ui.label(RichText::new(step_text).size(16.0).color(Colors::gray())); - ui.add_space(2.0); - // Show error if entered phrase is not valid. - if !self.mnemonic_setup.valid_phrase { - step_available = false; - ui.label(RichText::new(t!("wallets.not_valid_phrase")) - .size(16.0) - .color(Colors::red())); + + // Show step description or error if entered phrase is not valid. + if self.mnemonic_setup.valid_phrase && self.creation_error.is_none() { ui.add_space(2.0); + ui.label(RichText::new(step_text).size(16.0).color(Colors::gray())); + ui.add_space(2.0); + } else { + step_available = false; + // Show error text. + if let Some(err) = &self.creation_error { + ui.add_space(10.0); + ui.label(RichText::new(err) + .size(16.0) + .color(Colors::red())); + ui.add_space(10.0); + } else { + ui.label(RichText::new(&t!("wallets.not_valid_phrase")) + .size(16.0) + .color(Colors::red())); + ui.add_space(2.0); + }; } if step == Step::EnterMnemonic { ui.add_space(4.0); @@ -278,24 +294,29 @@ impl WalletCreation { }, Step::SetupConnection => { // Create wallet at last step. - let name = self.name_edit.clone(); - let pass = self.pass_edit.clone(); - let phrase = self.mnemonic_setup.mnemonic.get_phrase(); let conn_method = &self.network_setup.method; - let mut wallet = Wallet::create(name, - pass.clone(), - phrase, - conn_method).unwrap(); - // Open created wallet. - wallet.open(pass).unwrap(); - // Pass created wallet to callback. - (on_create)(wallet); - // Reset input data. - self.step = None; - self.name_edit = String::from(""); - self.pass_edit = String::from(""); - self.mnemonic_setup.reset(); - None + match Wallet::create(&self.name_edit, + &self.pass_edit, + &self.mnemonic_setup.mnemonic, + conn_method) { + Ok(mut w) => { + // Open created wallet. + w.open(&self.pass_edit).unwrap(); + // Pass created wallet to callback. + (on_create)(w); + // Reset input data. + self.step = None; + self.name_edit = String::from(""); + self.pass_edit = String::from(""); + self.mnemonic_setup.reset(); + None + + } + Err(e) => { + self.creation_error = Some(format!("{:?}", e)); + Some(Step::SetupConnection) + } + } } } } else { @@ -364,6 +385,7 @@ impl WalletCreation { self.name_edit = String::from(""); self.pass_edit = String::from(""); self.mnemonic_setup.reset(); + self.creation_error = None; }, Step::ConfirmMnemonic => self.step = Some(Step::EnterMnemonic), Step::SetupConnection => self.step = Some(Step::EnterMnemonic) diff --git a/src/gui/views/wallets/creation/mnemonic.rs b/src/gui/views/wallets/creation/mnemonic.rs index 0df7ce1..bc4013d 100644 --- a/src/gui/views/wallets/creation/mnemonic.rs +++ b/src/gui/views/wallets/creation/mnemonic.rs @@ -261,6 +261,7 @@ impl MnemonicSetup { /// Reset mnemonic phrase to default values. pub fn reset(&mut self) { self.mnemonic = Mnemonic::default(); + self.valid_phrase = true; } /// Draw word input [`Modal`] content. @@ -307,8 +308,7 @@ impl MnemonicSetup { self.word_edit = self.word_edit.trim().to_string(); // Check if word is valid. - let word_index = self.word_num_edit - 1; - if !self.mnemonic.is_valid_word(&self.word_edit, word_index) { + if !self.mnemonic.is_valid_word(&self.word_edit) { self.valid_word_edit = false; return; } @@ -321,6 +321,7 @@ impl MnemonicSetup { }; // Save word at list. + let word_index = self.word_num_edit - 1; words.remove(word_index); words.insert(word_index, self.word_edit.clone()); diff --git a/src/wallet/list.rs b/src/wallet/list.rs index a8d5a45..2298cc3 100644 --- a/src/wallet/list.rs +++ b/src/wallet/list.rs @@ -133,11 +133,11 @@ impl WalletList { } /// Open selected [`Wallet`]. - pub fn open_selected(&mut self, password: String) -> Result<(), Error> { + pub fn open_selected(&mut self, password: &String) -> Result<(), Error> { let selected_id = self.selected_id.clone(); for w in self.mut_list() { if Some(w.get_config().id) == selected_id { - return w.open(password.clone()); + return w.open(password); } } Err(Error::GenericError("Wallet is not selected".to_string())) diff --git a/src/wallet/mnemonic.rs b/src/wallet/mnemonic.rs index 1ab4124..fec22b8 100644 --- a/src/wallet/mnemonic.rs +++ b/src/wallet/mnemonic.rs @@ -55,15 +55,9 @@ impl Mnemonic { self.confirm_words = Self::empty_words(&self.size); } - /// Check if provided word is in BIP39 format and equal to non-empty generated word at index. - pub fn is_valid_word(&self, word: &String, index: usize) -> bool { - let valid = search(word).is_ok(); - let equal = if let Some(gen_word) = self.words.get(index) { - gen_word.is_empty() || gen_word == word - } else { - false - }; - valid && equal + /// Check if provided word is in BIP39 format. + pub fn is_valid_word(&self, word: &String) -> bool { + search(word).is_ok() } /// Check if current phrase is valid. @@ -116,12 +110,12 @@ impl Mnemonic { return; } let mut words = vec![]; - words_split.enumerate().for_each(|(i, word)| { - if confirmation && !self.is_valid_word(&word.to_string(), i) { + words_split.for_each(|word| { + if confirmation && !self.is_valid_word(&word.to_string()) { words = vec![]; return; } - words.insert(i, word.to_string()) + words.push(word.to_string()) }); if confirmation { if !words.is_empty() { diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index 280465a..90938b9 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -46,7 +46,7 @@ use rand::Rng; use crate::AppConfig; use crate::node::{Node, NodeConfig}; use crate::tor::Tor; -use crate::wallet::{ConnectionsConfig, ExternalConnection, WalletConfig}; +use crate::wallet::{ConnectionsConfig, ExternalConnection, Mnemonic, WalletConfig}; use crate::wallet::store::TxHeightStore; use crate::wallet::types::{ConnectionMethod, WalletAccount, WalletData, WalletInstance, WalletTransaction}; @@ -127,21 +127,21 @@ impl Wallet { /// Create new wallet. pub fn create( - name: String, - password: String, - mnemonic: String, + name: &String, + password: &String, + mnemonic: &Mnemonic, conn_method: &ConnectionMethod ) -> Result { - let mut config = WalletConfig::create(name, conn_method); + let mut config = WalletConfig::create(name.clone(), conn_method); let w = Wallet::new(config.clone()); { let instance = Self::create_wallet_instance(&mut config)?; let mut w_lock = instance.lock(); let p = w_lock.lc_provider()?; p.create_wallet(None, - Some(ZeroingString::from(mnemonic.clone())), - mnemonic.len(), - ZeroingString::from(password), + Some(ZeroingString::from(mnemonic.get_phrase())), + mnemonic.size.entropy_size(), + ZeroingString::from(password.clone()), false, )?; } @@ -312,7 +312,7 @@ impl Wallet { } /// Open the wallet and start [`WalletData`] sync at separate thread. - pub fn open(&mut self, password: String) -> Result<(), Error> { + pub fn open(&mut self, password: &String) -> Result<(), Error> { if self.is_open() { return Err(Error::GenericError("Already opened".to_string())); } @@ -334,7 +334,7 @@ impl Wallet { let instance = self.instance.clone().unwrap(); let mut wallet_lock = instance.lock(); let lc = wallet_lock.lc_provider()?; - match lc.open_wallet(None, ZeroingString::from(password), false, false) { + match lc.open_wallet(None, ZeroingString::from(password.clone()), false, false) { Ok(_) => { // Reset an error on opening. self.set_sync_error(false);