From 209d2b8a1db0e3f39f6e33631495713648c317a2 Mon Sep 17 00:00:00 2001 From: ardocrat Date: Sat, 18 May 2024 20:04:11 +0300 Subject: [PATCH] wallet: ability to restore wallet by deleting database --- locales/en.yml | 1 + locales/ru.yml | 3 +- src/gui/views/wallets/setup/recovery.rs | 18 ++++++++- src/wallet/config.rs | 14 +++++-- src/wallet/wallet.rs | 51 +++++++++++++++---------- 5 files changed, 61 insertions(+), 26 deletions(-) diff --git a/locales/en.yml b/locales/en.yml index 0925df5..ce9fb3a 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -118,6 +118,7 @@ wallets: tx_send_cancel_conf: 'Are you sure you want to cancel sending of %{amount} ツ?' tx_receive_cancel_conf: 'Are you sure you want to cancel receiving of %{amount} ツ?' rec_phrase_not_found: Recovery phrase not found. + restore_wallet_desc: Restore wallet by deleting all files if usual repair not helped, you will need to re-open your wallet. transport: desc: 'Use transport to receive or send messages synchronously:' tor_network: Tor network diff --git a/locales/ru.yml b/locales/ru.yml index dd11c12..de6e433 100644 --- a/locales/ru.yml +++ b/locales/ru.yml @@ -103,7 +103,7 @@ wallets: enter_amount_send: 'У вас есть %{amount} ツ. Введите количество для отправки:' enter_amount_receive: 'Введите количество для получения:' recovery: Восстановление - repair_wallet: Починить кошелёк + repair_wallet: Исправить кошелёк repair_desc: Проверить кошелёк, исправляя и восстанавливая недостающие выходы, если это необходимо. Эта операция займёт время. repair_unavailable: Необходимо активное подключение к узлу и завершённая синхронизация кошелька. delete: Удалить кошелёк @@ -118,6 +118,7 @@ wallets: tx_send_cancel_conf: 'Вы действительно хотите отменить отправку %{amount} ツ?' tx_receive_cancel_conf: 'Вы действительно хотите отменить получение %{amount} ツ?' rec_phrase_not_found: Фраза восстановления не найдена. + restore_wallet_desc: Восстановить кошелёк, удалив все файлы, если обычное исправление не помогло, вам будет необходимо переоткрыть кошелёк. transport: desc: 'Используйте транспорт для синхронных получения или отправки сообщений:' tor_network: Сеть Tor diff --git a/src/gui/views/wallets/setup/recovery.rs b/src/gui/views/wallets/setup/recovery.rs index 0278aaa..f55a443 100644 --- a/src/gui/views/wallets/setup/recovery.rs +++ b/src/gui/views/wallets/setup/recovery.rs @@ -17,7 +17,7 @@ use grin_chain::SyncStatus; use grin_util::ZeroingString; use crate::gui::Colors; -use crate::gui::icons::{EYE, STETHOSCOPE, TRASH, WRENCH}; +use crate::gui::icons::{EYE, LIFEBUOY, STETHOSCOPE, TRASH, WRENCH}; use crate::gui::platform::PlatformCallbacks; use crate::gui::views::{Modal, View}; use crate::gui::views::types::{ModalPosition, TextEditOptions}; @@ -93,6 +93,20 @@ impl RecoverySetup { View::horizontal_line(ui, Colors::ITEM_STROKE); ui.add_space(6.0); + // Draw button to restore the wallet. + let recover_text = format!("{} {}", LIFEBUOY, t!("wallets.recover")); + View::colored_text_button(ui, recover_text, Colors::GREEN, Colors::BUTTON, || { + wallet.delete_db(true); + }); + ui.add_space(6.0); + ui.label(RichText::new(t!("wallets.restore_wallet_desc")) + .size(16.0) + .color(Colors::INACTIVE_TEXT)); + + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + let recovery_text = format!("{}:", t!("wallets.recovery_phrase")); ui.label(RichText::new(recovery_text).size(16.0).color(Colors::GRAY)); ui.add_space(6.0); @@ -111,7 +125,7 @@ impl RecoverySetup { // Draw button to delete the wallet. let delete_text = format!("{} {}", TRASH, t!("wallets.delete")); - View::button(ui, delete_text, Colors::GOLD, || { + View::colored_text_button(ui, delete_text, Colors::RED, Colors::BUTTON, || { Modal::new(DELETE_CONFIRMATION_MODAL) .position(ModalPosition::Center) .title(t!("modal.confirmation")) diff --git a/src/wallet/config.rs b/src/wallet/config.rs index c303885..6833085 100644 --- a/src/wallet/config.rs +++ b/src/wallet/config.rs @@ -119,9 +119,17 @@ impl WalletConfig { /// Get current wallet data path. pub fn get_data_path(&self) -> String { let chain_type = AppConfig::chain_type(); - let mut config_path = Self::get_base_path(chain_type); - config_path.push(self.id.to_string()); - config_path.to_str().unwrap().to_string() + let mut data_path = Self::get_base_path(chain_type); + data_path.push(self.id.to_string()); + data_path.to_str().unwrap().to_string() + } + + /// Get wallet database data path. + pub fn get_db_path(&self) -> String { + let mut path = PathBuf::from(self.get_data_path()); + path.push("wallet_data"); + path.push("db"); + path.to_str().unwrap().to_string() } /// Get Slatepacks data path for current wallet. diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index d362608..4c62641 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -395,7 +395,6 @@ impl Wallet { // Close wallet at separate thread. let wallet_close = self.clone(); - let instance = wallet_close.instance.clone().unwrap(); let service_id = wallet_close.identifier(); thread::spawn(move || { // Stop running API server. @@ -407,17 +406,14 @@ impl Wallet { w_api_server.as_mut().unwrap().0.stop(); *w_api_server = None; } - // Stop running Tor service. Tor::stop_service(&service_id); - // Close the wallet. + let instance = wallet_close.instance.clone().unwrap(); Self::close_wallet(&instance); - // Mark wallet as not opened. wallet_close.closing.store(false, Ordering::Relaxed); wallet_close.is_open.store(false, Ordering::Relaxed); - // Wake up thread to exit. wallet_close.sync(true); }); @@ -969,6 +965,27 @@ impl Wallet { self.repair_progress.load(Ordering::Relaxed) } + /// Deleting wallet database files. + pub fn delete_db(&self, reopen: bool) { + let wallet_delete = self.clone(); + // Close wallet if open. + if self.is_open() { + self.close(); + } + thread::spawn(move || { + // Wait wallet to be closed. + if wallet_delete.is_open() { + thread::sleep(Duration::from_millis(300)); + } + // Remove wallet db files. + let _ = fs::remove_dir_all(wallet_delete.get_config().get_db_path()); + // Start sync to close thread. + wallet_delete.sync(true); + // Mark wallet to reopen. + wallet_delete.set_reopen(reopen); + }); + } + /// Get recovery phrase. pub fn get_recovery(&self, password: String) -> Result { let instance = self.instance.clone().unwrap(); @@ -979,27 +996,21 @@ impl Wallet { /// Close the wallet, delete its files and mark it as deleted. pub fn delete_wallet(&self) { - if !self.is_open() || self.instance.is_none() { - return; - } - self.closing.store(true, Ordering::Relaxed); - - // Delete wallet at separate thread. let wallet_delete = self.clone(); - let instance = wallet_delete.instance.clone().unwrap(); + // Close wallet if open. + if self.is_open() { + self.close(); + } thread::spawn(move || { - // Close the wallet. - Self::close_wallet(&instance); - + // Wait wallet to be closed. + if wallet_delete.is_open() { + thread::sleep(Duration::from_millis(300)); + } // Remove wallet files. let _ = fs::remove_dir_all(wallet_delete.get_config().get_data_path()); - // Mark wallet as not opened and deleted. - wallet_delete.closing.store(false, Ordering::Relaxed); - wallet_delete.is_open.store(false, Ordering::Relaxed); wallet_delete.deleted.store(true, Ordering::Relaxed); - - // Start sync to exit. + // Start sync to close thread. wallet_delete.sync(true); }); }