Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/release-notes-gui-872.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
GUI
---

* A menu action has been added to allow creating a watchonly wallet file from
an existing descriptor wallet. This option mirrors the `exportwatchonlywallet`
RPC - the exported file can be imported to another node using the Restore
Wallet menu action.
3 changes: 3 additions & 0 deletions src/interfaces/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ class Wallet

//! Return pointer to internal wallet class, useful for testing.
virtual wallet::CWallet* wallet() { return nullptr; }

//! Export a watchonly wallet file. See CWallet::ExportWatchOnlyWallet
virtual util::Result<std::string> exportWatchOnlyWallet(const fs::path& destination) = 0;
};

//! Wallet chain client that in addition to having chain client methods for
Expand Down
19 changes: 19 additions & 0 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,10 @@ void BitcoinGUI::createActions()
m_mask_values_action->setStatusTip(tr("Mask the values in the Overview tab"));
m_mask_values_action->setCheckable(true);

m_export_watchonly_action = new QAction(tr("Export watch-only wallet"), this);
m_export_watchonly_action->setEnabled(false);
m_export_watchonly_action->setStatusTip(tr("Export a watch-only version of the current wallet that can be restored onto another node."));

connect(quitAction, &QAction::triggered, this, &BitcoinGUI::quitRequested);
connect(aboutAction, &QAction::triggered, this, &BitcoinGUI::aboutClicked);
connect(aboutQtAction, &QAction::triggered, qApp, QApplication::aboutQt);
Expand Down Expand Up @@ -524,6 +528,18 @@ void BitcoinGUI::createActions()
});
connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::setPrivacy);
connect(m_mask_values_action, &QAction::toggled, this, &BitcoinGUI::enableHistoryAction);
GUIUtil::ExceptionSafeConnect(m_export_watchonly_action, &QAction::triggered, [this](bool) {
QString destination = GUIUtil::getSaveFileName(this, tr("Save Watch-only Wallet Export"), QString(), QString(), nullptr);
if (destination.isEmpty()) return;
WalletModel* model = walletFrame->currentWalletModel();
if (!Assume(model)) return;
util::Result<std::string> export_res = model->wallet().exportWatchOnlyWallet(GUIUtil::QStringToPath(destination));
if (export_res) {
QMessageBox::information(nullptr, tr("Export Successful"), tr("The wallet has been exported to ") + QString::fromStdString(*export_res));
} else {
QMessageBox::critical(nullptr, tr("Export Error"), QString::fromStdString(util::ErrorString(export_res).translated));
}
});
}
#endif // ENABLE_WALLET

Expand All @@ -547,6 +563,7 @@ void BitcoinGUI::createMenuBar()
file->addSeparator();
file->addAction(backupWalletAction);
file->addAction(m_restore_wallet_action);
file->addAction(m_export_watchonly_action);
file->addSeparator();
file->addAction(openAction);
file->addAction(signMessageAction);
Expand Down Expand Up @@ -832,6 +849,7 @@ void BitcoinGUI::setCurrentWallet(WalletModel* wallet_model)
break;
}
}
m_export_watchonly_action->setEnabled(!wallet_model->wallet().privateKeysDisabled());
updateWindowTitle();
}

Expand Down Expand Up @@ -866,6 +884,7 @@ void BitcoinGUI::setWalletActionsEnabled(bool enabled)
openAction->setEnabled(enabled);
m_close_wallet_action->setEnabled(enabled);
m_close_all_wallets_action->setEnabled(enabled);
m_export_watchonly_action->setEnabled(enabled);
}

void BitcoinGUI::createTrayIcon()
Expand Down
1 change: 1 addition & 0 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ class BitcoinGUI : public QMainWindow
QAction* m_mask_values_action{nullptr};
QAction* m_migrate_wallet_action{nullptr};
QMenu* m_migrate_wallet_menu{nullptr};
QAction* m_export_watchonly_action{nullptr};
#ifdef ENABLE_WALLET
QLabel *m_wallet_selector_label = nullptr;
QComboBox* m_wallet_selector = nullptr;
Expand Down
6 changes: 5 additions & 1 deletion src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -970,7 +970,11 @@ void PrintSlotException(
{
std::string description = sender->metaObject()->className();
description += "->";
description += receiver->metaObject()->className();
if (receiver) {
description += receiver->metaObject()->className();
} else {
description += "anonymous function";
}
PrintExceptionContinue(exception, description);
}

Expand Down
32 changes: 32 additions & 0 deletions src/qt/guiutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,38 @@ namespace GUIUtil
},
type);
}
template <typename Sender, typename Signal, typename Slot>
auto ExceptionSafeConnect(
Sender sender, Signal signal, Slot method)
{
return QObject::connect(
sender, signal,
[sender, method](auto&&... args) {
bool ok{true};
try {
method(std::forward<decltype(args)>(args)...);
} catch (const NonFatalCheckError& e) {
PrintSlotException(&e, sender, nullptr);
ok = QMetaObject::invokeMethod(
qApp, "handleNonFatalException",
blockingGUIThreadConnection(),
Q_ARG(QString, QString::fromStdString(e.what())));
} catch (const std::exception& e) {
PrintSlotException(&e, sender, nullptr);
ok = QMetaObject::invokeMethod(
qApp, "handleRunawayException",
blockingGUIThreadConnection(),
Q_ARG(QString, QString::fromStdString(e.what())));
} catch (...) {
PrintSlotException(nullptr, sender, nullptr);
ok = QMetaObject::invokeMethod(
qApp, "handleRunawayException",
blockingGUIThreadConnection(),
Q_ARG(QString, "Unknown failure occurred."));
}
assert(ok);
});
}

/**
* Shows a QDialog instance asynchronously, and deletes it on close.
Expand Down
7 changes: 7 additions & 0 deletions src/wallet/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <util/ui_change_type.h>
#include <wallet/coincontrol.h>
#include <wallet/context.h>
#include <wallet/export.h>
#include <wallet/feebumper.h>
#include <wallet/fees.h>
#include <wallet/load.h>
Expand Down Expand Up @@ -522,6 +523,12 @@ class WalletImpl : public Wallet
}
CWallet* wallet() override { return m_wallet.get(); }

util::Result<std::string> exportWatchOnlyWallet(const fs::path& destination) override {
LOCK(m_wallet->cs_wallet);
Comment thread
achow101 marked this conversation as resolved.
m_wallet->TopUpKeyPool();
return ExportWatchOnlyWallet(*m_wallet, destination, m_context);
}

WalletContext& m_context;
std::shared_ptr<CWallet> m_wallet;
};
Expand Down
Loading