diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a22043e..71848c5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,6 +1,7 @@ #include "mainwindow.h" #include "addressbook.h" #include "viewalladdresses.h" +#include "validateaddress.h" #include "ui_mainwindow.h" #include "ui_mobileappconnector.h" #include "ui_addressbook.h" @@ -11,6 +12,7 @@ #include "ui_turnstile.h" #include "ui_turnstileprogress.h" #include "ui_viewalladdresses.h" +#include "ui_validateaddress.h" #include "rpc.h" #include "balancestablemodel.h" #include "settings.h" @@ -83,6 +85,9 @@ MainWindow::MainWindow(QWidget *parent) : // z-Board.net QObject::connect(ui->actionz_board_net, &QAction::triggered, this, &MainWindow::postToZBoard); + // Validate Address + QObject::connect(ui->actionValidate_Address, &QAction::triggered, this, &MainWindow::validateAddress); + // Connect mobile app QObject::connect(ui->actionConnect_Mobile_App, &QAction::triggered, this, [=] () { if (rpc->getConnection() == nullptr) @@ -644,6 +649,48 @@ void MainWindow::donate() { ui->tabWidget->setCurrentIndex(1); } +/** + * Validate an address + */ +void MainWindow::validateAddress() { + // Make sure everything is up and running + if (!getRPC() || !getRPC()->getConnection()) + return; + + // First thing is ask the user for an address + bool ok; + auto address = QInputDialog::getText(this, tr("Enter Address to validate"), + tr("Transparent or Shielded Address:") + QString(" ").repeated(140), // Pad the label so the dialog box is wide enough + QLineEdit::Normal, "", &ok); + if (!ok) + return; + + getRPC()->validateAddress(address, [=] (json props) { + QDialog d(this); + Ui_ValidateAddress va; + va.setupUi(&d); + Settings::saveRestore(&d); + Settings::saveRestoreTableHeader(va.tblProps, &d, "validateaddressprops"); + va.tblProps->horizontalHeader()->setStretchLastSection(true); + + va.lblAddress->setText(address); + + QList> propsList; + for (auto it = props.begin(); it != props.end(); it++) { + + propsList.append( + QPair( + QString::fromStdString(it.key()), QString::fromStdString(it.value().dump())) + ); + } + + ValidateAddressesModel model(va.tblProps, propsList); + va.tblProps->setModel(&model); + + d.exec(); + }); + +} void MainWindow::postToZBoard() { QDialog d(this); @@ -1233,7 +1280,6 @@ void MainWindow::setupTransactionsTab() { } void MainWindow::addNewZaddr(bool sapling) { - rpc->newZaddr(sapling, [=] (json reply) { QString addr = QString::fromStdString(reply.get()); // Make sure the RPC class reloads the z-addrs for future use @@ -1318,6 +1364,7 @@ void MainWindow::setupReceiveTab() { viewaddrs.setupUi(&d); Settings::saveRestore(&d); Settings::saveRestoreTableHeader(viewaddrs.tblAddresses, &d, "viewalladdressestable"); + viewaddrs.tblAddresses->horizontalHeader()->setStretchLastSection(true); ViewAllAddressesModel model(viewaddrs.tblAddresses, *getRPC()->getAllTAddresses(), getRPC()); viewaddrs.tblAddresses->setModel(&model); diff --git a/src/mainwindow.h b/src/mainwindow.h index 40ca4ee..5343d28 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -58,6 +58,8 @@ public: void balancesReady(); void payZcashURI(QString uri = "", QString myAddr = ""); + void validateAddress(); + void updateLabels(); void updateTAddrCombo(bool checked); void updateFromCombo(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index aa9599a..b148265 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -1084,6 +1084,7 @@ &Apps + @@ -1202,6 +1203,11 @@ File a bug... + + + Validate Address + + diff --git a/src/rpc.cpp b/src/rpc.cpp index 5a79623..c38be5b 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -219,6 +219,18 @@ void RPC::importTPrivKey(QString addr, bool rescan, const std::functiondoRPCWithDefaultErrorHandling(payload, cb); } +void RPC::validateAddress(QString address, const std::function& cb) { + QString method = address.startsWith("z") ? "z_validateaddress" : "validateaddress"; + + json payload = { + {"jsonrpc", "1.0"}, + {"id", "someid"}, + {"method", method.toStdString() }, + {"params", { address.toStdString() } }, + }; + + conn->doRPCWithDefaultErrorHandling(payload, cb); +} void RPC::getBalance(const std::function& cb) { json payload = { diff --git a/src/rpc.h b/src/rpc.h index a4e54ea..9064b17 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -84,6 +84,7 @@ public: void getTPrivKey(QString addr, const std::function& cb); void importZPrivKey(QString addr, bool rescan, const std::function& cb); void importTPrivKey(QString addr, bool rescan, const std::function& cb); + void validateAddress(QString address, const std::function& cb); void shutdownZcashd(); void noConnection(); @@ -121,7 +122,6 @@ private: void getZAddresses (const std::function& cb); void getTAddresses (const std::function& cb); - Connection* conn = nullptr; QProcess* ezcashd = nullptr; diff --git a/src/validateaddress.cpp b/src/validateaddress.cpp new file mode 100644 index 0000000..d82e82e --- /dev/null +++ b/src/validateaddress.cpp @@ -0,0 +1,37 @@ +#include "validateaddress.h" + + +ValidateAddressesModel::ValidateAddressesModel(QTableView *parent, QList> props) + : QAbstractTableModel(parent) { + headers << tr("Property") << tr("Value"); + this->props = props; +} + + +int ValidateAddressesModel::rowCount(const QModelIndex&) const { + return props.size(); +} + +int ValidateAddressesModel::columnCount(const QModelIndex&) const { + return headers.size(); +} + +QVariant ValidateAddressesModel::data(const QModelIndex &index, int role) const { + QPair p = props.at(index.row()); + if (role == Qt::DisplayRole) { + switch(index.column()) { + case 0: return p.first; + case 1: return p.second; + } + } + return QVariant(); +} + + +QVariant ValidateAddressesModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + return headers.at(section); + } + + return QVariant(); +} diff --git a/src/validateaddress.h b/src/validateaddress.h new file mode 100644 index 0000000..19db4cb --- /dev/null +++ b/src/validateaddress.h @@ -0,0 +1,23 @@ +#ifndef VALIDATEADDRESS_H +#define VALIDATEADDRESS_H + +#include "precompiled.h" + +class ValidateAddressesModel : public QAbstractTableModel { + +public: + ValidateAddressesModel(QTableView* parent, QList> props); + ~ValidateAddressesModel() = default; + + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + +private: + QList> props; + QStringList headers; +}; + + +#endif // VALIDATEADDRESS_H diff --git a/src/validateaddress.ui b/src/validateaddress.ui new file mode 100644 index 0000000..20caebb --- /dev/null +++ b/src/validateaddress.ui @@ -0,0 +1,85 @@ + + + ValidateAddress + + + + 0 + 0 + 400 + 300 + + + + Validate Address + + + + + + TextLabel + + + + + + + Address: + + + + + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + ValidateAddress + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ValidateAddress + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 493e303..755ce22 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -53,6 +53,7 @@ SOURCES += \ src/addressbook.cpp \ src/logger.cpp \ src/addresscombo.cpp \ + src/validateaddress.cpp \ src/websockets.cpp \ src/mobileappconnector.cpp \ src/recurring.cpp \ @@ -78,13 +79,14 @@ HEADERS += \ src/fillediconlabel.h \ src/addressbook.h \ src/logger.h \ - src/addresscombo.h \ + src/addresscombo.h \ + src/validateaddress.h \ src/websockets.h \ src/mobileappconnector.h \ src/recurring.h \ src/requestdialog.h \ src/memoedit.h \ - src/viewalladdresses.h + src/viewalladdresses.h FORMS += \ src/mainwindow.ui \ @@ -97,6 +99,7 @@ FORMS += \ src/turnstileprogress.ui \ src/privkey.ui \ src/memodialog.ui \ + src/validateaddress.ui \ src/viewalladdresses.ui \ src/connection.ui \ src/zboard.ui \