This PR adds a menu entry Open Wallet
to support loading existing wallets in the UI.
Fixes #7675.
If the wallet folder name contains Chinese, it will create a new folder that has same wallet file with a weird name on Windows, maybe the encoding issue (Not related)
Also, the seperator is incorrect on Windows
-wallet=d:\...
?
-wallet=d:\錢包
does works, but the name displayed in Qt is incorrect
And it crash when I quit Qt
Checked that this isn’t an issue on Linux.
Maybe windows or boost is using big5 encoding. which ends in a right square bracket ]
0>>> '錢包'.encode('big5')
1b'\xbf\xfa\xa5]'
2>>> '錢包'.encode('big5').decode('utf8', 'replace')
3'���]'
706@@ -701,6 +707,20 @@ void BitcoinGUI::openClicked()
707 }
708 }
709
710+void BitcoinGUI::openWalletClicked()
711+{
712+ QString fileName = QFileDialog::getExistingDirectory(this, tr("Open Wallet"),
QDir::toNativeSeparators
to convert /
to \
on Windows
233+ }
234+ std::pair<std::unique_ptr<Wallet>, std::string> loadWallet(const std::string& wallet_file) override
235+ {
236+#ifdef ENABLE_WALLET
237+ try {
238+ std::string dummy_warning;
loadwallet()
in rpcwallet.cpp. Does it make sense to factor it out to avoid repetition?
WalletManager
249+ AddWallet(wallet);
250+
251+ wallet->postInitProcess();
252+ return { MakeWallet(*wallet), std::string() };
253+ } catch (...) {
254+ return { std::unique_ptr<Wallet>(), "ops" };
ops
712+ QString fileName = QFileDialog::getExistingDirectory(this, tr("Open Wallet"),
713+ QString(),
714+ QFileDialog::ShowDirsOnly
715+ | QFileDialog::DontResolveSymlinks);
716+ if (fileName.isEmpty()) return;
717+ const auto& result = m_node.loadWallet(fileName.toStdString());
auto
here makes it difficult to understand the result.second
below.
715+ QFileDialog::ShowDirsOnly
716+ | QFileDialog::DontResolveSymlinks);
717+ if (fileName.isEmpty()) return;
718+
719+ std::vector<std::string> errors;
720+ m_node.loadWallet(QDir::toNativeSeparators(fileName).toStdString(), errors);
713@@ -707,6 +714,24 @@ void BitcoinGUI::openClicked()
714 }
715 }
716
717+void BitcoinGUI::openWalletClicked()
718+{
719+ QString fileName = QFileDialog::getExistingDirectory(this, tr("Open Wallet"),
720+ QString(),
.bitcoin
).
713@@ -707,6 +714,24 @@ void BitcoinGUI::openClicked()
714 }
715 }
716
717+void BitcoinGUI::openWalletClicked()
718+{
719+ QString fileName = QFileDialog::getExistingDirectory(this, tr("Open Wallet"),
720+ QString(),
721+ QFileDialog::ShowDirsOnly
.dat
files.
323@@ -322,6 +324,15 @@ void BitcoinGUI::createActions()
324 openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
325 openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
326
327+ m_new_wallet_action = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("New &Wallet..."), this);
&
sets the keyboard shortcut, so these should be unique (or absent).
On macOS when opening a wallet or creating a new wallet it suggests the directory from which opened QT by default. This also leads to strangeness in the dropdown list:
The default should be the datadir, if that can be passed into the dialog.
For creating new wallet, I think a better approach is to ask for a wallet name, and not offer the user the option to put it in a different directory for the UI.
For opening an existing wallet I have a light preference for just scanning the default directory for wallets and showing a list of wallets to choose from. This also prevents confusion around wallets that are files vs. wallets that are directories. Offering multiple wallets and offering the ability to put wallets anywhere in the filesystem are two different features.
Code looks good to me, but I’m not qualified to tell if the memory / pointer management stuff is correct.
macOS threw a warning:
0objc[17648]: Class FIFinderSyncExtensionHost is implemented in both /System/Library/PrivateFrameworks/FinderKit.framework/Versions/A/FinderKit (0x7fff86ae1c90) and /System/Library/PrivateFrameworks/FileProvider.framework/OverrideBundles/FinderSyncCollaborationFileProviderOverride.bundle/Contents/MacOS/FinderSyncCollaborationFileProviderOverride (0x113143cd8). One of the two will be used. Which one is undefined.
Or walletdir?
If present, probably yes. Afaik it’s only created if there was no datadir at launch time, so at least in normal circumstances if /wallets exists, it should be non-confusing to use that as a default.
120+
121+ wallet->postInitProcess();
122+ return wallet;
123+}
124+
125+std::shared_ptr<CWallet> LoadWallet(const std::string& wallet_file, std::string& error, std::string& warning)
LoadWallet
and CreateWallet
357@@ -347,6 +358,9 @@ void BitcoinGUI::createActions()
358 connect(usedSendingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedSendingAddresses()));
359 connect(usedReceivingAddressesAction, SIGNAL(triggered()), walletFrame, SLOT(usedReceivingAddresses()));
360 connect(openAction, SIGNAL(triggered()), this, SLOT(openClicked()));
361+ connect(m_new_wallet_action, SIGNAL(triggered()), this, SLOT(newWallet()));
362+ connect(m_open_wallet_action, SIGNAL(triggered()), this, SLOT(openWallet()));
363+ connect(m_close_wallet_action, SIGNAL(triggered()), this, SLOT(closeWallet()));
Fails wallet_disableprivatekeys.py
. The wallet_creation_flags
are not being passed through to CreateWalletFromFile()
, and so this regresses being able to create a watch-only wallet.
With #9662 merged, do we want the same feature in the UI?
Later. Let’s just try to get the basic functionality into the GUI first!
703@@ -681,6 +704,54 @@ void BitcoinGUI::openClicked()
704 }
705 }
706
707+void BitcoinGUI::newWallet()
708+{
709+ QString file_name = QFileDialog::getSaveFileName(this, tr("New Wallet"));
719+ }
720+}
721+
722+void BitcoinGUI::openWallet()
723+{
724+ QString file_name = QFileDialog::getExistingDirectory(this, tr("Open Wallet"), QString(), QFileDialog::DontResolveSymlinks);
Why is this getExistingDirectory()
? A wallet can also be a file I think.
Also defaults to the directory that qt is running in.
78@@ -79,6 +79,74 @@ std::shared_ptr<CWallet> GetWallet(const std::string& name)
79 return nullptr;
80 }
81
82+static void GetWalletNameAndPath(const std::string& wallet_file, std::string& wallet_name, fs::path& wallet_path) {
yes, I have some changes to submit.
Great! Looking forward to seeing them :grin:
in this PR?
No, but worth creating an up for grabs issue for.
@promag - it’d be great to get this in for v0.18. It’s the last piece in https://github.com/bitcoin/bitcoin/projects/2.
Longer term, one of my motivations for #13059 was to have bitcoind/qt not create a default wallet at startup if one didn’t exist. This PR is the final blocker for that to happen.
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
master
:-)
@jnewbery wrote:
Longer term […] to have bitcoind/qt not create a default wallet at startup if one didn’t exist. This PR is the final blocker for that to happen.
That would be nice indeed. I find it quite annoying that you can’t start bitcoind without any wallet loaded. And I have too many wallet.dat
files floating around that I need to carefully check are actually safe to delete :-)
I’ll test again after rebase.
Re #11485 listing wallets, this could be added later. It’s nice to just show a list of wallet names that can be loaded, avoiding the file dialog.
For this PR it should be enough if the file dialog opens in walletdir
, or datadir
if that doesn’t exist. (the latter is impossible now, so maybe a source code comment warning would suffice).
Creating a new wallet should probably create a data and/or wallet dir, though it’s easier if #13761 is merged first.
@Sjors @jnewbery this is what it looks like:
For this PR it should be enough if the file dialog opens in walletdir, or datadir if that doesn’t exist.
If we handle wallets in the -walletdir
differently, then, for external wallets, I think we should point the file dialog to QDesktopServices::DocumentsLocation
or whatever.
Open External Wallet
to the bottom and just call it Other...
. Indeed it makes sense that doesn’t use walletdir.
Doesn’t build on linux/win gitian:
0 CXXLD test/test_bitcoin.exe
1 AR qt/libbitcoinqt.a
2 OBJCXXLD qt/bitcoin-qt.exe
3libbitcoin_server.a(libbitcoin_server_a-node.o): In function `getWalletDir':
4/home/ubuntu/build/bitcoin/distsrc-i686-w64-mingw32/src/interfaces/node.cpp:226: undefined reference to `GetWalletDir[abi:cxx11]()'
5collect2: error: ld returned 1 exit status
6Makefile:3904: recipe for target 'qt/bitcoin-qt.exe' failed
7make[2]: *** [qt/bitcoin-qt.exe] Error 1
8make[2]: Leaving directory '/home/ubuntu/build/bitcoin/distsrc-i686-w64-mingw32/src'
9Makefile:10188: recipe for target 'all-recursive' failed
10make[1]: *** [all-recursive] Error 1
11make[1]: Leaving directory '/home/ubuntu/build/bitcoin/distsrc-i686-w64-mingw32/src'
12Makefile:774: recipe for target 'all-recursive' failed
13make: *** [all-recursive] Error 1
14Failed run an application inside container
0 AR qt/libbitcoinqt.a
1 OBJCXXLD qt/bitcoin-qt
2libbitcoin_server.a(libbitcoin_server_a-node.o): In function `interfaces::(anonymous namespace)::NodeImpl::getWalletDir()':
3/home/ubuntu/build/bitcoin/distsrc-i686-pc-linux-gnu/src/interfaces/node.cpp:226: undefined reference to `GetWalletDir[abi:cxx11]()'
4collect2: error: ld returned 1 exit status
5Makefile:3904: recipe for target 'qt/bitcoin-qt' failed
6make[2]: *** [qt/bitcoin-qt] Error 1
7make[2]: Leaving directory '/home/ubuntu/build/bitcoin/distsrc-i686-pc-linux-gnu/src'
8Makefile:10188: recipe for target 'all-recursive' failed
9make[1]: *** [all-recursive] Error 1
10make[1]: Leaving directory '/home/ubuntu/build/bitcoin/distsrc-i686-pc-linux-gnu/src'
11Makefile:774: recipe for target 'all-recursive' failed
12make: *** [all-recursive] Error 1
13Failed run an application inside container
It’d be nice to get this in to 0.18, is that feasible? Needs a rebase
Overall this is looking good, concept ACK with some code review, I’ll review more once rebased/the comments above have been addressed and the WIP fixup commit is done
331@@ -330,6 +332,15 @@ void BitcoinGUI::createActions()
332 openAction = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("Open &URI..."), this);
333 openAction->setStatusTip(tr("Open a bitcoin: URI or payment request"));
334
335+ m_new_wallet_action = new QAction(platformStyle->TextColorIcon(":/icons/open"), tr("New &Wallet"), this);
A lot of this has been moved to smaller pull requests. E.g. there’s now a separate PR for just the open wallet feature #15153. I suppose “unloading” a wallet would be fairly trivial on top of that.
For my own work on #14912 I’d love to have a (proof of concept) “create wallet” PR to build on top of. Ideally it would a dialog, with a check box for the read-only feature (and later for the empty wallet feature in #14938).