Skip to content

Commit

Permalink
Pay payment requests
Browse files Browse the repository at this point in the history
  • Loading branch information
adityapk00 committed Mar 22, 2019
1 parent c70819b commit e46725f
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 120 deletions.
1 change: 1 addition & 0 deletions application.qrc
Expand Up @@ -5,6 +5,7 @@
<qresource prefix="/icons">
<file>res/connected.gif</file>
<file>res/loading.gif</file>
<file>res/paymentreq.gif</file>
<file>res/icon.ico</file>
</qresource>
<qresource prefix="/img">
Expand Down
Binary file added res/paymentreq.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
81 changes: 17 additions & 64 deletions src/mainwindow.cpp
Expand Up @@ -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:<addr>?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"),
Expand All @@ -820,78 +814,29 @@ 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:<addr>?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);
raise();

// 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();
}
}
Expand Down Expand Up @@ -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();
Expand Down
61 changes: 58 additions & 3 deletions src/requestdialog.cpp
Expand Up @@ -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),
Expand All @@ -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:<addr>?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);
Expand Down Expand Up @@ -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);
}
}
}
4 changes: 3 additions & 1 deletion src/requestdialog.h
Expand Up @@ -3,6 +3,7 @@

#include <QDialog>
#include "mainwindow.h"
#include "ui_requestdialog.h"

namespace Ui {
class RequestDialog;
Expand All @@ -17,7 +18,8 @@ class RequestDialog : public QDialog
~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;
};
Expand Down

0 comments on commit e46725f

Please sign in to comment.