Skip to content

Commit

Permalink
gui: Add Wallet Restore in the GUI
Browse files Browse the repository at this point in the history
  • Loading branch information
w0xlt committed Nov 14, 2021
1 parent 6d83b02 commit f202ddb
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ class WalletClient : public ChainClient
//! Load existing wallet.
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;

virtual std::unique_ptr<Wallet> restoreWallet(const std::string& backup_file, const std::string& wallet_name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;

//! Return default wallet directory.
virtual std::string getWalletDir() = 0;

Expand Down
21 changes: 21 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include <QCursor>
#include <QDateTime>
#include <QDragEnterEvent>
#include <QInputDialog>
#include <QListWidget>
#include <QMenu>
#include <QMenuBar>
Expand Down Expand Up @@ -360,6 +361,10 @@ void BitcoinGUI::createActions()
m_create_wallet_action->setEnabled(false);
m_create_wallet_action->setStatusTip(tr("Create a new wallet"));

m_restore_wallet_action = new QAction(tr("Restore Wallet…"), this);
m_restore_wallet_action->setEnabled(false);
m_restore_wallet_action->setStatusTip(tr("Restore a wallet from a backup file"));

m_close_all_wallets_action = new QAction(tr("Close All Wallets…"), this);
m_close_all_wallets_action->setStatusTip(tr("Close all wallets"));

Expand Down Expand Up @@ -433,6 +438,20 @@ void BitcoinGUI::createActions()
connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
activity->create();
});
connect(m_restore_wallet_action, &QAction::triggered, [this] {
QString backupFile = GUIUtil::getOpenFileName(this,
tr("Load Wallet Backup"), QString(),
tr("Wallet Data File (*.dat)"), nullptr);
if (backupFile.isEmpty()) return;

bool walletNameOk;
QString walletName = QInputDialog::getText(this, tr("Restore Name"), tr("Wallet Name:"), QLineEdit::Normal, "", &walletNameOk);
if (!walletNameOk || walletName.isEmpty()) return;

auto activity = new RestoreWalletActivity(m_wallet_controller, this);
connect(activity, &RestoreWalletActivity::restored, this, &BitcoinGUI::setCurrentWallet);
activity->restore(backupFile.toStdString(), walletName.toStdString());
});
connect(m_close_all_wallets_action, &QAction::triggered, [this] {
m_wallet_controller->closeAllWallets(this);
});
Expand Down Expand Up @@ -460,6 +479,7 @@ void BitcoinGUI::createMenuBar()
{
file->addAction(m_create_wallet_action);
file->addAction(m_open_wallet_action);
file->addAction(m_restore_wallet_action);
file->addAction(m_close_wallet_action);
file->addAction(m_close_all_wallets_action);
file->addSeparator();
Expand Down Expand Up @@ -657,6 +677,7 @@ void BitcoinGUI::setWalletController(WalletController* wallet_controller)
m_create_wallet_action->setEnabled(true);
m_open_wallet_action->setEnabled(true);
m_open_wallet_action->setMenu(m_open_wallet_menu);
m_restore_wallet_action->setEnabled(true);

GUIUtil::ExceptionSafeConnect(wallet_controller, &WalletController::walletAdded, this, &BitcoinGUI::addWallet);
connect(wallet_controller, &WalletController::walletRemoved, this, &BitcoinGUI::removeWallet);
Expand Down
1 change: 1 addition & 0 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class BitcoinGUI : public QMainWindow
QAction* showHelpMessageAction = nullptr;
QAction* m_create_wallet_action{nullptr};
QAction* m_open_wallet_action{nullptr};
QAction* m_restore_wallet_action{nullptr};
QMenu* m_open_wallet_menu{nullptr};
QAction* m_close_wallet_action{nullptr};
QAction* m_close_all_wallets_action{nullptr};
Expand Down
37 changes: 37 additions & 0 deletions src/qt/walletcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,40 @@ void LoadWalletsActivity::load()
QTimer::singleShot(0, this, [this] { Q_EMIT finished(); });
});
}

RestoreWalletActivity::RestoreWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
: WalletControllerActivity(wallet_controller, parent_widget)
{
}

void RestoreWalletActivity::restore(const std::string& backup_file, const std::string& wallet_name)
{
QString name = QString::fromStdString(wallet_name);

showProgressDialog(
tr("Restore Wallet"),
tr("Restoring Wallet <b>%1</b>…").arg(name.toHtmlEscaped())
);

QTimer::singleShot(0, worker(), [this, backup_file, wallet_name] {
std::unique_ptr<interfaces::Wallet> wallet = node().walletClient().restoreWallet(backup_file, wallet_name, m_error_message, m_warning_message);

if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));

QTimer::singleShot(0, this, &RestoreWalletActivity::finish);
});
}

void RestoreWalletActivity::finish()
{
if (!m_error_message.empty()) {
QMessageBox::critical(m_parent_widget, tr("Restore wallet failed"), QString::fromStdString(m_error_message.translated));
} else if (!m_warning_message.empty()) {
QMessageBox::warning(m_parent_widget, tr("Restore wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated));
}

if (m_wallet_model) Q_EMIT restored(m_wallet_model);

Q_EMIT finished();
}

16 changes: 16 additions & 0 deletions src/qt/walletcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,20 @@ class LoadWalletsActivity : public WalletControllerActivity
void load();
};

class RestoreWalletActivity : public WalletControllerActivity
{
Q_OBJECT

public:
RestoreWalletActivity(WalletController* wallet_controller, QWidget* parent_widget);

void restore(const std::string& backup_file, const std::string& wallet_name);

Q_SIGNALS:
void restored(WalletModel* wallet_model);

private:
void finish();
};

#endif // BITCOIN_QT_WALLETCONTROLLER_H
8 changes: 8 additions & 0 deletions src/wallet/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,14 @@ class WalletClientImpl : public WalletClient
options.require_existing = true;
return MakeWallet(m_context, LoadWallet(m_context, name, true /* load_on_start */, options, status, error, warnings));
}
std::unique_ptr<Wallet> restoreWallet(const std::string& backup_file, const std::string& wallet_name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{
DatabaseOptions options;
DatabaseStatus status;
options.require_existing = true;

return MakeWallet(m_context, RestoreWallet(m_context, backup_file, wallet_name, /* load_on_start= */ true, options, status, error, warnings));
}
std::string getWalletDir() override
{
return fs::PathToString(GetWalletDir());
Expand Down
16 changes: 16 additions & 0 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,22 @@ std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string&
return wallet;
}

std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const std::string& backup_file, const std::string& wallet_name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name));

if (fs::exists(wallet_path) || !TryCreateDirectories(wallet_path)) {
error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(wallet_path)));
status = DatabaseStatus::FAILED_ALREADY_EXISTS;
return nullptr;
}

auto wallet_file = wallet_path / "wallet.dat";
fs::copy_file(backup_file, wallet_file, fs::copy_option::fail_if_exists);

return LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
}

/** @defgroup mapWallet
*
* @{
Expand Down
1 change: 1 addition & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ std::vector<std::shared_ptr<CWallet>> GetWallets(WalletContext& context);
std::shared_ptr<CWallet> GetWallet(WalletContext& context, const std::string& name);
std::shared_ptr<CWallet> LoadWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::shared_ptr<CWallet> CreateWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const std::string& backup_file, const std::string& wallet_name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::unique_ptr<interfaces::Handler> HandleLoadWallet(WalletContext& context, LoadWalletFn load_wallet);
std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error);

Expand Down

0 comments on commit f202ddb

Please sign in to comment.