wallet: ability to restore wallet by deleting database

This commit is contained in:
ardocrat 2024-05-18 20:04:11 +03:00
parent 8244f2a2fb
commit 209d2b8a1d
5 changed files with 61 additions and 26 deletions

View file

@ -118,6 +118,7 @@ wallets:
tx_send_cancel_conf: 'Are you sure you want to cancel sending of %{amount} ツ?' 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} ツ?' tx_receive_cancel_conf: 'Are you sure you want to cancel receiving of %{amount} ツ?'
rec_phrase_not_found: Recovery phrase not found. 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: transport:
desc: 'Use transport to receive or send messages synchronously:' desc: 'Use transport to receive or send messages synchronously:'
tor_network: Tor network tor_network: Tor network

View file

@ -103,7 +103,7 @@ wallets:
enter_amount_send: 'У вас есть %{amount} ツ. Введите количество для отправки:' enter_amount_send: 'У вас есть %{amount} ツ. Введите количество для отправки:'
enter_amount_receive: 'Введите количество для получения:' enter_amount_receive: 'Введите количество для получения:'
recovery: Восстановление recovery: Восстановление
repair_wallet: Починить кошелёк repair_wallet: Исправить кошелёк
repair_desc: Проверить кошелёк, исправляя и восстанавливая недостающие выходы, если это необходимо. Эта операция займёт время. repair_desc: Проверить кошелёк, исправляя и восстанавливая недостающие выходы, если это необходимо. Эта операция займёт время.
repair_unavailable: Необходимо активное подключение к узлу и завершённая синхронизация кошелька. repair_unavailable: Необходимо активное подключение к узлу и завершённая синхронизация кошелька.
delete: Удалить кошелёк delete: Удалить кошелёк
@ -118,6 +118,7 @@ wallets:
tx_send_cancel_conf: 'Вы действительно хотите отменить отправку %{amount} ツ?' tx_send_cancel_conf: 'Вы действительно хотите отменить отправку %{amount} ツ?'
tx_receive_cancel_conf: 'Вы действительно хотите отменить получение %{amount} ツ?' tx_receive_cancel_conf: 'Вы действительно хотите отменить получение %{amount} ツ?'
rec_phrase_not_found: Фраза восстановления не найдена. rec_phrase_not_found: Фраза восстановления не найдена.
restore_wallet_desc: Восстановить кошелёк, удалив все файлы, если обычное исправление не помогло, вам будет необходимо переоткрыть кошелёк.
transport: transport:
desc: 'Используйте транспорт для синхронных получения или отправки сообщений:' desc: 'Используйте транспорт для синхронных получения или отправки сообщений:'
tor_network: Сеть Tor tor_network: Сеть Tor

View file

@ -17,7 +17,7 @@ use grin_chain::SyncStatus;
use grin_util::ZeroingString; use grin_util::ZeroingString;
use crate::gui::Colors; 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::platform::PlatformCallbacks;
use crate::gui::views::{Modal, View}; use crate::gui::views::{Modal, View};
use crate::gui::views::types::{ModalPosition, TextEditOptions}; use crate::gui::views::types::{ModalPosition, TextEditOptions};
@ -93,6 +93,20 @@ impl RecoverySetup {
View::horizontal_line(ui, Colors::ITEM_STROKE); View::horizontal_line(ui, Colors::ITEM_STROKE);
ui.add_space(6.0); 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")); let recovery_text = format!("{}:", t!("wallets.recovery_phrase"));
ui.label(RichText::new(recovery_text).size(16.0).color(Colors::GRAY)); ui.label(RichText::new(recovery_text).size(16.0).color(Colors::GRAY));
ui.add_space(6.0); ui.add_space(6.0);
@ -111,7 +125,7 @@ impl RecoverySetup {
// Draw button to delete the wallet. // Draw button to delete the wallet.
let delete_text = format!("{} {}", TRASH, t!("wallets.delete")); 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) Modal::new(DELETE_CONFIRMATION_MODAL)
.position(ModalPosition::Center) .position(ModalPosition::Center)
.title(t!("modal.confirmation")) .title(t!("modal.confirmation"))

View file

@ -119,9 +119,17 @@ impl WalletConfig {
/// Get current wallet data path. /// Get current wallet data path.
pub fn get_data_path(&self) -> String { pub fn get_data_path(&self) -> String {
let chain_type = AppConfig::chain_type(); let chain_type = AppConfig::chain_type();
let mut config_path = Self::get_base_path(chain_type); let mut data_path = Self::get_base_path(chain_type);
config_path.push(self.id.to_string()); data_path.push(self.id.to_string());
config_path.to_str().unwrap().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. /// Get Slatepacks data path for current wallet.

View file

@ -395,7 +395,6 @@ impl Wallet {
// Close wallet at separate thread. // Close wallet at separate thread.
let wallet_close = self.clone(); let wallet_close = self.clone();
let instance = wallet_close.instance.clone().unwrap();
let service_id = wallet_close.identifier(); let service_id = wallet_close.identifier();
thread::spawn(move || { thread::spawn(move || {
// Stop running API server. // Stop running API server.
@ -407,17 +406,14 @@ impl Wallet {
w_api_server.as_mut().unwrap().0.stop(); w_api_server.as_mut().unwrap().0.stop();
*w_api_server = None; *w_api_server = None;
} }
// Stop running Tor service. // Stop running Tor service.
Tor::stop_service(&service_id); Tor::stop_service(&service_id);
// Close the wallet. // Close the wallet.
let instance = wallet_close.instance.clone().unwrap();
Self::close_wallet(&instance); Self::close_wallet(&instance);
// Mark wallet as not opened. // Mark wallet as not opened.
wallet_close.closing.store(false, Ordering::Relaxed); wallet_close.closing.store(false, Ordering::Relaxed);
wallet_close.is_open.store(false, Ordering::Relaxed); wallet_close.is_open.store(false, Ordering::Relaxed);
// Wake up thread to exit. // Wake up thread to exit.
wallet_close.sync(true); wallet_close.sync(true);
}); });
@ -969,6 +965,27 @@ impl Wallet {
self.repair_progress.load(Ordering::Relaxed) 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. /// Get recovery phrase.
pub fn get_recovery(&self, password: String) -> Result<ZeroingString, Error> { pub fn get_recovery(&self, password: String) -> Result<ZeroingString, Error> {
let instance = self.instance.clone().unwrap(); let instance = self.instance.clone().unwrap();
@ -979,27 +996,21 @@ impl Wallet {
/// Close the wallet, delete its files and mark it as deleted. /// Close the wallet, delete its files and mark it as deleted.
pub fn delete_wallet(&self) { 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 wallet_delete = self.clone();
let instance = wallet_delete.instance.clone().unwrap(); // Close wallet if open.
if self.is_open() {
self.close();
}
thread::spawn(move || { thread::spawn(move || {
// Close the wallet. // Wait wallet to be closed.
Self::close_wallet(&instance); if wallet_delete.is_open() {
thread::sleep(Duration::from_millis(300));
}
// Remove wallet files. // Remove wallet files.
let _ = fs::remove_dir_all(wallet_delete.get_config().get_data_path()); let _ = fs::remove_dir_all(wallet_delete.get_config().get_data_path());
// Mark wallet as not opened and deleted. // 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); wallet_delete.deleted.store(true, Ordering::Relaxed);
// Start sync to close thread.
// Start sync to exit.
wallet_delete.sync(true); wallet_delete.sync(true);
}); });
} }