Bitcoin Core 31.99.0
P2P Digital Currency
walletcontroller.cpp
Go to the documentation of this file.
1// Copyright (c) 2019-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6
8#include <qt/clientmodel.h>
10#include <qt/guiconstants.h>
11#include <qt/guiutil.h>
12#include <qt/walletmodel.h>
13
14#include <external_signer.h>
15#include <interfaces/handler.h>
16#include <interfaces/node.h>
17#include <util/string.h>
18#include <util/threadnames.h>
19#include <util/translation.h>
20#include <wallet/wallet.h>
21
22#include <algorithm>
23#include <chrono>
24
25#include <QApplication>
26#include <QCheckBox>
27#include <QMessageBox>
28#include <QMetaObject>
29#include <QMutexLocker>
30#include <QThread>
31#include <QTimer>
32#include <QWindow>
33
34using util::Join;
39
40WalletController::WalletController(ClientModel& client_model, const PlatformStyle* platform_style, QObject* parent)
41 : QObject(parent)
42 , m_activity_thread(new QThread(this))
43 , m_activity_worker(new QObject)
44 , m_client_model(client_model)
45 , m_node(client_model.node())
46 , m_platform_style(platform_style)
47 , m_options_model(client_model.getOptionsModel())
48{
49 m_handler_load_wallet = m_node.walletLoader().handleLoadWallet([this](std::unique_ptr<interfaces::Wallet> wallet) {
50 getOrCreateWallet(std::move(wallet));
51 });
52
54 m_activity_thread->start();
55 QTimer::singleShot(0, m_activity_worker, []() {
56 util::ThreadRename("qt-walletctrl");
57 });
58}
59
60// Not using the default destructor because not all member types definitions are
61// available in the header, just forward declared.
63{
64 m_activity_thread->quit();
65 m_activity_thread->wait();
66 delete m_activity_worker;
67}
68
69std::map<std::string, std::pair<bool, std::string>> WalletController::listWalletDir() const
70{
71 QMutexLocker locker(&m_mutex);
72 std::map<std::string, std::pair<bool, std::string>> wallets;
73 for (const auto& [name, format] : m_node.walletLoader().listWalletDir()) {
74 wallets[name] = std::make_pair(false, format);
75 }
76 for (WalletModel* wallet_model : m_wallets) {
77 auto it = wallets.find(wallet_model->wallet().getWalletName());
78 if (it != wallets.end()) it->second.first = true;
79 }
80 return wallets;
81}
82
84{
85 // Once the wallet is successfully removed from the node, the model will emit the 'WalletModel::unload' signal.
86 // This signal is already connected and will complete the removal of the view from the GUI.
87 // Look at 'WalletController::getOrCreateWallet' for the signal connection.
88 wallet_model->wallet().remove();
89}
90
91void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
92{
93 QMessageBox box(parent);
94 box.setWindowTitle(tr("Close wallet"));
95 box.setText(tr("Are you sure you wish to close the wallet <i>%1</i>?").arg(GUIUtil::HtmlEscape(wallet_model->getDisplayName())));
96 box.setInformativeText(tr("Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled."));
97 box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel);
98 box.setDefaultButton(QMessageBox::Yes);
99 if (box.exec() != QMessageBox::Yes) return;
100
101 removeWallet(wallet_model);
102}
103
105{
106 QMessageBox::StandardButton button = QMessageBox::question(parent, tr("Close all wallets"),
107 tr("Are you sure you wish to close all wallets?"),
108 QMessageBox::Yes|QMessageBox::Cancel,
109 QMessageBox::Yes);
110 if (button != QMessageBox::Yes) return;
111
112 QMutexLocker locker(&m_mutex);
113 for (WalletModel* wallet_model : m_wallets) {
114 removeWallet(wallet_model);
115 }
116}
117
118WalletModel* WalletController::getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet)
119{
120 QMutexLocker locker(&m_mutex);
121
122 // Return model instance if exists.
123 if (!m_wallets.empty()) {
124 std::string name = wallet->getWalletName();
125 for (WalletModel* wallet_model : m_wallets) {
126 if (wallet_model->wallet().getWalletName() == name) {
127 return wallet_model;
128 }
129 }
130 }
131
132 // Instantiate model and register it.
133 WalletModel* wallet_model = new WalletModel(std::move(wallet), m_client_model, m_platform_style,
134 nullptr /* required for the following moveToThread() call */);
135
136 // Move WalletModel object to the thread that created the WalletController
137 // object (GUI main thread), instead of the current thread, which could be
138 // an outside wallet thread or RPC thread sending a LoadWallet notification.
139 // This ensures queued signals sent to the WalletModel object will be
140 // handled on the GUI event loop.
141 wallet_model->moveToThread(thread());
142 // setParent(parent) must be called in the thread which created the parent object. More details in #18948.
143 QMetaObject::invokeMethod(this, [wallet_model, this] {
144 wallet_model->setParent(this);
146
147 m_wallets.push_back(wallet_model);
148
149 // WalletModel::startPollBalance needs to be called in a thread managed by
150 // Qt because of startTimer. Considering the current thread can be a RPC
151 // thread, better delegate the calling to Qt with Qt::AutoConnection.
152 const bool called = QMetaObject::invokeMethod(wallet_model, "startPollBalance");
153 assert(called);
154
155 connect(wallet_model, &WalletModel::unload, this, [this, wallet_model] {
156 // Defer removeAndDeleteWallet when no modal widget is actively waiting for an action.
157 // TODO: remove this workaround by removing usage of QDialog::exec.
158 QWidget* active_dialog = QApplication::activeModalWidget();
159 if (active_dialog && dynamic_cast<QProgressDialog*>(active_dialog) == nullptr) {
160 connect(qApp, &QApplication::focusWindowChanged, wallet_model, [this, wallet_model]() {
161 if (!QApplication::activeModalWidget()) {
162 removeAndDeleteWallet(wallet_model);
163 }
164 }, Qt::QueuedConnection);
165 } else {
166 removeAndDeleteWallet(wallet_model);
167 }
168 }, Qt::QueuedConnection);
169
170 // Re-emit coinsSent signal from wallet model.
171 connect(wallet_model, &WalletModel::coinsSent, this, &WalletController::coinsSent);
172
173 Q_EMIT walletAdded(wallet_model);
174
175 return wallet_model;
176}
177
179{
180 // Unregister wallet model.
181 {
182 QMutexLocker locker(&m_mutex);
183 m_wallets.erase(std::remove(m_wallets.begin(), m_wallets.end(), wallet_model));
184 }
185 Q_EMIT walletRemoved(wallet_model);
186 // Currently this can trigger the unload since the model can hold the last
187 // CWallet shared pointer.
188 delete wallet_model;
189}
190
192 : QObject(wallet_controller)
193 , m_wallet_controller(wallet_controller)
194 , m_parent_widget(parent_widget)
195{
196 connect(this, &WalletControllerActivity::finished, this, &QObject::deleteLater);
197}
198
199void WalletControllerActivity::showProgressDialog(const QString& title_text, const QString& label_text, bool show_minimized)
200{
201 auto progress_dialog = new QProgressDialog(m_parent_widget);
202 progress_dialog->setAttribute(Qt::WA_DeleteOnClose);
203 connect(this, &WalletControllerActivity::finished, progress_dialog, &QWidget::close);
204
205 progress_dialog->setWindowTitle(title_text);
206 progress_dialog->setLabelText(label_text);
207 progress_dialog->setRange(0, 0);
208 progress_dialog->setCancelButton(nullptr);
209 progress_dialog->setWindowModality(Qt::ApplicationModal);
210 GUIUtil::PolishProgressDialog(progress_dialog);
211 // The setValue call forces QProgressDialog to start the internal duration estimation.
212 // See details in https://bugreports.qt.io/browse/QTBUG-47042.
213 progress_dialog->setValue(0);
214 // When requested, launch dialog minimized
215 if (show_minimized) progress_dialog->showMinimized();
216}
217
218CreateWalletActivity::CreateWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
219 : WalletControllerActivity(wallet_controller, parent_widget)
220{
222}
223
225{
227 delete m_passphrase_dialog;
228}
229
231{
233 m_passphrase_dialog->setWindowModality(Qt::ApplicationModal);
234 m_passphrase_dialog->show();
235
236 connect(m_passphrase_dialog, &QObject::destroyed, [this] {
237 m_passphrase_dialog = nullptr;
238 });
239 connect(m_passphrase_dialog, &QDialog::accepted, [this] {
240 createWallet();
241 });
242 connect(m_passphrase_dialog, &QDialog::rejected, [this] {
243 Q_EMIT finished();
244 });
245}
246
248{
250 //: Title of window indicating the progress of creation of a new wallet.
251 tr("Create Wallet"),
252 /*: Descriptive text of the create wallet progress window which indicates
253 to the user which wallet is currently being created. */
254 tr("Creating Wallet <b>%1</b>…").arg(m_create_wallet_dialog->walletName().toHtmlEscaped()));
255
256 std::string name = m_create_wallet_dialog->walletName().toStdString();
257 uint64_t flags = 0;
258 // Enable descriptors by default.
262 }
265 }
268 }
269
270 QTimer::singleShot(500ms, worker(), [this, name, flags] {
272
273 if (wallet) {
275 } else {
277 }
278
279 QTimer::singleShot(500ms, this, &CreateWalletActivity::finish);
280 });
281}
282
284{
285 if (!m_error_message.empty()) {
286 QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message.translated));
287 } else if (!m_warning_message.empty()) {
288 QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated));
289 }
290
292
293 Q_EMIT finished();
294}
295
297{
299
300 std::vector<std::unique_ptr<interfaces::ExternalSigner>> signers;
301 try {
302 signers = node().listExternalSigners();
303 } catch (const std::runtime_error& e) {
304 QMessageBox::critical(nullptr, tr("Can't list signers"), e.what());
305 }
306 if (signers.size() > 1) {
307 QMessageBox::critical(nullptr, tr("Too many external signers found"), QString::fromStdString("More than one external signer found. Please connect only one at a time."));
308 signers.clear();
309 }
311
312 m_create_wallet_dialog->setWindowModality(Qt::ApplicationModal);
314
315 connect(m_create_wallet_dialog, &QObject::destroyed, [this] {
316 m_create_wallet_dialog = nullptr;
317 });
318 connect(m_create_wallet_dialog, &QDialog::rejected, [this] {
319 Q_EMIT finished();
320 });
321 connect(m_create_wallet_dialog, &QDialog::accepted, [this] {
323 askPassphrase();
324 } else {
325 createWallet();
326 }
327 });
328}
329
330OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
331 : WalletControllerActivity(wallet_controller, parent_widget)
332{
333}
334
336{
337 if (!m_error_message.empty()) {
338 QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message.translated));
339 } else if (!m_warning_message.empty()) {
340 QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated));
341 }
342
344
345 Q_EMIT finished();
346}
347
348void OpenWalletActivity::open(const std::string& path)
349{
350 QString name = GUIUtil::WalletDisplayName(path);
351
353 //: Title of window indicating the progress of opening of a wallet.
354 tr("Open Wallet"),
355 /*: Descriptive text of the open wallet progress window which indicates
356 to the user which wallet is currently being opened. */
357 tr("Opening Wallet <b>%1</b>…").arg(name.toHtmlEscaped()));
358
359 QTimer::singleShot(0, worker(), [this, path] {
361
362 if (wallet) {
364 } else {
366 }
367
368 QTimer::singleShot(0, this, &OpenWalletActivity::finish);
369 });
370}
371
372LoadWalletsActivity::LoadWalletsActivity(WalletController* wallet_controller, QWidget* parent_widget)
373 : WalletControllerActivity(wallet_controller, parent_widget)
374{
375}
376
377void LoadWalletsActivity::load(bool show_loading_minimized)
378{
380 //: Title of progress window which is displayed when wallets are being loaded.
381 tr("Load Wallets"),
382 /*: Descriptive text of the load wallets progress window which indicates to
383 the user that wallets are currently being loaded.*/
384 tr("Loading wallets…"),
385 /*show_minimized=*/show_loading_minimized);
386
387 QTimer::singleShot(0, worker(), [this] {
388 for (auto& wallet : node().walletLoader().getWallets()) {
390 }
391
392 QTimer::singleShot(0, this, [this] { Q_EMIT finished(); });
393 });
394}
395
396RestoreWalletActivity::RestoreWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
397 : WalletControllerActivity(wallet_controller, parent_widget)
398{
399}
400
401void RestoreWalletActivity::restore(const fs::path& backup_file, const std::string& wallet_name)
402{
403 QString name = QString::fromStdString(wallet_name);
404
406 //: Title of progress window which is displayed when wallets are being restored.
407 tr("Restore Wallet"),
408 /*: Descriptive text of the restore wallets progress window which indicates to
409 the user that wallets are currently being restored.*/
410 tr("Restoring Wallet <b>%1</b>…").arg(name.toHtmlEscaped()));
411
412 QTimer::singleShot(0, worker(), [this, backup_file, wallet_name] {
413 auto wallet{node().walletLoader().restoreWallet(backup_file, wallet_name, m_warning_message, /*load_after_restore=*/true)};
414
415 if (wallet) {
417 } else {
419 }
420
421 QTimer::singleShot(0, this, &RestoreWalletActivity::finish);
422 });
423}
424
426{
427 if (!m_error_message.empty()) {
428 //: Title of message box which is displayed when the wallet could not be restored.
429 QMessageBox::critical(m_parent_widget, tr("Restore wallet failed"), QString::fromStdString(m_error_message.translated));
430 } else if (!m_warning_message.empty()) {
431 //: Title of message box which is displayed when the wallet is restored with some warning.
432 QMessageBox::warning(m_parent_widget, tr("Restore wallet warning"), QString::fromStdString(Join(m_warning_message, Untranslated("\n")).translated));
433 } else {
434 //: Title of message box which is displayed when the wallet is successfully restored.
435 QMessageBox::information(m_parent_widget, tr("Restore wallet message"), QString::fromStdString(Untranslated("Wallet restored successfully \n").translated));
436 }
437
439
440 Q_EMIT finished();
441}
442
443void MigrateWalletActivity::do_migrate(const std::string& name, bool load_wallet)
444{
445 SecureString passphrase;
446 if (node().walletLoader().isEncrypted(name)) {
447 // Get the passphrase for the wallet
449 if (dlg.exec() == QDialog::Rejected) return;
450 }
451
452 showProgressDialog(tr("Migrate Wallet"), tr("Migrating Wallet <b>%1</b>…").arg(GUIUtil::HtmlEscape(name)));
453
454 QTimer::singleShot(0, worker(), [this, name, passphrase, load_wallet] {
455 auto res{node().walletLoader().migrateWallet(name, passphrase, load_wallet)};
456
457 if (res) {
458 m_success_message = tr("The wallet '%1' was migrated successfully.").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(name)));
459 if (res->watchonly_wallet_name) {
460 m_success_message += QChar(' ') + tr("Watchonly scripts have been migrated to a new wallet named '%1'.").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(res->watchonly_wallet_name.value())));
461 }
462 if (res->solvables_wallet_name) {
463 m_success_message += QChar(' ') + tr("Solvable but not watched scripts have been migrated to a new wallet named '%1'.").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(res->solvables_wallet_name.value())));
464 }
465 if (load_wallet) {
466 assert(res->wallet);
467 m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(res->wallet));
468 } else {
469 m_success_message += QChar(' ') + tr("The wallet was not loaded after migration. You can open it from the \"File > Open wallet\" menu.");
470 }
471 } else {
473 }
474
475 QTimer::singleShot(0, this, &MigrateWalletActivity::finish);
476 });
477}
478
479void MigrateWalletActivity::migrate(const std::string& name)
480{
481 // Warn the user about migration
482 QMessageBox box(m_parent_widget);
483 box.setWindowTitle(tr("Migrate wallet"));
484 box.setText(tr("Are you sure you wish to migrate the wallet <i>%1</i>?").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(name))));
485 box.setInformativeText(tr("Migrating the wallet will convert this wallet to one or more descriptor wallets. A new wallet backup will need to be made.\n"
486 "If this wallet contains any watchonly scripts, a new wallet will be created which contains those watchonly scripts.\n"
487 "If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts.\n\n"
488 "The migration process will create a backup of the wallet before migrating. This backup file will be named "
489 "<wallet name>-<timestamp>.legacy.bak and can be found in the directory for this wallet. In the event of "
490 "an incorrect migration, the backup can be restored with the \"Restore Wallet\" functionality."));
491 auto* load_wallet_checkbox = new QCheckBox(tr("Load wallet after migration"), &box);
492 load_wallet_checkbox->setToolTip(tr("If the node is pruned and the wallet was created before the pruned height, the migration process may fail trying to load the migrated wallet."));
493 load_wallet_checkbox->setChecked(true);
494 box.setCheckBox(load_wallet_checkbox);
495 box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel);
496 box.setDefaultButton(QMessageBox::Yes);
497 if (box.exec() != QMessageBox::Yes) return;
498
499 do_migrate(name, load_wallet_checkbox->isChecked());
500}
501
502void MigrateWalletActivity::restore_and_migrate(const fs::path& path, const std::string& wallet_name)
503{
504 // Warn the user about migration
505 QMessageBox box(m_parent_widget);
506 box.setWindowTitle(tr("Restore and Migrate wallet"));
507 box.setText(tr("Are you sure you wish to restore the wallet file <i>%1</i> to <i>%2</i> and migrate it?").arg(GUIUtil::HtmlEscape(fs::PathToString(path)), GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(wallet_name))));
508 box.setInformativeText(tr("Restoring the wallet will copy the backup file to the wallets directory and place it in the standard "
509 "wallet directory layout. The original file will not be modified.\n\n"
510 "Migrating the wallet will convert the restored wallet to one or more descriptor wallets. A new wallet backup will need to be made.\n"
511 "If this wallet contains any watchonly scripts, a new wallet will be created which contains those watchonly scripts.\n"
512 "If this wallet contains any solvable but not watched scripts, a different and new wallet will be created which contains those scripts.\n\n"
513 "The migration process will create a backup of the wallet before migrating. This backup file will be named "
514 "<wallet name>-<timestamp>.legacy.bak and can be found in the directory for this wallet. In the event of "
515 "an incorrect migration, the backup can be restored with the \"Restore Wallet\" functionality."));
516 box.setStandardButtons(QMessageBox::Yes|QMessageBox::Cancel);
517 box.setDefaultButton(QMessageBox::Yes);
518 if (box.exec() != QMessageBox::Yes) return;
519
521 //: Title of progress window which is displayed when wallets are being restored.
522 tr("Restore Wallet"),
523 /*: Descriptive text of the restore wallets progress window which indicates to
524 the user that wallets are currently being restored.*/
525 tr("Restoring Wallet <b>%1</b>…").arg(GUIUtil::HtmlEscape(GUIUtil::WalletDisplayName(wallet_name))));
526
527 QTimer::singleShot(0, worker(), [this, path, wallet_name] {
528 auto res{node().walletLoader().restoreWallet(path, wallet_name, m_warning_message, /*load_after_restore=*/false)};
529
530 if (!res) {
532 QTimer::singleShot(0, this, &MigrateWalletActivity::finish);
533 return;
534 }
535 QTimer::singleShot(0, this, [this, wallet_name] {
536 do_migrate(wallet_name, /*load_wallet=*/true);
537 });
538 });
539}
540
542{
543 if (!m_error_message.empty()) {
544 QMessageBox::critical(m_parent_widget, tr("Migration failed"), QString::fromStdString(m_error_message.translated));
545 } else {
546 QMessageBox::information(m_parent_widget, tr("Migration Successful"), m_success_message);
547 }
548
550
551 Q_EMIT finished();
552}
node::NodeContext m_node
Definition: bitcoin-gui.cpp:47
int flags
Definition: bitcoin-tx.cpp:530
Multifunctional dialog to ask for passphrases.
@ Encrypt
Ask passphrase twice and encrypt.
@ UnlockMigration
Ask passphrase for unlocking during migration.
Model for Bitcoin network client.
Definition: clientmodel.h:57
AskPassphraseDialog * m_passphrase_dialog
CreateWalletDialog * m_create_wallet_dialog
CreateWalletActivity(WalletController *wallet_controller, QWidget *parent_widget)
void created(WalletModel *wallet_model)
Dialog for creating wallets.
bool isMakeBlankWalletChecked() const
QString walletName() const
bool isDisablePrivateKeysChecked() const
bool isEncryptWalletChecked() const
void setSigners(const std::vector< std::unique_ptr< interfaces::ExternalSigner > > &signers)
bool isExternalSignerChecked() const
void load(bool show_loading_minimized)
LoadWalletsActivity(WalletController *wallet_controller, QWidget *parent_widget)
void do_migrate(const std::string &name, bool load_wallet)
void restore_and_migrate(const fs::path &path, const std::string &wallet_name)
void migrated(WalletModel *wallet_model)
void migrate(const std::string &path)
void opened(WalletModel *wallet_model)
OpenWalletActivity(WalletController *wallet_controller, QWidget *parent_widget)
void open(const std::string &path)
void restore(const fs::path &backup_file, const std::string &wallet_name)
void restored(WalletModel *wallet_model)
RestoreWalletActivity(WalletController *wallet_controller, QWidget *parent_widget)
std::vector< bilingual_str > m_warning_message
WalletController *const m_wallet_controller
interfaces::Node & node() const
QObject * worker() const
void showProgressDialog(const QString &title_text, const QString &label_text, bool show_minimized=false)
WalletControllerActivity(WalletController *wallet_controller, QWidget *parent_widget)
QWidget *const m_parent_widget
Controller between interfaces::Node, WalletModel instances and the GUI.
WalletController(ClientModel &client_model, const PlatformStyle *platform_style, QObject *parent)
WalletModel * getOrCreateWallet(std::unique_ptr< interfaces::Wallet > wallet)
ClientModel & m_client_model
void removeAndDeleteWallet(WalletModel *wallet_model)
void walletAdded(WalletModel *wallet_model)
void closeAllWallets(QWidget *parent=nullptr)
std::unique_ptr< interfaces::Handler > m_handler_load_wallet
QThread *const m_activity_thread
void coinsSent(WalletModel *wallet_model, SendCoinsRecipient recipient, QByteArray transaction)
QObject *const m_activity_worker
void walletRemoved(WalletModel *wallet_model)
const PlatformStyle *const m_platform_style
interfaces::Node & m_node
void closeWallet(WalletModel *wallet_model, QWidget *parent=nullptr)
std::map< std::string, std::pair< bool, std::string > > listWalletDir() const
Returns all wallet names in the wallet dir mapped to whether the wallet is loaded.
void removeWallet(WalletModel *wallet_model)
Starts the wallet closure procedure.
std::vector< WalletModel * > m_wallets
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:49
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
void coinsSent(WalletModel *wallet, SendCoinsRecipient recipient, QByteArray transaction)
QString getDisplayName() const
void unload()
virtual WalletLoader & walletLoader()=0
Get wallet loader.
virtual std::vector< std::unique_ptr< ExternalSigner > > listExternalSigners()=0
Return list of external signers (attached devices which can sign transactions).
virtual void remove()=0
virtual util::Result< WalletMigrationResult > migrateWallet(const std::string &name, const SecureString &passphrase, bool load_wallet)=0
Migrate a wallet.
virtual util::Result< std::unique_ptr< Wallet > > restoreWallet(const fs::path &backup_file, const std::string &wallet_name, std::vector< bilingual_str > &warnings, bool load_after_restore)=0
Restore backup wallet.
virtual util::Result< std::unique_ptr< Wallet > > createWallet(const std::string &name, const SecureString &passphrase, uint64_t wallet_creation_flags, std::vector< bilingual_str > &warnings)=0
Create new wallet.
virtual std::vector< std::pair< std::string, std::string > > listWalletDir()=0
Return available wallets in wallet directory.
virtual util::Result< std::unique_ptr< Wallet > > loadWallet(const std::string &name, std::vector< bilingual_str > &warnings)=0
Load existing wallet.
virtual std::unique_ptr< Handler > handleLoadWallet(LoadWalletFn fn)=0
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:162
static const int MAX_PASSPHRASE_SIZE
Definition: guiconstants.h:20
std::thread thread
Thread variable should be after other struct members so the thread does not start until the other mem...
Qt::ConnectionType blockingGUIThreadConnection()
Get connection type to call object slot in GUI thread with invokeMethod.
Definition: guiutil.cpp:380
QString WalletDisplayName(const QString &name)
Definition: guiutil.cpp:990
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:249
void PolishProgressDialog(QProgressDialog *dialog)
Definition: guiutil.cpp:897
Definition: messages.h:21
void format(std::ostream &out, FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1079
void ThreadRename(const std::string &)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
Definition: threadnames.cpp:55
bilingual_str ErrorString(const Result< T > &result)
Definition: result.h:93
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
Definition: string.h:208
@ WALLET_FLAG_EXTERNAL_SIGNER
Indicates that the wallet needs an external signer.
Definition: walletutil.h:56
@ WALLET_FLAG_DESCRIPTORS
Indicate that this wallet supports DescriptorScriptPubKeyMan.
Definition: walletutil.h:53
@ WALLET_FLAG_DISABLE_PRIVATE_KEYS
Definition: walletutil.h:30
@ WALLET_FLAG_BLANK_WALLET
Flag set when a wallet contains no HD seed and no private keys, scripts, addresses,...
Definition: walletutil.h:50
const char * name
Definition: rest.cpp:50
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:53
bool empty() const
Definition: translation.h:35
std::string translated
Definition: translation.h:26
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition: translation.h:82
assert(!tx.IsCoinBase())