Add export all keys menu
This commit is contained in:
@@ -40,8 +40,12 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
QDesktopServices::openUrl(QUrl("https://github.com/adityapk00/zec-qt-wallet/releases"));
|
QDesktopServices::openUrl(QUrl("https://github.com/adityapk00/zec-qt-wallet/releases"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Import Private Key
|
||||||
QObject::connect(ui->actionImport_Private_Key, &QAction::triggered, this, &MainWindow::importPrivKey);
|
QObject::connect(ui->actionImport_Private_Key, &QAction::triggered, this, &MainWindow::importPrivKey);
|
||||||
|
|
||||||
|
// Export All Private Keys
|
||||||
|
QObject::connect(ui->actionExport_All_Private_Keys, &QAction::triggered, this, &MainWindow::exportAllKeys);
|
||||||
|
|
||||||
// Set up about action
|
// Set up about action
|
||||||
QObject::connect(ui->actionAbout, &QAction::triggered, [=] () {
|
QObject::connect(ui->actionAbout, &QAction::triggered, [=] () {
|
||||||
QDialog aboutDialog(this);
|
QDialog aboutDialog(this);
|
||||||
@@ -436,6 +440,7 @@ void MainWindow::importPrivKey() {
|
|||||||
Ui_PrivKey pui;
|
Ui_PrivKey pui;
|
||||||
pui.setupUi(&d);
|
pui.setupUi(&d);
|
||||||
|
|
||||||
|
pui.buttonBox->button(QDialogButtonBox::Save)->setVisible(false);
|
||||||
pui.helpLbl->setText(QString() %
|
pui.helpLbl->setText(QString() %
|
||||||
"Please paste your private keys (z-Addr or t-Addr) here, one per line.\n" %
|
"Please paste your private keys (z-Addr or t-Addr) here, one per line.\n" %
|
||||||
"The keys will be imported into your connected zcashd node");
|
"The keys will be imported into your connected zcashd node");
|
||||||
@@ -462,6 +467,54 @@ void MainWindow::importPrivKey() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::exportAllKeys() {
|
||||||
|
QDialog d(this);
|
||||||
|
Ui_PrivKey pui;
|
||||||
|
pui.setupUi(&d);
|
||||||
|
|
||||||
|
auto ps = this->geometry();
|
||||||
|
QMargins margin = QMargins() + 50;
|
||||||
|
d.setGeometry(ps.marginsRemoved(margin));
|
||||||
|
|
||||||
|
pui.privKeyTxt->setPlainText("Loading...");
|
||||||
|
pui.privKeyTxt->setReadOnly(true);
|
||||||
|
pui.privKeyTxt->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
|
||||||
|
pui.helpLbl->setText("These are all the private keys for all the addresses in your wallet");
|
||||||
|
|
||||||
|
// Disable the save button until it finishes loading
|
||||||
|
pui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
|
||||||
|
pui.buttonBox->button(QDialogButtonBox::Ok)->setVisible(false);
|
||||||
|
|
||||||
|
// Wire up save button
|
||||||
|
QObject::connect(pui.buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=] () {
|
||||||
|
QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
|
||||||
|
"zcash-all-privatekeys.txt");
|
||||||
|
QFile file(fileName);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) {
|
||||||
|
QMessageBox::information(this, tr("Unable to open file"), file.errorString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QTextStream out(&file);
|
||||||
|
out << pui.privKeyTxt->toPlainText();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call the API
|
||||||
|
rpc->getAllPrivKeys([=] (auto privKeys) {
|
||||||
|
QString allKeysTxt;
|
||||||
|
for (auto keypair : privKeys) {
|
||||||
|
allKeysTxt = allKeysTxt % keypair.second % " # addr=" % keypair.first % "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
pui.privKeyTxt->setPlainText(allKeysTxt);
|
||||||
|
pui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
d.exec();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::setupBalancesTab() {
|
void MainWindow::setupBalancesTab() {
|
||||||
ui->unconfirmedWarning->setVisible(false);
|
ui->unconfirmedWarning->setVisible(false);
|
||||||
|
|
||||||
@@ -493,6 +546,7 @@ void MainWindow::setupBalancesTab() {
|
|||||||
pui.privKeyTxt->setPlainText(privKey);
|
pui.privKeyTxt->setPlainText(privKey);
|
||||||
pui.privKeyTxt->setReadOnly(true);
|
pui.privKeyTxt->setReadOnly(true);
|
||||||
pui.privKeyTxt->selectAll();
|
pui.privKeyTxt->selectAll();
|
||||||
|
pui.buttonBox->button(QDialogButtonBox::Save)->setVisible(false);
|
||||||
pui.buttonBox->button(QDialogButtonBox::Ok)->setVisible(false);
|
pui.buttonBox->button(QDialogButtonBox::Ok)->setVisible(false);
|
||||||
|
|
||||||
d.exec();
|
d.exec();
|
||||||
@@ -542,6 +596,7 @@ void MainWindow::setupBalancesTab() {
|
|||||||
void MainWindow::setupTransactionsTab() {
|
void MainWindow::setupTransactionsTab() {
|
||||||
// Set up context menu on transactions tab
|
// Set up context menu on transactions tab
|
||||||
ui->transactionsTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->transactionsTable->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
QObject::connect(ui->transactionsTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
|
QObject::connect(ui->transactionsTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
|
||||||
QModelIndex index = ui->transactionsTable->indexAt(pos);
|
QModelIndex index = ui->transactionsTable->indexAt(pos);
|
||||||
if (index.row() < 0) return;
|
if (index.row() < 0) return;
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ private:
|
|||||||
|
|
||||||
void donate();
|
void donate();
|
||||||
void importPrivKey();
|
void importPrivKey();
|
||||||
|
void exportAllKeys();
|
||||||
void doImport(QList<QString>* keys);
|
void doImport(QList<QString>* keys);
|
||||||
|
|
||||||
void restoreSavedStates();
|
void restoreSavedStates();
|
||||||
|
|||||||
@@ -726,6 +726,7 @@
|
|||||||
<string>&File</string>
|
<string>&File</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionImport_Private_Key"/>
|
<addaction name="actionImport_Private_Key"/>
|
||||||
|
<addaction name="actionExport_All_Private_Keys"/>
|
||||||
<addaction name="actionTurnstile_Migration"/>
|
<addaction name="actionTurnstile_Migration"/>
|
||||||
<addaction name="actionSettings"/>
|
<addaction name="actionSettings"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@@ -781,6 +782,11 @@
|
|||||||
<string>&Import Private Key</string>
|
<string>&Import Private Key</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionExport_All_Private_Keys">
|
||||||
|
<property name="text">
|
||||||
|
<string>Export All Private Keys</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons">
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok|QDialogButtonBox::Save</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
82
src/rpc.cpp
82
src/rpc.cpp
@@ -202,6 +202,88 @@ void RPC::sendZTransaction(json params, const std::function<void(json)>& cb) {
|
|||||||
conn->doRPCWithDefaultErrorHandling(payload, cb);
|
conn->doRPCWithDefaultErrorHandling(payload, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to get all the private keys for both z and t addresses. It will make 2 batch calls,
|
||||||
|
* combine the result, and call the callback with a single list containing both the t-addr and z-addr
|
||||||
|
* private keys
|
||||||
|
*/
|
||||||
|
void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)> cb) {
|
||||||
|
|
||||||
|
// A special function that will call the callback when two lists have been added
|
||||||
|
auto holder = new QPair<int, QList<QPair<QString, QString>>>();
|
||||||
|
holder->first = 0; // This is the number of times the callback has been called, initalized to 0
|
||||||
|
auto fnCombineTwoLists = [=] (QList<QPair<QString, QString>> list) {
|
||||||
|
// Increment the callback counter
|
||||||
|
holder->first++;
|
||||||
|
|
||||||
|
// Add all
|
||||||
|
std::copy(list.begin(), list.end(), std::back_inserter(holder->second));
|
||||||
|
|
||||||
|
// And if the caller has been called twice, do the parent callback with the
|
||||||
|
// collected list
|
||||||
|
if (holder->first == 2) {
|
||||||
|
// Sort so z addresses are on top
|
||||||
|
std::sort(holder->second.begin(), holder->second.end(),
|
||||||
|
[=] (auto a, auto b) { return a.first > b.first; });
|
||||||
|
|
||||||
|
cb(holder->second);
|
||||||
|
delete holder;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A utility fn to do the batch calling
|
||||||
|
auto fnDoBatchGetPrivKeys = [=](json getAddressPayload, std::string privKeyDumpMethodName) {
|
||||||
|
conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (json resp) {
|
||||||
|
QList<QString> addrs;
|
||||||
|
for (auto addr : resp.get<json::array_t>()) {
|
||||||
|
addrs.push_back(QString::fromStdString(addr.get<json::string_t>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, do a batch request to get all the private keys
|
||||||
|
conn->doBatchRPC<QString>(
|
||||||
|
addrs,
|
||||||
|
[=] (auto addr) {
|
||||||
|
json payload = {
|
||||||
|
{"jsonrpc", "1.0"},
|
||||||
|
{"id", "someid"},
|
||||||
|
{"method", privKeyDumpMethodName},
|
||||||
|
{"params", { addr.toStdString() }},
|
||||||
|
};
|
||||||
|
return payload;
|
||||||
|
},
|
||||||
|
[=] (QMap<QString, json>* privkeys) {
|
||||||
|
QList<QPair<QString, QString>> allTKeys;
|
||||||
|
for (QString addr: privkeys->keys()) {
|
||||||
|
allTKeys.push_back(
|
||||||
|
QPair<QString, QString>(
|
||||||
|
addr,
|
||||||
|
QString::fromStdString(privkeys->value(addr).get<json::string_t>())));
|
||||||
|
}
|
||||||
|
|
||||||
|
fnCombineTwoLists(allTKeys);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// First get all the T and Z addresses.
|
||||||
|
json payloadT = {
|
||||||
|
{"jsonrpc", "1.0"},
|
||||||
|
{"id", "someid"},
|
||||||
|
{"method", "getaddressesbyaccount"},
|
||||||
|
{"params", {""} }
|
||||||
|
};
|
||||||
|
|
||||||
|
json payloadZ = {
|
||||||
|
{"jsonrpc", "1.0"},
|
||||||
|
{"id", "someid"},
|
||||||
|
{"method", "z_listaddresses"}
|
||||||
|
};
|
||||||
|
|
||||||
|
fnDoBatchGetPrivKeys(payloadT, "dumpprivkey");
|
||||||
|
fnDoBatchGetPrivKeys(payloadZ, "z_exportkey");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Build the RPC JSON Parameters for this tx (with the dev fee included if applicable)
|
// Build the RPC JSON Parameters for this tx (with the dev fee included if applicable)
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ public:
|
|||||||
void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
|
void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
|
||||||
void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
|
void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
|
||||||
|
|
||||||
|
void getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)>);
|
||||||
|
|
||||||
Turnstile* getTurnstile() { return turnstile; }
|
Turnstile* getTurnstile() { return turnstile; }
|
||||||
Connection* getConnection() { return conn; }
|
Connection* getConnection() { return conn; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user