From 9dd6821178478e9d8b2dca9f92b913c016ff8b33 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 22 Mar 2019 12:44:40 -0700 Subject: [PATCH 01/15] Refactor MemoEdit --- src/memodialog.ui | 9 ++- src/memoedit.cpp | 44 +++++++++++++++ src/memoedit.h | 22 ++++++++ src/precompiled.h | 2 + src/requestdialog.cpp | 14 +++++ src/requestdialog.h | 22 ++++++++ src/requestdialog.ui | 124 ++++++++++++++++++++++++++++++++++++++++++ src/sendtab.cpp | 23 +------- src/settings.ui | 39 +++++++++++-- zec-qt-wallet.pro | 11 +++- 10 files changed, 282 insertions(+), 28 deletions(-) create mode 100644 src/memoedit.cpp create mode 100644 src/memoedit.h create mode 100644 src/requestdialog.cpp create mode 100644 src/requestdialog.h create mode 100644 src/requestdialog.ui diff --git a/src/memodialog.ui b/src/memodialog.ui index 0d7e704..1c144e0 100644 --- a/src/memodialog.ui +++ b/src/memodialog.ui @@ -35,7 +35,7 @@ - + @@ -70,6 +70,13 @@ + + + MemoEdit + QPlainTextEdit +
memoedit.h
+
+
diff --git a/src/memoedit.cpp b/src/memoedit.cpp new file mode 100644 index 0000000..f8a3565 --- /dev/null +++ b/src/memoedit.cpp @@ -0,0 +1,44 @@ +#include "memoedit.h" + +MemoEdit::MemoEdit(QWidget* parent) : QPlainTextEdit(parent) { + QObject::connect(this, &QPlainTextEdit::textChanged, [=]() { + QString txt = this->toPlainText(); + if (lenDisplayLabel) + lenDisplayLabel->setText(QString::number(txt.toUtf8().size()) + "/" + QString::number(maxlen)); + + if (txt.toUtf8().size() <= maxlen) { + // Everything is fine + acceptButton->setEnabled(true); + lenDisplayLabel->setStyleSheet(""); + } + else { + // Overweight + acceptButton->setEnabled(false); + lenDisplayLabel->setStyleSheet("color: red;"); + } + + }); +} + +void MemoEdit::setMaxLen(int len) { + this->maxlen = len; +} + +void MemoEdit::setLenDisplayLabel(QLabel* label) { + this->lenDisplayLabel = label; +} + +void MemoEdit::setAcceptButton(QPushButton* button) { + this->acceptButton = button; +} + +void MemoEdit::includeReplyTo(QString addr) { + if (addr.isEmpty()) + return; + + auto curText = this->toPlainText(); + if (curText.endsWith(addr)) + return; + + this->setPlainText(curText + "\n" + tr("Reply to") + ":\n" + addr); +} \ No newline at end of file diff --git a/src/memoedit.h b/src/memoedit.h new file mode 100644 index 0000000..1c6ba93 --- /dev/null +++ b/src/memoedit.h @@ -0,0 +1,22 @@ +#ifndef MEMOEDIT_H +#define MEMOEDIT_H + +#include "precompiled.h" + +class MemoEdit : public QPlainTextEdit +{ +public: + MemoEdit(QWidget* parent); + + void setMaxLen(int len); + void setLenDisplayLabel(QLabel* label); + void setAcceptButton(QPushButton* button); + void includeReplyTo(QString replyToAddress); + +private: + int maxlen = 512; + QLabel* lenDisplayLabel = nullptr; + QPushButton* acceptButton = nullptr; +}; + +#endif // MEMOEDIT_H \ No newline at end of file diff --git a/src/precompiled.h b/src/precompiled.h index ee2dea5..5745182 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp new file mode 100644 index 0000000..5a56298 --- /dev/null +++ b/src/requestdialog.cpp @@ -0,0 +1,14 @@ +#include "requestdialog.h" +#include "ui_requestdialog.h" + +RequestDialog::RequestDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::RequestDialog) +{ + ui->setupUi(this); +} + +RequestDialog::~RequestDialog() +{ + delete ui; +} diff --git a/src/requestdialog.h b/src/requestdialog.h new file mode 100644 index 0000000..36e2da0 --- /dev/null +++ b/src/requestdialog.h @@ -0,0 +1,22 @@ +#ifndef REQUESTDIALOG_H +#define REQUESTDIALOG_H + +#include + +namespace Ui { +class RequestDialog; +} + +class RequestDialog : public QDialog +{ + Q_OBJECT + +public: + explicit RequestDialog(QWidget *parent = nullptr); + ~RequestDialog(); + +private: + Ui::RequestDialog *ui; +}; + +#endif // REQUESTDIALOG_H diff --git a/src/requestdialog.ui b/src/requestdialog.ui new file mode 100644 index 0000000..b2a11b3 --- /dev/null +++ b/src/requestdialog.ui @@ -0,0 +1,124 @@ + + + RequestDialog + + + + 0 + 0 + 544 + 450 + + + + Dialog + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + amount in ZEC + + + + + + + Amount USD + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Amount + + + + + + + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + z address + + + + + + + Memo + + + + + + + Request From + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + RequestDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + RequestDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/sendtab.cpp b/src/sendtab.cpp index b0ffb47..a91ff4c 100644 --- a/src/sendtab.cpp +++ b/src/sendtab.cpp @@ -330,22 +330,8 @@ void MainWindow::memoButtonClicked(int number, bool includeReplyTo) { memoDialog.setupUi(&dialog); Settings::saveRestore(&dialog); - QObject::connect(memoDialog.memoTxt, &QPlainTextEdit::textChanged, [=] () { - QString txt = memoDialog.memoTxt->toPlainText(); - memoDialog.memoSize->setText(QString::number(txt.toUtf8().size()) + "/512"); - - if (txt.toUtf8().size() <= 512) { - // Everything is fine - memoDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); - memoDialog.memoSize->setStyleSheet(""); - } - else { - // Overweight - memoDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - memoDialog.memoSize->setStyleSheet("color: red;"); - } - - }); + memoDialog.memoTxt->setLenDisplayLabel(memoDialog.memoSize); + memoDialog.memoTxt->setAcceptButton(memoDialog.buttonBox->button(QDialogButtonBox::Ok)); auto fnAddReplyTo = [=, &dialog]() { QString replyTo = ui->inputsCombo->currentText(); @@ -354,11 +340,8 @@ void MainWindow::memoButtonClicked(int number, bool includeReplyTo) { if (replyTo.isEmpty()) return; } - auto curText = memoDialog.memoTxt->toPlainText(); - if (curText.endsWith(replyTo)) - return; - memoDialog.memoTxt->setPlainText(curText + "\n" + tr("Reply to") + ":\n" + replyTo); + memoDialog.memoTxt->includeReplyTo(replyTo); // MacOS has a really annoying bug where the Plaintext doesn't refresh when the content is // updated. So we do this ugly hack - resize the window slightly to force it to refresh diff --git a/src/settings.ui b/src/settings.ui index 38d40c1..d026952 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -274,7 +274,7 @@ Troubleshooting - + Reindex @@ -305,7 +305,7 @@ - + Qt::Vertical @@ -318,7 +318,24 @@ - + + + + + + + + + + + Rescan the blockchain for any missing wallet transactions and to correct your wallet balance. This will take several hours. You need to restart ZecWallet for this to take effect + + + true + + + + Rebuild the entire blockchain from the genesis block, by rescanning all the block files. This may take several hours to days, depending on your hardware. You need to restart ZecWallet for this to take effect @@ -328,13 +345,27 @@ - + + + + Rescan + + + + Qt::Horizontal + + + + + + + diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 83af52b..3f08154 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -55,7 +55,9 @@ SOURCES += \ src/addresscombo.cpp \ src/websockets.cpp \ src/mobileappconnector.cpp \ - src/recurring.cpp + src/recurring.cpp \ + src/requestdialog.cpp \ + src/memoedit.cpp HEADERS += \ src/mainwindow.h \ @@ -78,7 +80,9 @@ HEADERS += \ src/addresscombo.h \ src/websockets.h \ src/mobileappconnector.h \ - src/recurring.h + src/recurring.h \ + src/requestdialog.h \ + src/memoedit.h FORMS += \ src/mainwindow.ui \ @@ -95,7 +99,8 @@ FORMS += \ src/mobileappconnector.ui \ src/createzcashconfdialog.ui \ src/recurringdialog.ui \ - src/newrecurring.ui + src/newrecurring.ui \ + src/requestdialog.ui TRANSLATIONS = res/zec_qt_wallet_es.ts \ From c70819be0f08c5248446f46c4af864ad6a827aeb Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 22 Mar 2019 13:27:24 -0700 Subject: [PATCH 02/15] Requst payment dialog --- src/mainwindow.cpp | 9 ++++ src/mainwindow.h | 9 +++- src/mainwindow.ui | 18 ++++--- src/memoedit.cpp | 32 ++++++++----- src/memoedit.h | 1 + src/requestdialog.cpp | 49 +++++++++++++++++++ src/requestdialog.h | 3 ++ src/requestdialog.ui | 109 ++++++++++++++++++++++++++++++++---------- src/sendtab.cpp | 8 ++-- 9 files changed, 191 insertions(+), 47 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cab4485..01573e4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -16,6 +16,7 @@ #include "turnstile.h" #include "senttxstore.h" #include "connection.h" +#include "requestdialog.h" #include "websockets.h" using json = nlohmann::json; @@ -45,6 +46,11 @@ MainWindow::MainWindow(QWidget *parent) : rpc->checkForUpdate(false); }); + // Request zcash + QObject::connect(ui->actionRequest_zcash, &QAction::triggered, [=]() { + RequestDialog::showRequestZcash(this); + }); + // Pay Zcash URI QObject::connect(ui->actionPay_URI, &QAction::triggered, [=] () { payZcashURI(); @@ -1505,6 +1511,9 @@ MainWindow::~MainWindow() delete rpc; delete labelCompleter; + delete amtValidator; + delete feesValidator; + delete loadingMovie; delete logger; diff --git a/src/mainwindow.h b/src/mainwindow.h index 1a80213..6a5e179 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -42,6 +42,9 @@ public: void updateLabelsAutoComplete(); RPC* getRPC() { return rpc; } + QCompleter* getLabelCompleter() { return labelCompleter; } + QRegExpValidator* getAmountValidator() { return amtValidator; } + QString doSendTxValidations(Tx tx); void setDefaultPayFrom(); @@ -126,8 +129,10 @@ private: WSServer* wsserver = nullptr; WormholeClient* wormhole = nullptr; - RPC* rpc = nullptr; - QCompleter* labelCompleter = nullptr; + RPC* rpc = nullptr; + QCompleter* labelCompleter = nullptr; + QRegExpValidator* amtValidator = nullptr; + QRegExpValidator* feesValidator = nullptr; QMovie* loadingMovie; }; diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 812ed37..718a2bf 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -22,7 +22,7 @@ - 2 + 1 @@ -1058,6 +1058,7 @@ &File + @@ -1183,19 +1184,24 @@ Ctrl+M + + + Request zcash... + + - - QRCodeLabel - QLabel -
qrcodelabel.h
-
AddressCombo QComboBox
addresscombo.h
+ + QRCodeLabel + QLabel +
qrcodelabel.h
+
FilledIconLabel QLabel diff --git a/src/memoedit.cpp b/src/memoedit.cpp index f8a3565..79589e2 100644 --- a/src/memoedit.cpp +++ b/src/memoedit.cpp @@ -1,27 +1,35 @@ #include "memoedit.h" MemoEdit::MemoEdit(QWidget* parent) : QPlainTextEdit(parent) { - QObject::connect(this, &QPlainTextEdit::textChanged, [=]() { - QString txt = this->toPlainText(); - if (lenDisplayLabel) - lenDisplayLabel->setText(QString::number(txt.toUtf8().size()) + "/" + QString::number(maxlen)); + QObject::connect(this, &QPlainTextEdit::textChanged, this, &MemoEdit::updateDisplay); +} - if (txt.toUtf8().size() <= maxlen) { - // Everything is fine +void MemoEdit::updateDisplay() { + QString txt = this->toPlainText(); + if (lenDisplayLabel) + lenDisplayLabel->setText(QString::number(txt.toUtf8().size()) + "/" + QString::number(maxlen)); + + if (txt.toUtf8().size() <= maxlen) { + // Everything is fine + if (acceptButton) acceptButton->setEnabled(true); + + if (lenDisplayLabel) lenDisplayLabel->setStyleSheet(""); - } - else { - // Overweight + } + else { + // Overweight + if (acceptButton) acceptButton->setEnabled(false); + + if (lenDisplayLabel) lenDisplayLabel->setStyleSheet("color: red;"); - } - - }); + } } void MemoEdit::setMaxLen(int len) { this->maxlen = len; + updateDisplay(); } void MemoEdit::setLenDisplayLabel(QLabel* label) { diff --git a/src/memoedit.h b/src/memoedit.h index 1c6ba93..f1b2f5c 100644 --- a/src/memoedit.h +++ b/src/memoedit.h @@ -12,6 +12,7 @@ public: void setLenDisplayLabel(QLabel* label); void setAcceptButton(QPushButton* button); void includeReplyTo(QString replyToAddress); + void updateDisplay(); private: int maxlen = 512; diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index 5a56298..abfe170 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -1,5 +1,7 @@ #include "requestdialog.h" #include "ui_requestdialog.h" +#include "settings.h" +#include "addressbook.h" RequestDialog::RequestDialog(QWidget *parent) : QDialog(parent), @@ -12,3 +14,50 @@ RequestDialog::~RequestDialog() { delete ui; } + +// Static method that shows the request dialog +void RequestDialog::showRequestZcash(MainWindow* main) { + QDialog d(main); + Ui_RequestDialog req; + req.setupUi(&d); + Settings::saveRestore(&d); + + // Setup the Label completer for the Address + req.txtFrom->setCompleter(main->getLabelCompleter()); + QObject::connect(req.txtFrom, &QLineEdit::textChanged, [=] (auto text) { + auto addr = AddressBook::addressFromAddressLabel(text); + if (!Settings::getInstance()->isSaplingAddress(addr)) { + req.lblSaplingWarning->setText(tr("Can only request from Sapling addresses")); + req.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } else { + req.lblSaplingWarning->setText(""); + req.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + } + }); + + // Wire up AddressBook button + QObject::connect(req.btnAddressBook, &QPushButton::clicked, [=] () { + AddressBook::open(main, req.txtFrom); + }); + + // Amount textbox + req.txtAmount->setValidator(main->getAmountValidator()); + QObject::connect(req.txtAmount, &QLineEdit::textChanged, [=] (auto text) { + req.txtAmountUSD->setText(Settings::getUSDFormat(text.toDouble())); + }); + req.txtAmountUSD->setText(Settings::getUSDFormat(req.txtAmount->text().toDouble())); + + req.txtMemo->setAcceptButton(req.buttonBox->button(QDialogButtonBox::Ok)); + req.txtMemo->setLenDisplayLabel(req.lblMemoLen); + req.txtMemo->setMaxLen(400); + + req.txtFrom->setFocus(); + + if (d.exec() == QDialog::Accepted) { + // Construct a zcash Payment URI with the data and pay it immediately. + QString paymentURI = "zcash:" + AddressBook::addressFromAddressLabel(req.txtFrom->text()) + + "?amt=" + Settings::getDecimalString(req.txtAmount->text().toDouble()) + + "&memo=" + QUrl::toPercentEncoding(req.txtMemo->toPlainText()); + main->payZcashURI(paymentURI); + } +} \ No newline at end of file diff --git a/src/requestdialog.h b/src/requestdialog.h index 36e2da0..eca2e5d 100644 --- a/src/requestdialog.h +++ b/src/requestdialog.h @@ -2,6 +2,7 @@ #define REQUESTDIALOG_H #include +#include "mainwindow.h" namespace Ui { class RequestDialog; @@ -15,6 +16,8 @@ public: explicit RequestDialog(QWidget *parent = nullptr); ~RequestDialog(); + static void showRequestZcash(MainWindow* main); + private: Ui::RequestDialog *ui; }; diff --git a/src/requestdialog.ui b/src/requestdialog.ui index b2a11b3..dd3614f 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -6,45 +6,92 @@ 0 0 - 544 - 450 + 714 + 524 Dialog - + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - amount in ZEC + Amount - - + + + + color: red; + - Amount USD + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + - Amount + 0 / 512 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + + + Memo + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + AddressBook + + + + - + @@ -60,32 +107,46 @@ - - + + - Memo + Request From - - + + - Request From + Amount USD + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - + + + + Amount in ZEC + + + + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok -
+ + + MemoEdit + QPlainTextEdit +
memoedit.h
+
+
diff --git a/src/sendtab.cpp b/src/sendtab.cpp index a91ff4c..13f7613 100644 --- a/src/sendtab.cpp +++ b/src/sendtab.cpp @@ -12,7 +12,8 @@ using json = nlohmann::json; void MainWindow::setupSendTab() { // Create the validator for send to/amount fields - auto amtValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}")); + amtValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}")); + ui->Amount1->setValidator(amtValidator); // Send button @@ -72,8 +73,9 @@ void MainWindow::setupSendTab() { ui->lblMinerFeeUSD->setText(Settings::getUSDFormat(txt.toDouble())); } }); + //Fees validator - auto feesValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}")); + feesValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}")); ui->minerFeeAmt->setValidator(feesValidator); // Font for the first Memo label @@ -243,8 +245,8 @@ void MainWindow::addAddressSection() { Amount1->setObjectName(QString("Amount") % QString::number(itemNumber)); Amount1->setBaseSize(QSize(200, 0)); Amount1->setAlignment(Qt::AlignRight); + // Create the validator for send to/amount fields - auto amtValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}")); Amount1->setValidator(amtValidator); QObject::connect(Amount1, &QLineEdit::textChanged, [=] (auto text) { this->amountChanged(itemNumber, text); From e46725f322665bd08e04429c0aed1eb4e55ee2f1 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 22 Mar 2019 15:37:21 -0700 Subject: [PATCH 03/15] Pay payment requests --- application.qrc | 1 + res/paymentreq.gif | Bin 0 -> 7633 bytes src/mainwindow.cpp | 81 ++++++--------------------- src/requestdialog.cpp | 61 ++++++++++++++++++++- src/requestdialog.h | 4 +- src/requestdialog.ui | 124 +++++++++++++++++++++++++++--------------- src/settings.cpp | 61 +++++++++++++++++++-- src/settings.h | 12 ++++ src/txtablemodel.cpp | 22 ++++++-- 9 files changed, 246 insertions(+), 120 deletions(-) create mode 100644 res/paymentreq.gif diff --git a/application.qrc b/application.qrc index e7e9b2c..c7201af 100644 --- a/application.qrc +++ b/application.qrc @@ -5,6 +5,7 @@ res/connected.gif res/loading.gif + res/paymentreq.gif res/icon.ico diff --git a/res/paymentreq.gif b/res/paymentreq.gif new file mode 100644 index 0000000000000000000000000000000000000000..f451982d5a421a22b58ebf01fed514207c6f0e00 GIT binary patch literal 7633 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 literal 0 HcmV?d00001 diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 01573e4..82ba03c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -804,12 +804,6 @@ void MainWindow::payZcashURI(QString uri) { return; } - // Error to display if something goes wrong. - auto payZcashURIError = [=] (QString errorDetail = "") { - QMessageBox::critical(this, tr("Error paying zcash URI"), - tr("URI should be of the form 'zcash:?amt=x&memo=y") + "\n" + errorDetail); - }; - // If there was no URI passed, ask the user for one. if (uri.isEmpty()) { uri = QInputDialog::getText(this, tr("Paste Zcash URI"), @@ -820,70 +814,21 @@ void MainWindow::payZcashURI(QString uri) { if (uri.isEmpty()) return; - // URI should be of the form zcash://address?amt=x&memo=y - if (!uri.startsWith("zcash:")) { - payZcashURIError(); - return; - } - // Extract the address qDebug() << "Recieved URI " << uri; - uri = uri.right(uri.length() - QString("zcash:").length()); - - QRegExp re("([a-zA-Z0-9]+)"); - int pos; - if ( (pos = re.indexIn(uri)) == -1 ) { - payZcashURIError(); - return; - } - - QString addr = re.cap(1); - if (!Settings::isValidAddress(addr)) { - payZcashURIError(tr("Could not understand address")); + PaymentURI paymentInfo = Settings::parseURI(uri); + if (!paymentInfo.error.isEmpty()) { + QMessageBox::critical(this, tr("Error paying zcash URI"), + tr("URI should be of the form 'zcash:?amt=x&memo=y") + "\n" + paymentInfo.error); return; } - uri = uri.right(uri.length() - addr.length()); - - double amount = 0.0; - QString memo = ""; - - if (!uri.isEmpty()) { - uri = uri.right(uri.length() - 1); // Eat the "?" - - QStringList args = uri.split("&"); - for (QString arg: args) { - QStringList kv = arg.split("="); - if (kv.length() != 2) { - payZcashURIError(); - return; - } - - if (kv[0].toLower() == "amt" || kv[0].toLower() == "amount") { - amount = kv[1].toDouble(); - } else if (kv[0].toLower() == "memo" || kv[0].toLower() == "message" || kv[0].toLower() == "msg") { - memo = kv[1]; - // Test if this is hex - - QRegularExpression hexMatcher("^[0-9A-F]+$", - QRegularExpression::CaseInsensitiveOption); - QRegularExpressionMatch match = hexMatcher.match(memo); - if (match.hasMatch()) { - // Encoded as hex, convert to string - memo = QByteArray::fromHex(memo.toUtf8()); - } - } else { - payZcashURIError(tr("Unknown field in URI:") + kv[0]); - return; - } - } - } // Now, set the fields on the send tab removeExtraAddresses(); - ui->Address1->setText(addr); + ui->Address1->setText(paymentInfo.addr); ui->Address1->setCursorPosition(0); - ui->Amount1->setText(QString::number(amount)); - ui->MemoTxt1->setText(memo); + ui->Amount1->setText(Settings::getDecimalString(paymentInfo.amt.toDouble())); + ui->MemoTxt1->setText(paymentInfo.memo); // And switch to the send tab. ui->tabWidget->setCurrentIndex(1); @@ -891,7 +836,7 @@ void MainWindow::payZcashURI(QString uri) { // And click the send button if the amount is > 0, to validate everything. If everything is OK, it will show the confirm box // else, show the error message; - if (amount > 0) { + if (paymentInfo.amt > 0) { sendButton(); } } @@ -1214,8 +1159,16 @@ void MainWindow::setupTransactionsTab() { QDesktopServices::openUrl(QUrl(url)); }); + // Payment Request + if (!memo.isEmpty() && memo.startsWith("zcash:")) { + menu.addAction(tr("View Payment Request"), [=] () { + RequestDialog::showPaymentConfirmation(this, memo); + }); + } + + // View Memo if (!memo.isEmpty()) { - menu.addAction(tr("View Memo"), [=] () { + menu.addAction(tr("View Memo"), [=] () { QMessageBox mb(QMessageBox::Information, tr("Memo"), memo, QMessageBox::Ok, this); mb.setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); mb.exec(); diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index abfe170..da95c3d 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -2,6 +2,10 @@ #include "ui_requestdialog.h" #include "settings.h" #include "addressbook.h" +#include "mainwindow.h" +#include "rpc.h" +#include "settings.h" + RequestDialog::RequestDialog(QWidget *parent) : QDialog(parent), @@ -15,6 +19,51 @@ RequestDialog::~RequestDialog() delete ui; } +void RequestDialog::setupDialog(QDialog* d, Ui_RequestDialog* req) { + req->setupUi(d); + Settings::saveRestore(d); + + // Setup + req->txtMemo->setLenDisplayLabel(req->lblMemoLen); + req->lblAmount->setText(req->lblAmount->text() + Settings::getTokenName()); +} + +// Static method that shows an incoming payment request and prompts the user to pay it +void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI) { + PaymentURI payInfo = Settings::parseURI(paymentURI); + if (!payInfo.error.isEmpty()) { + QMessageBox::critical(main, tr("Error paying zcash URI"), + tr("URI should be of the form 'zcash:?amt=x&memo=y") + "\n" + payInfo.error); + return; + } + + QDialog d(main); + Ui_RequestDialog req; + setupDialog(&d, &req); + + // In the view mode, all fields are read-only + req.txtAmount->setReadOnly(true); + req.txtFrom->setReadOnly(true); + req.txtMemo->setReadOnly(true); + + // Payment is "to" + req.lblAddress->setText(tr("Pay To")); + + // No Addressbook + req.btnAddressBook->setVisible(false); + + req.txtFrom->setText(payInfo.addr); + req.txtMemo->setPlainText(payInfo.memo); + req.txtAmount->setText(payInfo.amt); + req.txtAmountUSD->setText(Settings::getUSDFormat(req.txtAmount->text().toDouble())); + + req.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Pay")); + + if (d.exec() == QDialog::Accepted) { + main->payZcashURI(paymentURI); + } +} + // Static method that shows the request dialog void RequestDialog::showRequestZcash(MainWindow* main) { QDialog d(main); @@ -55,9 +104,15 @@ void RequestDialog::showRequestZcash(MainWindow* main) { if (d.exec() == QDialog::Accepted) { // Construct a zcash Payment URI with the data and pay it immediately. - QString paymentURI = "zcash:" + AddressBook::addressFromAddressLabel(req.txtFrom->text()) + QString memoURI = "zcash:" + main->getRPC()->getDefaultSaplingAddress() + "?amt=" + Settings::getDecimalString(req.txtAmount->text().toDouble()) + "&memo=" + QUrl::toPercentEncoding(req.txtMemo->toPlainText()); - main->payZcashURI(paymentURI); + + QString sendURI = "zcash:" + AddressBook::addressFromAddressLabel(req.txtFrom->text()) + + "?amt=0.0001" + + "&memo=" + QUrl::toPercentEncoding(memoURI); + + qDebug() << "Paying " << sendURI; + main->payZcashURI(sendURI); } -} \ No newline at end of file +} diff --git a/src/requestdialog.h b/src/requestdialog.h index eca2e5d..a05b3c7 100644 --- a/src/requestdialog.h +++ b/src/requestdialog.h @@ -3,6 +3,7 @@ #include #include "mainwindow.h" +#include "ui_requestdialog.h" namespace Ui { class RequestDialog; @@ -17,7 +18,8 @@ public: ~RequestDialog(); static void showRequestZcash(MainWindow* main); - + static void showPaymentConfirmation(MainWindow* main, QString paymentURI); + static void setupDialog(QDialog* d, Ui_RequestDialog* req); private: Ui::RequestDialog *ui; }; diff --git a/src/requestdialog.ui b/src/requestdialog.ui index dd3614f..f188f8b 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -6,41 +6,41 @@ 0 0 - 714 - 524 + 1052 + 509 - Dialog + Payment Request + + + + Qt::Vertical + + + + 20 + 40 + + + + - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Amount - - - - color: red; - - - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - + Qt::Horizontal @@ -67,8 +67,38 @@ - + + + + + 0 + 0 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + z address + + + + + + + Request From + + + + + + + + AddressBook + + + @@ -82,35 +112,25 @@ - - - - AddressBook - - - - - - - - 0 - 0 - + + + + color: red; - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + - - z address + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + - Request From + @@ -120,24 +140,37 @@ Amount USD - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + - Amount in ZEC + Amount in - + Qt::Horizontal + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -147,6 +180,11 @@
memoedit.h
+ + txtFrom + txtAmount + txtMemo + diff --git a/src/settings.cpp b/src/settings.cpp index 6810d51..c291247 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -161,10 +161,7 @@ void Settings::saveRestore(QDialog* d) { } QString Settings::getUSDFormat(double bal) { - if (!Settings::getInstance()->isTestnet() && Settings::getInstance()->getZECPrice() > 0) - return "$" + QLocale(QLocale::English).toString(bal * Settings::getInstance()->getZECPrice(), 'f', 2); - else - return QString(); + return "$" + QLocale(QLocale::English).toString(bal * Settings::getInstance()->getZECPrice(), 'f', 2); } QString Settings::getDecimalString(double amt) { @@ -289,4 +286,60 @@ bool Settings::isValidAddress(QString addr) { ztsexp.exactMatch(addr) || zsexp.exactMatch(addr); } +// Get a pretty string representation of this Payment URI +QString Settings::paymentURIPretty(PaymentURI uri) { + return QString() + "Payment Request\n" + "Pay: " + uri.addr + "\nAmount: " + getZECDisplayFormat(uri.amt.toDouble()) + + "\nMemo:" + QUrl::fromPercentEncoding(uri.memo.toUtf8()); +} + +// Parse a payment URI string into its components +PaymentURI Settings::parseURI(QString uri) { + PaymentURI ans; + + if (!uri.startsWith("zcash:")) { + ans.error = "Not a zcash payment URI"; + return ans; + } + + uri = uri.right(uri.length() - QString("zcash:").length()); + + QRegExp re("([a-zA-Z0-9]+)"); + int pos; + if ( (pos = re.indexIn(uri)) == -1 ) { + ans.error = "Couldn't find an address"; + return ans; + } + + ans.addr = re.cap(1); + if (!Settings::isValidAddress(ans.addr)) { + ans.error = "Could not understand address"; + return ans; + } + uri = uri.right(uri.length() - ans.addr.length()); + + if (!uri.isEmpty()) { + uri = uri.right(uri.length() - 1); // Eat the "?" + + QStringList args = uri.split("&"); + for (QString arg: args) { + QStringList kv = arg.split("="); + if (kv.length() != 2) { + ans.error = "No value argument was seen"; + return ans; + } + + if (kv[0].toLower() == "amt" || kv[0].toLower() == "amount") { + ans.amt = kv[1]; + } else if (kv[0].toLower() == "memo" || kv[0].toLower() == "message" || kv[0].toLower() == "msg") { + ans.memo = QUrl::fromPercentEncoding(kv[1].toUtf8()); + } else { + ans.error = "Unknown field in URI:" + kv[0]; + return ans; + } + } + } + + return ans; +} + const QString Settings::labelRegExp("[a-zA-Z0-9\\-_]{0,40}"); diff --git a/src/settings.h b/src/settings.h index 03ba530..ee3a053 100644 --- a/src/settings.h +++ b/src/settings.h @@ -13,6 +13,15 @@ struct Config { struct ToFields; struct Tx; +struct PaymentURI { + QString addr; + QString amt; + QString memo; + + // Any errors are stored here + QString error; +}; + class Settings { public: @@ -68,6 +77,9 @@ public: static void saveRestore(QDialog* d); + static PaymentURI parseURI(QString paymentURI); + static QString paymentURIPretty(PaymentURI); + static bool isZAddress(QString addr); static bool isTAddress(QString addr); diff --git a/src/txtablemodel.cpp b/src/txtablemodel.cpp index cc099e7..f563921 100644 --- a/src/txtablemodel.cpp +++ b/src/txtablemodel.cpp @@ -138,8 +138,14 @@ void TxTableModel::updateAllData() { if (role == Qt::ToolTipRole) { switch (index.column()) { - case 0: return modeldata->at(index.row()).type + - (dat.memo.isEmpty() ? "" : " tx memo: \"" + dat.memo + "\""); + case 0: { + if (dat.memo.startsWith("zcash:")) { + return Settings::paymentURIPretty(Settings::parseURI(dat.memo)); + } else { + return modeldata->at(index.row()).type + + (dat.memo.isEmpty() ? "" : " tx memo: \"" + dat.memo + "\""); + } + } case 1: { auto addr = modeldata->at(index.row()).address; if (addr.trimmed().isEmpty()) @@ -154,9 +160,15 @@ void TxTableModel::updateAllData() { if (role == Qt::DecorationRole && index.column() == 0) { if (!dat.memo.isEmpty()) { - // Return the info pixmap to indicate memo - QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); - return QVariant(icon.pixmap(16, 16)); + // If the memo is a Payment URI, then show a payment request icon + if (dat.memo.startsWith("zcash:")) { + QIcon icon(":/icons/res/paymentreq.gif"); + return QVariant(icon.pixmap(16, 16)); + } else { + // Return the info pixmap to indicate memo + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + return QVariant(icon.pixmap(16, 16)); + } } else { // Empty pixmap to make it align QPixmap p(16, 16); From ce2621abdfce855d89050f673c0522cf67393d64 Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Sat, 23 Mar 2019 10:42:42 -0700 Subject: [PATCH 04/15] Pick from address for request payments --- .gitignore | 1 + src/mainwindow.cpp | 9 ++- src/mainwindow.h | 2 +- src/requestdialog.cpp | 28 ++++++-- src/requestdialog.h | 2 +- src/requestdialog.ui | 156 ++++++++++++++++++++++++------------------ src/settings.ui | 17 ----- 7 files changed, 120 insertions(+), 95 deletions(-) diff --git a/.gitignore b/.gitignore index 0194a5a..a1efcce 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ workspace.code-workspace *.mak zcashd IDEWorkspaceChecks.plist +*.sln diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 82ba03c..df635d2 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -795,8 +795,9 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event) { // Pay the Zcash URI by showing a confirmation window. If the URI parameter is empty, the UI -// will prompt for one. -void MainWindow::payZcashURI(QString uri) { +// will prompt for one. If the myAddr is empty, then the default from address is used to send +// the transaction. +void MainWindow::payZcashURI(QString uri, QString myAddr) { // If the Payments UI is not ready (i.e, all balances have not loaded), defer the payment URI if (!uiPaymentsReady) { qDebug() << "Payment UI not ready, waiting for UI to pay URI"; @@ -825,6 +826,10 @@ void MainWindow::payZcashURI(QString uri) { // Now, set the fields on the send tab removeExtraAddresses(); + if (!myAddr.isEmpty()) { + ui->inputsCombo->setCurrentText(myAddr); + } + ui->Address1->setText(paymentInfo.addr); ui->Address1->setCursorPosition(0); ui->Amount1->setText(Settings::getDecimalString(paymentInfo.amt.toDouble())); diff --git a/src/mainwindow.h b/src/mainwindow.h index 6a5e179..692e746 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -54,7 +54,7 @@ public: void stopWebsocket(); void balancesReady(); - void payZcashURI(QString uri = ""); + void payZcashURI(QString uri = "", QString myAddr = ""); void updateLabels(); void updateTAddrCombo(bool checked); diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index da95c3d..1adcb75 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -6,6 +6,7 @@ #include "rpc.h" #include "settings.h" +#include "precompiled.h" RequestDialog::RequestDialog(QWidget *parent) : QDialog(parent), @@ -19,13 +20,26 @@ RequestDialog::~RequestDialog() delete ui; } -void RequestDialog::setupDialog(QDialog* d, Ui_RequestDialog* req) { +void RequestDialog::setupDialog(MainWindow* main, QDialog* d, Ui_RequestDialog* req) { req->setupUi(d); Settings::saveRestore(d); // Setup req->txtMemo->setLenDisplayLabel(req->lblMemoLen); req->lblAmount->setText(req->lblAmount->text() + Settings::getTokenName()); + + if (!main || !main->getRPC() || !main->getRPC()->getAllZAddresses() || !main->getRPC()->getAllBalances()) + return; + + for (auto addr : *main->getRPC()->getAllZAddresses()) { + auto bal = main->getRPC()->getAllBalances()->value(addr); + if (bal == 0) + continue; + if (Settings::getInstance()->isSaplingAddress(addr)) { + req->cmbMyAddress->addItem(addr, bal); + } + } + req->cmbMyAddress->setCurrentText(main->getRPC()->getDefaultSaplingAddress()); } // Static method that shows an incoming payment request and prompts the user to pay it @@ -39,7 +53,7 @@ void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI QDialog d(main); Ui_RequestDialog req; - setupDialog(&d, &req); + setupDialog(main, &d, &req); // In the view mode, all fields are read-only req.txtAmount->setReadOnly(true); @@ -60,7 +74,7 @@ void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI req.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Pay")); if (d.exec() == QDialog::Accepted) { - main->payZcashURI(paymentURI); + main->payZcashURI(paymentURI, req.cmbMyAddress->currentText()); } } @@ -68,8 +82,8 @@ void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI void RequestDialog::showRequestZcash(MainWindow* main) { QDialog d(main); Ui_RequestDialog req; - req.setupUi(&d); - Settings::saveRestore(&d); + + setupDialog(main, &d, &req); // Setup the Label completer for the Address req.txtFrom->setCompleter(main->getLabelCompleter()); @@ -104,7 +118,7 @@ void RequestDialog::showRequestZcash(MainWindow* main) { if (d.exec() == QDialog::Accepted) { // Construct a zcash Payment URI with the data and pay it immediately. - QString memoURI = "zcash:" + main->getRPC()->getDefaultSaplingAddress() + QString memoURI = "zcash:" + req.cmbMyAddress->currentText() + "?amt=" + Settings::getDecimalString(req.txtAmount->text().toDouble()) + "&memo=" + QUrl::toPercentEncoding(req.txtMemo->toPlainText()); @@ -113,6 +127,6 @@ void RequestDialog::showRequestZcash(MainWindow* main) { + "&memo=" + QUrl::toPercentEncoding(memoURI); qDebug() << "Paying " << sendURI; - main->payZcashURI(sendURI); + main->payZcashURI(sendURI, req.cmbMyAddress->currentText()); } } diff --git a/src/requestdialog.h b/src/requestdialog.h index a05b3c7..6e53234 100644 --- a/src/requestdialog.h +++ b/src/requestdialog.h @@ -19,7 +19,7 @@ public: static void showRequestZcash(MainWindow* main); static void showPaymentConfirmation(MainWindow* main, QString paymentURI); - static void setupDialog(QDialog* d, Ui_RequestDialog* req); + static void setupDialog(MainWindow* main, QDialog* d, Ui_RequestDialog* req); private: Ui::RequestDialog *ui; }; diff --git a/src/requestdialog.ui b/src/requestdialog.ui index f188f8b..db1a3cc 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -6,29 +6,23 @@ 0 0 - 1052 - 509 + 588 + 384 Payment Request - - - - - + + - Qt::Vertical + Qt::Horizontal - - - 20 - 40 - + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - + @@ -40,16 +34,58 @@ - - + + + + + + + + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + z address + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -60,6 +96,26 @@ + + + + color: red; + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + @@ -67,19 +123,10 @@ - - - - - 0 - 0 - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - z address + + + + Qt::Horizontal @@ -114,26 +161,6 @@
- - - - color: red; - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - - - @@ -151,25 +178,15 @@ - - - - Qt::Horizontal + + + + My Address - - - - Qt::Horizontal - - - - 40 - 20 - - - + + @@ -179,6 +196,11 @@ QPlainTextEdit
memoedit.h
+ + AddressCombo + QComboBox +
addresscombo.h
+
txtFrom diff --git a/src/settings.ui b/src/settings.ui index d026952..f107bd4 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -325,16 +325,6 @@
- - - - Rescan the blockchain for any missing wallet transactions and to correct your wallet balance. This will take several hours. You need to restart ZecWallet for this to take effect - - - true - - - @@ -345,13 +335,6 @@ - - - - Rescan - - - From 3fdbdc5de07bf8531ec411a9995da56fb937e9c6 Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Sat, 23 Mar 2019 10:55:13 -0700 Subject: [PATCH 05/15] Handle 0-balance edge cases --- src/requestdialog.cpp | 11 ++- src/requestdialog.ui | 175 ++++++++++++++++++++++-------------------- 2 files changed, 98 insertions(+), 88 deletions(-) diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index 1adcb75..406d71a 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -33,8 +33,6 @@ void RequestDialog::setupDialog(MainWindow* main, QDialog* d, Ui_RequestDialog* for (auto addr : *main->getRPC()->getAllZAddresses()) { auto bal = main->getRPC()->getAllBalances()->value(addr); - if (bal == 0) - continue; if (Settings::getInstance()->isSaplingAddress(addr)) { req->cmbMyAddress->addItem(addr, bal); } @@ -126,7 +124,12 @@ void RequestDialog::showRequestZcash(MainWindow* main) { + "?amt=0.0001" + "&memo=" + QUrl::toPercentEncoding(memoURI); - qDebug() << "Paying " << sendURI; - main->payZcashURI(sendURI, req.cmbMyAddress->currentText()); + // If the disclosed address in the memo doesn't have a balance, then we can't send the Tx from that address, + QString payFrom = ""; + if (main->getRPC()->getAllBalances()->value(req.cmbMyAddress->currentText()) > 0) { + payFrom = req.cmbMyAddress->currentText(); + } + + main->payZcashURI(sendURI, payFrom); } } diff --git a/src/requestdialog.ui b/src/requestdialog.ui index db1a3cc..d50db6d 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -14,16 +14,6 @@ Payment Request - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -34,46 +24,14 @@ - - - - - - - - - + + Qt::Horizontal - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - z address - - - - - + Qt::Vertical @@ -86,16 +44,6 @@ - - - - 0 / 512 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - @@ -109,26 +57,8 @@ - - - - Qt::Horizontal - - - - - - - Memo - - - - - - - Qt::Horizontal - - + + @@ -161,20 +91,20 @@ - - - - Amount USD + + + + Qt::Horizontal - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + - Amount in + Memo @@ -185,9 +115,86 @@ + + + + Qt::Horizontal + + + + + + + 0 / 512 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + Amount in + + + + + + + Amount USD + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + z address + + + + + + + The recipient will see this address in the "to" field when they pay your request. + + + From 1d483424b8b78c306337aa7770e15170ea455a14 Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Sat, 23 Mar 2019 10:58:05 -0700 Subject: [PATCH 06/15] simplify --- src/requestdialog.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index 406d71a..4023318 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -124,12 +124,8 @@ void RequestDialog::showRequestZcash(MainWindow* main) { + "?amt=0.0001" + "&memo=" + QUrl::toPercentEncoding(memoURI); - // If the disclosed address in the memo doesn't have a balance, then we can't send the Tx from that address, - QString payFrom = ""; - if (main->getRPC()->getAllBalances()->value(req.cmbMyAddress->currentText()) > 0) { - payFrom = req.cmbMyAddress->currentText(); - } - - main->payZcashURI(sendURI, payFrom); + // If the disclosed address in the memo doesn't have a balance, it will automatically fallback to the default + // sapling address + main->payZcashURI(sendURI, req.cmbMyAddress->currentText()); } } From 6a16c257bc2a9999ee99ddaa530d2f43d63bccb6 Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Sat, 23 Mar 2019 15:47:57 -0700 Subject: [PATCH 07/15] Remove address info while paying request --- src/requestdialog.cpp | 3 +++ src/requestdialog.ui | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index 4023318..116745a 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -64,6 +64,9 @@ void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI // No Addressbook req.btnAddressBook->setVisible(false); + // No "address is visible" warning + req.lblAddressInfo->setVisible(false); + req.txtFrom->setText(payInfo.addr); req.txtMemo->setPlainText(payInfo.memo); req.txtAmount->setText(payInfo.amt); diff --git a/src/requestdialog.ui b/src/requestdialog.ui index d50db6d..32ed78f 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -189,7 +189,7 @@ - + The recipient will see this address in the "to" field when they pay your request. From f80cbbb823874bf340cd995d68c004d873affef5 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 25 Mar 2019 14:00:55 -0700 Subject: [PATCH 08/15] 0.6.4 --- README.md | 6 +++--- src/version.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6cc26ce..6331e39 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,14 @@ Head over to the releases page and grab the latest installers or binary. https:/ If you are on Debian/Ubuntu, please download the `.deb` package and install it. ``` -sudo dpkg -i linux-deb-zecwallet-v0.6.3.deb +sudo dpkg -i linux-deb-zecwallet-v0.6.4.deb sudo apt install -f ``` Or you can download and run the binaries directly. ``` -tar -xvf zecwallet-v0.6.3.tar.gz -./zecwallet-v0.6.3/zecwallet +tar -xvf zecwallet-v0.6.4.tar.gz +./zecwallet-v0.6.4/zecwallet ``` ### Windows diff --git a/src/version.h b/src/version.h index 051e94b..6f9b57a 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define APP_VERSION "0.6.3" +#define APP_VERSION "0.6.4" From be924416e6f4424cafe7e5ea70324c9fbb364568 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 25 Mar 2019 15:47:56 -0700 Subject: [PATCH 09/15] Clean up request dialog --- src/requestdialog.ui | 218 +++++++++++++++++++++---------------------- 1 file changed, 109 insertions(+), 109 deletions(-) diff --git a/src/requestdialog.ui b/src/requestdialog.ui index 32ed78f..304303e 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -6,45 +6,63 @@ 0 0 - 588 - 384 + 663 + 529 Payment Request - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - Amount - - + + - + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + AddressBook + + + + + + Qt::Horizontal - - - - Qt::Vertical + + + + Request From - - - 20 - 40 - + + + + + + My Address - + - + color: red; @@ -52,46 +70,23 @@ - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - + + - Request From + Amount in - - - - - - AddressBook - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + + + + - + Qt::Horizontal @@ -101,68 +96,70 @@ - - - - Memo + + + + + 0 + 0 + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + z address - - - - My Address + + + + + 0 + 0 + - + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + Amount + + + + Qt::Horizontal - - - - - + + - 0 / 512 + The recipient will see this address in the "to" field when they pay your request. Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - + + - + 0 / 512 - - - - - - Amount in + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + Amount USD @@ -172,26 +169,30 @@ - - - - - 0 - 0 - + + + + Qt::Vertical - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 20 + 40 + - - z address + + + + + + Memo - - + + - The recipient will see this address in the "to" field when they pay your request. + @@ -210,7 +211,6 @@ - txtFrom txtAmount txtMemo From 5afd6eddea0584c7ef5194409be7fbb6e011c431 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 25 Mar 2019 15:57:50 -0700 Subject: [PATCH 10/15] Include icon --- src/requestdialog.cpp | 3 ++ src/requestdialog.ui | 69 ++++++++++++++++++++++++++++++------------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index 116745a..e0fd53d 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -38,6 +38,9 @@ void RequestDialog::setupDialog(MainWindow* main, QDialog* d, Ui_RequestDialog* } } req->cmbMyAddress->setCurrentText(main->getRPC()->getDefaultSaplingAddress()); + + QIcon icon(":/icons/res/paymentreq.gif"); + req->label_5->setPixmap(icon.pixmap(48, 48)); } // Static method that shows an incoming payment request and prompts the user to pay it diff --git a/src/requestdialog.ui b/src/requestdialog.ui index 304303e..b7ec07e 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -14,10 +14,10 @@ Payment Request - + - + @@ -41,28 +41,28 @@ - + Qt::Horizontal - + Request From - + My Address - + color: red; @@ -72,21 +72,21 @@ - + Amount in - + - + Qt::Horizontal @@ -96,7 +96,14 @@ - + + + + + + + + @@ -112,7 +119,14 @@ - + + + + Qt::Horizontal + + + + @@ -122,7 +136,7 @@ - + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter @@ -132,14 +146,14 @@ - + Qt::Horizontal - + The recipient will see this address in the "to" field when they pay your request. @@ -149,7 +163,7 @@ - + 0 / 512 @@ -159,7 +173,7 @@ - + Amount USD @@ -169,7 +183,7 @@ - + Qt::Vertical @@ -182,17 +196,30 @@ - + Memo - - + + - + TextLabel + + + Qt::AlignCenter + + + + + + + Request payment from a Sapling address. You'll send a ZEC 0.0001 transaction to the address with a zcash payment URI. The memo will be included in the transaction when the address pays you. + + + true From 4ee553c17c88138bfecece2a3c2f95d3022e44c8 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 25 Mar 2019 16:12:42 -0700 Subject: [PATCH 11/15] Edit text for payment response --- src/requestdialog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index e0fd53d..65ab73b 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -77,6 +77,8 @@ void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI req.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Pay")); + req.label_6->setText(tr("You are paying a payment request. Your address will not be visible to the person requesting this payment.")); + if (d.exec() == QDialog::Accepted) { main->payZcashURI(paymentURI, req.cmbMyAddress->currentText()); } From 117fb450590e0b624d0441bda157124cea310c92 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 25 Mar 2019 16:24:59 -0700 Subject: [PATCH 12/15] Cleanup --- src/requestdialog.cpp | 4 ++-- src/requestdialog.ui | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/requestdialog.cpp b/src/requestdialog.cpp index 65ab73b..d2fbfc9 100644 --- a/src/requestdialog.cpp +++ b/src/requestdialog.cpp @@ -40,7 +40,7 @@ void RequestDialog::setupDialog(MainWindow* main, QDialog* d, Ui_RequestDialog* req->cmbMyAddress->setCurrentText(main->getRPC()->getDefaultSaplingAddress()); QIcon icon(":/icons/res/paymentreq.gif"); - req->label_5->setPixmap(icon.pixmap(48, 48)); + req->lblPixmap->setPixmap(icon.pixmap(48, 48)); } // Static method that shows an incoming payment request and prompts the user to pay it @@ -77,7 +77,7 @@ void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI req.buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Pay")); - req.label_6->setText(tr("You are paying a payment request. Your address will not be visible to the person requesting this payment.")); + req.lblHeader->setText(tr("You are paying a payment request. Your address will not be visible to the person requesting this payment.")); if (d.exec() == QDialog::Accepted) { main->payZcashURI(paymentURI, req.cmbMyAddress->currentText()); diff --git a/src/requestdialog.ui b/src/requestdialog.ui index b7ec07e..74e7b9f 100644 --- a/src/requestdialog.ui +++ b/src/requestdialog.ui @@ -204,7 +204,7 @@ - + TextLabel @@ -214,7 +214,7 @@ - + Request payment from a Sapling address. You'll send a ZEC 0.0001 transaction to the address with a zcash payment URI. The memo will be included in the transaction when the address pays you. From 8bfafadf27cc1e7a3c01f1565d66e8a56bb09a9b Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 25 Mar 2019 16:26:58 -0700 Subject: [PATCH 13/15] Signatures to zip file --- src/scripts/signbinaries.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/scripts/signbinaries.sh b/src/scripts/signbinaries.sh index 3a17e21..679b279 100755 --- a/src/scripts/signbinaries.sh +++ b/src/scripts/signbinaries.sh @@ -44,6 +44,7 @@ mv sha256sum-v$APP_VERSION.txt ../release/signatures/ cp ../res/SIGNATURES_README ../release/signatures/README cd ../release/signatures -tar -czf signatures-v$APP_VERSION.tar.gz * -mv signatures-v$APP_VERSION.tar.gz ../../artifacts +#tar -czf signatures-v$APP_VERSION.tar.gz * +zip signatures-v$APP_VERSION.zip * +mv signatures-v$APP_VERSION.zip ../../artifacts From 5b5fc6ee2231d482fe653cf2369b34a413fa14cc Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 28 Mar 2019 15:39:07 -0700 Subject: [PATCH 14/15] Add codesigning --- src/scripts/codesign.sh | 116 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100755 src/scripts/codesign.sh diff --git a/src/scripts/codesign.sh b/src/scripts/codesign.sh new file mode 100755 index 0000000..208c158 --- /dev/null +++ b/src/scripts/codesign.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +# Setup +bold=$(tput bold) +normal=$(tput sgr0) + +# Print the usage and exit +do_help() { + echo "codesign.sh v0.1"; + echo ""; + echo "Sign release binaries with gpg keysigning" + echo ""; + echo "Usage:" + echo "codesign.sh --version [version_id] file [file ...]"; + echo "" + exit 1; +} + +# Print the usage for the version parameter and exit +do_version_missing() { + echo "No release version identifier specified"; + echo "Please specify a release version with ${bold}--version${normal}" + echo + echo "Example:" + echo "./codesign.sh --version 1.4 filename.msi" + exit 1; +} + +# Print the instructions for how to install dependencies +do_missing_command() { + echo "Error: ${bold}$1${normal} was not installed" + echo "" + echo "One or more dependencies are missing. Please install all dependencies by running:" + echo "${bold}brew install gsha256sum gnupg${normal}" + exit 1; +} + +# Print error message for missing private key +do_missing_gpg_key() { + echo "Error: Couldn't find a local private key to sign with." + echo + echo "The command ${bold}gpg -K${normal} didn't return any keys. Did you forget to install the private keys on this machine?" + exit 1; +} + +# Accept the variables as command line arguments as well +POSITIONAL=() +while [[ $# -gt 0 ]] +do +key="$1" + +case $key in + -h|--help) + do_help + ;; + -v|--version) + APP_VERSION="$2" + shift # past argument + shift # past value + ;; + *) # unknown option + POSITIONAL+=("$1") # save it in an array for later + shift # past argument + ;; +esac +done +set -- "${POSITIONAL[@]}" # restore positional parameters + +if [ -z $APP_VERSION ]; then + do_version_missing +fi + +# Check for existance of the gpg and sha256sum commands +hash gsha256sum 2>/dev/null || { + do_missing_command gsha256sum + exit 1; +} + +hash gpg 2>/dev/null || { + do_missing_command gpg + exit 1; +} + +hash zip 2>/dev/null || { + do_missing_command zip + exit 1; +} + +# Check to see that we have a private key installed on this machine +if [[ -z $(gpg -K) ]]; then + do_missing_gpg_key +fi + +PackageContents=() + +# Calculate the sha256sum for all input files +gsha256sum $@ > sha256sum.txt +PackageContents+=("sha256sum.txt") + +# Sign all the files +for var in "$@" +do + rm -f $var.sig + echo "Signing" $var + gpg --batch --output $var.sig --detach-sig $var + PackageContents+=("$var.sig") +done + +# Zip up everything into a neat package +ZipName=signatures-v$APP_VERSION.zip +echo "Zipping files into $ZipName" +rm -f $ZipName +zip $ZipName ${PackageContents[@]} 2>&1 >/dev/null + +# Clean up intermediate files +rm ${PackageContents[@]} \ No newline at end of file From 38e3731beff466b049831a84991960e0fb45d7d6 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 28 Mar 2019 16:30:59 -0700 Subject: [PATCH 15/15] Remove Sprout recieving --- src/mainwindow.cpp | 41 +++-------------------------------------- src/mainwindow.ui | 32 +------------------------------- src/websockets.cpp | 2 +- 3 files changed, 5 insertions(+), 70 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index df635d2..ed4560c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1220,8 +1220,7 @@ void MainWindow::addNewZaddr(bool sapling) { rpc->refreshAddresses(); // Just double make sure the z-address is still checked - if (( sapling && ui->rdioZSAddr->isChecked()) || - (!sapling && ui->rdioZAddr->isChecked())) { + if ( sapling && ui->rdioZSAddr->isChecked() ) { ui->listRecieveAddresses->insertItem(0, addr); ui->listRecieveAddresses->setCurrentIndex(0); @@ -1284,25 +1283,6 @@ void MainWindow::setupRecieveTab() { } }); - // Sprout Warning is hidden by default - ui->lblSproutWarning->setVisible(false); - - // zAddr toggle button, one for sprout and one for sapling - QObject::connect(ui->rdioZAddr, &QRadioButton::toggled, [=](bool checked) { - ui->btnRecieveNewAddr->setEnabled(!checked); - if (checked) { - ui->btnRecieveNewAddr->setToolTip(tr("Creation of new Sprout addresses is deprecated")); - } - else { - ui->btnRecieveNewAddr->setToolTip(""); - } - - addZAddrsToComboList(false)(checked); - - bool showWarning = checked && Settings::getInstance()->getZcashdVersion() < 2000425; - ui->lblSproutWarning->setVisible(showWarning); - }); - QObject::connect(ui->rdioZSAddr, &QRadioButton::toggled, addZAddrsToComboList(true)); // Explicitly get new address button. @@ -1310,16 +1290,7 @@ void MainWindow::setupRecieveTab() { if (!rpc->getConnection()) return; - if (ui->rdioZAddr->isChecked()) { - QString syncMsg = !Settings::getInstance()->isSaplingActive() ? "Please wait for your node to finish syncing to create Sapling addresses.\n\n" : ""; - auto confirm = QMessageBox::question(this, "Sprout Address", - syncMsg + "Sprout addresses are inefficient, and will be deprecated in the future in favour of Sapling addresses.\n" - "Are you sure you want to create a new Sprout address?", QMessageBox::Yes, QMessageBox::No); - if (confirm != QMessageBox::Yes) - return; - - addNewZaddr(false); - } else if (ui->rdioZSAddr->isChecked()) { + if (ui->rdioZSAddr->isChecked()) { addNewZaddr(true); } else if (ui->rdioTAddr->isChecked()) { addNewTAddr(); @@ -1333,14 +1304,8 @@ void MainWindow::setupRecieveTab() { // Hide Sapling radio button if Sapling is not active if (Settings::getInstance()->isSaplingActive()) { - ui->rdioZSAddr->setVisible(true); ui->rdioZSAddr->setChecked(true); - ui->rdioZAddr->setText("z-Addr(Legacy Sprout)"); - } else { - ui->rdioZSAddr->setVisible(false); - ui->rdioZAddr->setChecked(true); - ui->rdioZAddr->setText("z-Addr"); // Don't use the "Sprout" label if there's no Sapling - } + } // And then select the first one ui->listRecieveAddresses->setCurrentIndex(0); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 718a2bf..e0e7a31 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -22,7 +22,7 @@ - 1 + 2 @@ -697,13 +697,6 @@ - - - - z-Addr(Legacy Sprout) - - - @@ -730,28 +723,6 @@ - - - - color: red; - - - <html><head/><body><p>You should suspend trust in the receipt of funds to Sprout z-addresses until you upgrade to zcashd v2.0.4. See <a href="https://z.cash/support/security/announcements/security-announcement-2019-03-19/"><span style=" text-decoration: underline; color:#0000ff;">Security Announcement</span></a>.</p></body></html> - - - Qt::RichText - - - true - - - true - - - Qt::TextBrowserInteraction - - - @@ -1221,7 +1192,6 @@ cancelSendButton rdioZSAddr rdioTAddr - rdioZAddr listRecieveAddresses btnRecieveNewAddr txtRecieve diff --git a/src/websockets.cpp b/src/websockets.cpp index ccfd42c..19af1b2 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -12,7 +12,7 @@ WSServer::WSServer(quint16 port, bool debug, QObject *parent) : m_debug(debug) { m_mainWindow = (MainWindow *) parent; - if (m_pWebSocketServer->listen(QHostAddress::AnyIPv4, port)) { + if (m_pWebSocketServer->listen(QHostAddress::AnyIPv4, port+100)) { if (m_debug) qDebug() << "Echoserver listening on port" << port; connect(m_pWebSocketServer, &QWebSocketServer::newConnection,