diff --git a/CMakeLists.txt b/CMakeLists.txt index 01e3cfc..821a90b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ if(DEBUG) set(CMAKE_VERBOSE_MAKEFILE ON) endif() -set(MONERO_HEAD "a6bf6dbb8f1637ccffee1a30d2285324a3ce4d66") +set(MONERO_HEAD "9ca5569f40a392b16946c5c3bda312eecfdcc9ab") set(BUILD_GUI_DEPS ON) set(ARCH "x86-64") set(BUILD_64 ON) diff --git a/monero b/monero index a6bf6db..9ca5569 160000 --- a/monero +++ b/monero @@ -1 +1 @@ -Subproject commit a6bf6dbb8f1637ccffee1a30d2285324a3ce4d66 +Subproject commit 9ca5569f40a392b16946c5c3bda312eecfdcc9ab diff --git a/src/dialog/transactioninfodialog.cpp b/src/dialog/transactioninfodialog.cpp index 3428181..f8b60be 100644 --- a/src/dialog/transactioninfodialog.cpp +++ b/src/dialog/transactioninfodialog.cpp @@ -6,7 +6,9 @@ #include "libwalletqt/CoinsInfo.h" #include "libwalletqt/WalletManager.h" -#include +#include "utils.h" + +#include TransactionInfoDialog::TransactionInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent) : QDialog(parent) @@ -16,6 +18,8 @@ TransactionInfoDialog::TransactionInfoDialog(Wallet *wallet, TransactionInfo *tx { ui->setupUi(this); + m_txProofWidget = new TxProofWidget(this, wallet, txInfo); + ui->label_txid->setText(QString(txInfo->hash())); if (txInfo->direction() == TransactionInfo::Direction_In) { @@ -48,6 +52,8 @@ TransactionInfoDialog::TransactionInfoDialog(Wallet *wallet, TransactionInfo *tx ui->destinations->setText(destinations); } + ui->txProofWidget->addWidget(m_txProofWidget); + this->adjustSize(); } diff --git a/src/dialog/transactioninfodialog.h b/src/dialog/transactioninfodialog.h index bf0fbb9..3426a87 100644 --- a/src/dialog/transactioninfodialog.h +++ b/src/dialog/transactioninfodialog.h @@ -9,6 +9,7 @@ #include "libwalletqt/Coins.h" #include "libwalletqt/TransactionInfo.h" #include "libwalletqt/Wallet.h" +#include "widgets/txproofwidget.h" namespace Ui { class TransactionInfoDialog; @@ -27,6 +28,7 @@ private: TransactionInfo *m_txInfo; Wallet *m_wallet; + TxProofWidget *m_txProofWidget; }; #endif //FEATHER_TRANSACTIONINFODIALOG_H diff --git a/src/dialog/transactioninfodialog.ui b/src/dialog/transactioninfodialog.ui index 7282027..cee67a1 100644 --- a/src/dialog/transactioninfodialog.ui +++ b/src/dialog/transactioninfodialog.ui @@ -6,8 +6,8 @@ 0 0 - 547 - 436 + 829 + 570 @@ -158,6 +158,16 @@ + + + + Qt::Horizontal + + + + + + diff --git a/src/libwalletqt/TransactionInfo.cpp b/src/libwalletqt/TransactionInfo.cpp index 3352198..19e7fd1 100644 --- a/src/libwalletqt/TransactionInfo.cpp +++ b/src/libwalletqt/TransactionInfo.cpp @@ -28,6 +28,11 @@ bool TransactionInfo::isCoinbase() const return m_coinbase; } +quint64 TransactionInfo::balanceDelta() const +{ + return m_amount + m_fee; +} + double TransactionInfo::amount() const { // there's no unsigned uint64 for JS, so better use double @@ -44,6 +49,11 @@ QString TransactionInfo::displayAmount() const return WalletManager::displayAmount(m_amount); } +quint64 TransactionInfo::atomicFee() const +{ + return m_fee; +} + QString TransactionInfo::fee() const { if(m_fee == 0) @@ -127,6 +137,15 @@ QString TransactionInfo::destinations_formatted() const return destinations; } +QList TransactionInfo::destinations() const +{ + QList dests; + for (auto const& t: m_transfers) { + dests.append(t->address()); + } + return dests; +} + QString TransactionInfo::rings_formatted() const { QString rings; diff --git a/src/libwalletqt/TransactionInfo.h b/src/libwalletqt/TransactionInfo.h index 98dece9..63709e8 100644 --- a/src/libwalletqt/TransactionInfo.h +++ b/src/libwalletqt/TransactionInfo.h @@ -52,10 +52,12 @@ public: bool isPending() const; bool isFailed() const; bool isCoinbase() const; + quint64 balanceDelta() const; double amount() const; quint64 atomicAmount() const; QString displayAmount() const; QString fee() const; + quint64 atomicFee() const; quint64 blockHeight() const; QString description() const; QSet subaddrIndex() const; @@ -72,6 +74,7 @@ public: QString paymentId() const; //! only applicable for output transactions //! used in tx details popup + QList destinations() const; QString destinations_formatted() const; QString rings_formatted() const; diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index cac888d..40d6dbe 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -792,12 +792,10 @@ QString Wallet::checkTxKey(const QString &txid, const QString &tx_key, const QSt return QString::fromStdString(result); } -QString Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const +TxProof Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const { std::string result = m_walletImpl->getTxProof(txid.toStdString(), address.toStdString(), message.toStdString()); - if (result.empty()) - result = "error|" + m_walletImpl->errorString(); - return QString::fromStdString(result); + return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString())); } //void Wallet::getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback) @@ -817,12 +815,10 @@ TxProofResult Wallet::checkTxProof(const QString &txid, const QString &address, return {success, good, received, in_pool, confirmations}; } -Q_INVOKABLE QString Wallet::getSpendProof(const QString &txid, const QString &message) const +Q_INVOKABLE TxProof Wallet::getSpendProof(const QString &txid, const QString &message) const { std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString()); - if (result.empty()) - result = "error|" + m_walletImpl->errorString(); - return QString::fromStdString(result); + return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString())); } //void Wallet::getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback) diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 010009d..d770045 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -22,6 +22,13 @@ namespace Monero { struct Wallet; // forward declaration } +struct TxProof { + TxProof(QString proof, QString error = "") + : proof(std::move(proof)), error(std::move(error)){} + + QString proof; + QString error; +}; class TransactionHistory; class TransactionHistoryModel; @@ -336,11 +343,11 @@ public: Q_INVOKABLE QString getTxKey(const QString &txid) const; //Q_INVOKABLE void getTxKeyAsync(const QString &txid, const QJSValue &callback); Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address); - Q_INVOKABLE QString getTxProof(const QString &txid, const QString &address, const QString &message) const; + Q_INVOKABLE TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const; // Q_INVOKABLE void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback); //Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); Q_INVOKABLE TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); - Q_INVOKABLE QString getSpendProof(const QString &txid, const QString &message) const; + Q_INVOKABLE TxProof getSpendProof(const QString &txid, const QString &message) const; // Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback); Q_INVOKABLE QPair checkSpendProof(const QString &txid, const QString &message, const QString &signature) const; // Rescan spent outputs diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 729711b..d6d5149 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -302,8 +302,8 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : // History connect(ui->historyWidget, &HistoryWidget::spendProof, [&](const QString &txid){ - QString spendProof = m_ctx->currentWallet->getSpendProof(txid, ""); - Utils::copyToClipboard(spendProof); + TxProof txproof = m_ctx->currentWallet->getSpendProof(txid, ""); + Utils::copyToClipboard(txproof.proof); }); connect(ui->historyWidget, &HistoryWidget::viewOnBlockExplorer, this, &MainWindow::onViewOnBlockExplorer); diff --git a/src/model/TransactionHistoryModel.cpp b/src/model/TransactionHistoryModel.cpp index 969dae7..254d30f 100644 --- a/src/model/TransactionHistoryModel.cpp +++ b/src/model/TransactionHistoryModel.cpp @@ -119,7 +119,7 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const case Column::FiatAmount: case Column::Amount: { - if (tInfo.direction() == TransactionInfo::Direction_Out && tInfo.amount() > 0) { + if (tInfo.direction() == TransactionInfo::Direction_Out) { result = QVariant(QColor("#BC1E1E")); } } @@ -152,8 +152,8 @@ QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionInfo &tI } case Column::Amount: { - QString amount = QString::number(tInfo.atomicAmount() / globals::cdiv, 'f', 4); - amount = (tInfo.direction() == TransactionInfo::Direction_Out && tInfo.amount() > 0) ? "-" + amount : "+" + amount; + QString amount = QString::number(tInfo.balanceDelta() / globals::cdiv, 'f', 4); + amount = (tInfo.direction() == TransactionInfo::Direction_Out) ? "-" + amount : "+" + amount; return amount; } case Column::TxID: @@ -164,7 +164,7 @@ QVariant TransactionHistoryModel::parseTransactionInfo(const TransactionInfo &tI if (usd_price == 0.0) return QVariant("?"); - double usd_amount = usd_price * tInfo.amount(); + double usd_amount = usd_price * (tInfo.balanceDelta() / globals::cdiv); if(this->preferredFiatSymbol != "USD") usd_amount = AppContext::prices->convert("USD", this->preferredFiatSymbol, usd_amount); double fiat_rounded = ceil(Utils::roundSignificant(usd_amount, 3) * 100.0) / 100.0; diff --git a/src/widgets/txproofwidget.cpp b/src/widgets/txproofwidget.cpp new file mode 100644 index 0000000..81178cd --- /dev/null +++ b/src/widgets/txproofwidget.cpp @@ -0,0 +1,61 @@ +#include "txproofwidget.h" +#include "ui_txproofwidget.h" + +#include +#include + +#include "utils/utils.h" + +TxProofWidget::TxProofWidget(QWidget *parent, Wallet *wallet, TransactionInfo *txInfo) + : QWidget(parent) + , ui(new Ui::TxProofWidget) + , m_wallet(wallet) + , m_txid(txInfo->hash()) +{ + ui->setupUi(this); + + if (txInfo->direction() == TransactionInfo::Direction_Out) { + for (auto const &d: txInfo->destinations()) { + ui->comboBox_TxProofAddresses->addItem(d); + } + } else { + ui->btn_copySpendProof->setEnabled(false); + + for (auto const &s: txInfo->subaddrIndex()) { + ui->comboBox_TxProofAddresses->addItem(wallet->address(txInfo->subaddrAccount(), s)); + } + } + + if (ui->comboBox_TxProofAddresses->count() == 0) { + ui->btn_copyTxProof->setEnabled(false); + } + + connect(ui->btn_copySpendProof, &QPushButton::clicked, this, &TxProofWidget::copySpendProof); + connect(ui->btn_copyTxProof, &QPushButton::clicked, this, &TxProofWidget::copyTxProof); +} + +void TxProofWidget::copySpendProof() { + auto txproof = m_wallet->getSpendProof(m_txid, ""); + if (!txproof.error.isEmpty()) { + QMessageBox::warning(this, "Copy SpendProof", QString("Failed to copy SpendProof").arg(txproof.error)); + return; + } + + Utils::copyToClipboard(txproof.proof); + QMessageBox::information(this, "Copy SpendProof", "SpendProof copied to clipboard"); +} + +void TxProofWidget::copyTxProof() { + auto txproof = m_wallet->getTxProof(m_txid, ui->comboBox_TxProofAddresses->currentText(), ""); + if (!txproof.error.isEmpty()) { + QMessageBox::warning(this, "Copy Transaction Proof", QString("Failed to copy transaction proof: %1").arg(txproof.error)); + return; + } + + Utils::copyToClipboard(txproof.proof); + QMessageBox::information(this, "Copy Transaction Proof", "Transaction proof copied to clipboard"); +} + +TxProofWidget::~TxProofWidget() { + delete ui; +} diff --git a/src/widgets/txproofwidget.h b/src/widgets/txproofwidget.h new file mode 100644 index 0000000..f6c5358 --- /dev/null +++ b/src/widgets/txproofwidget.h @@ -0,0 +1,30 @@ +#ifndef FEATHER_TXPROOFWIDGET_H +#define FEATHER_TXPROOFWIDGET_H + +#include + +#include "libwalletqt/Wallet.h" +#include "libwalletqt/TransactionInfo.h" + +namespace Ui { + class TxProofWidget; +} + +class TxProofWidget : public QWidget +{ +Q_OBJECT + +public: + explicit TxProofWidget(QWidget *parent, Wallet *wallet, TransactionInfo *txid); + ~TxProofWidget() override; + +private: + void copySpendProof(); + void copyTxProof(); + + Ui::TxProofWidget *ui; + QString m_txid; + Wallet *m_wallet; +}; + +#endif //FEATHER_TXPROOFWIDGET_H diff --git a/src/widgets/txproofwidget.ui b/src/widgets/txproofwidget.ui new file mode 100644 index 0000000..91f1efc --- /dev/null +++ b/src/widgets/txproofwidget.ui @@ -0,0 +1,103 @@ + + + TxProofWidget + + + + 0 + 0 + 647 + 79 + + + + + 0 + 0 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 0 + 0 + + + + Copy + + + + + + + SpendProof + + + + + + + + + + + + 0 + 0 + + + + Copy + + + + + + + + 0 + 0 + + + + In/OutProof + + + + + + + + 0 + 0 + + + + + + + + + + +