mirror of
				https://git.wownero.com/wowlet/wowlet.git
				synced 2024-08-15 01:03:14 +00:00 
			
		
		
		
	Merge pull request 'Offline transaction signing' (#88) from tobtoht/feather:offline_tx_signing into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/88 Reviewed-by: dsc <dsc@noreply.gitgud.wownero.nl>
This commit is contained in:
		
						commit
						24993bc0b2
					
				
					 35 changed files with 1334 additions and 52 deletions
				
			
		| 
						 | 
				
			
			@ -30,7 +30,7 @@ if(DEBUG)
 | 
			
		|||
    set(CMAKE_VERBOSE_MAKEFILE ON)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
set(MONERO_HEAD "f6587d7943a19c55a5b78af1a89b22c130513b73")
 | 
			
		||||
set(MONERO_HEAD "c2b7b50fdea2e66a593f9c9109ebd742f69ad9d1")
 | 
			
		||||
set(BUILD_GUI_DEPS ON)
 | 
			
		||||
set(ARCH "x86-64")
 | 
			
		||||
set(BUILD_64 ON)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								monero
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								monero
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
Subproject commit f6587d7943a19c55a5b78af1a89b22c130513b73
 | 
			
		||||
Subproject commit c2b7b50fdea2e66a593f9c9109ebd742f69ad9d1
 | 
			
		||||
							
								
								
									
										62
									
								
								src/dialog/broadcasttxdialog.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/dialog/broadcasttxdialog.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#include "broadcasttxdialog.h"
 | 
			
		||||
#include "ui_broadcasttxdialog.h"
 | 
			
		||||
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx)
 | 
			
		||||
        : QDialog(parent)
 | 
			
		||||
        , m_ctx(ctx)
 | 
			
		||||
        , ui(new Ui::BroadcastTxDialog)
 | 
			
		||||
{
 | 
			
		||||
    ui->setupUi(this);
 | 
			
		||||
 | 
			
		||||
    m_network = new UtilsNetworking(m_ctx->network, this);
 | 
			
		||||
 | 
			
		||||
    auto node = ctx->nodes->connection();
 | 
			
		||||
    m_rpc = new DaemonRpc(this, m_network, node.full);
 | 
			
		||||
 | 
			
		||||
    connect(ui->btn_Broadcast, &QPushButton::clicked, this, &BroadcastTxDialog::broadcastTx);
 | 
			
		||||
    connect(ui->btn_Close, &QPushButton::clicked, this, &BroadcastTxDialog::reject);
 | 
			
		||||
 | 
			
		||||
    connect(m_rpc, &DaemonRpc::ApiResponse, this, &BroadcastTxDialog::onApiResponse);
 | 
			
		||||
 | 
			
		||||
    this->adjustSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BroadcastTxDialog::broadcastTx() {
 | 
			
		||||
    QString tx = ui->transaction->toPlainText();
 | 
			
		||||
 | 
			
		||||
    QString node = [this]{
 | 
			
		||||
        QString node;
 | 
			
		||||
        if (ui->radio_useCustom->isChecked())
 | 
			
		||||
            node = ui->customNode->text();
 | 
			
		||||
        else
 | 
			
		||||
            node = m_ctx->nodes->connection().full;
 | 
			
		||||
 | 
			
		||||
        if (!node.startsWith("http://"))
 | 
			
		||||
            node = QString("http://%1").arg(node);
 | 
			
		||||
        return node;
 | 
			
		||||
    }();
 | 
			
		||||
 | 
			
		||||
    m_rpc->setDaemonAddress(node);
 | 
			
		||||
    m_rpc->sendRawTransaction(tx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BroadcastTxDialog::onApiResponse(const DaemonRpc::DaemonResponse &resp) {
 | 
			
		||||
    if (!resp.ok) {
 | 
			
		||||
        QMessageBox::warning(this, "Transaction broadcast", resp.status);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (resp.endpoint == DaemonRpc::Endpoint::SEND_RAW_TRANSACTION) {
 | 
			
		||||
        QMessageBox::information(this, "Transaction broadcast", "Transaction submitted successfully.\n\n"
 | 
			
		||||
                                                      "If the transaction belongs to this wallet it may take several minutes before it shows up in the history tab.");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BroadcastTxDialog::~BroadcastTxDialog() {
 | 
			
		||||
    delete ui;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								src/dialog/broadcasttxdialog.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/dialog/broadcasttxdialog.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_BROADCASTTXDIALOG_H
 | 
			
		||||
#define FEATHER_BROADCASTTXDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include "appcontext.h"
 | 
			
		||||
#include "utils/daemonrpc.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
    class BroadcastTxDialog;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class BroadcastTxDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit BroadcastTxDialog(QWidget *parent, AppContext *ctx);
 | 
			
		||||
    ~BroadcastTxDialog() override;
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void broadcastTx();
 | 
			
		||||
    void onApiResponse(const DaemonRpc::DaemonResponse &resp);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Ui::BroadcastTxDialog *ui;
 | 
			
		||||
    UtilsNetworking *m_network;
 | 
			
		||||
    AppContext *m_ctx;
 | 
			
		||||
    DaemonRpc *m_rpc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_BROADCASTTXDIALOG_H
 | 
			
		||||
							
								
								
									
										111
									
								
								src/dialog/broadcasttxdialog.ui
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								src/dialog/broadcasttxdialog.ui
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,111 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<ui version="4.0">
 | 
			
		||||
 <class>BroadcastTxDialog</class>
 | 
			
		||||
 <widget class="QDialog" name="BroadcastTxDialog">
 | 
			
		||||
  <property name="geometry">
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>797</width>
 | 
			
		||||
    <height>575</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>Broadcast transaction</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLabel" name="label">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
      <string>Transaction:</string>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QPlainTextEdit" name="transaction">
 | 
			
		||||
     <property name="minimumSize">
 | 
			
		||||
      <size>
 | 
			
		||||
       <width>500</width>
 | 
			
		||||
       <height>0</height>
 | 
			
		||||
      </size>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="placeholderText">
 | 
			
		||||
      <string>Paste hex encoded signed tx string here</string>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QGroupBox" name="groupBox">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Node</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <layout class="QVBoxLayout" name="verticalLayout_2">
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QRadioButton" name="radio_useDefault">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Use currently connected node</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="checked">
 | 
			
		||||
         <bool>true</bool>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QRadioButton" name="radio_useCustom">
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>Use custom node</string>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLineEdit" name="customNode"/>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLabel" name="label_2">
 | 
			
		||||
     <property name="enabled">
 | 
			
		||||
      <bool>false</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="text">
 | 
			
		||||
      <string>All transactions are broadcast over Tor</string>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
     <item>
 | 
			
		||||
      <spacer name="horizontalSpacer">
 | 
			
		||||
       <property name="orientation">
 | 
			
		||||
        <enum>Qt::Horizontal</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="sizeHint" stdset="0">
 | 
			
		||||
        <size>
 | 
			
		||||
         <width>40</width>
 | 
			
		||||
         <height>20</height>
 | 
			
		||||
        </size>
 | 
			
		||||
       </property>
 | 
			
		||||
      </spacer>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QPushButton" name="btn_Broadcast">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Broadcast</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QPushButton" name="btn_Close">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Close</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <resources/>
 | 
			
		||||
 <connections/>
 | 
			
		||||
</ui>
 | 
			
		||||
| 
						 | 
				
			
			@ -9,15 +9,14 @@
 | 
			
		|||
#include <QFileDialog>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
QrCodeDialog::QrCodeDialog(QWidget *parent, const QString &text, const QString &title)
 | 
			
		||||
QrCodeDialog::QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title)
 | 
			
		||||
        : QDialog(parent)
 | 
			
		||||
        , ui(new Ui::QrCodeDialog)
 | 
			
		||||
{
 | 
			
		||||
    ui->setupUi(this);
 | 
			
		||||
    this->setWindowTitle(title);
 | 
			
		||||
 | 
			
		||||
    m_qrc = new QrCode(text, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
 | 
			
		||||
    m_pixmap = m_qrc->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
 | 
			
		||||
    m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
 | 
			
		||||
    ui->QrCode->setPixmap(m_pixmap);
 | 
			
		||||
 | 
			
		||||
    connect(ui->btn_CopyImage, &QPushButton::clicked, this, &QrCodeDialog::copyImage);
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +31,11 @@ QrCodeDialog::QrCodeDialog(QWidget *parent, const QString &text, const QString &
 | 
			
		|||
QrCodeDialog::~QrCodeDialog()
 | 
			
		||||
{
 | 
			
		||||
    delete ui;
 | 
			
		||||
    delete m_qrc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QrCodeDialog::setQrCode(const QrCode &qrCode) {
 | 
			
		||||
    m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
 | 
			
		||||
    ui->QrCode->setPixmap(m_pixmap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QrCodeDialog::copyImage() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,15 +16,15 @@ class QrCodeDialog : public QDialog
 | 
			
		|||
Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit QrCodeDialog(QWidget *parent, const QString &text, const QString &title = "Qr Code");
 | 
			
		||||
    explicit QrCodeDialog(QWidget *parent, const QrCode &qrCode, const QString &title = "Qr Code");
 | 
			
		||||
    ~QrCodeDialog() override;
 | 
			
		||||
    void setQrCode(const QrCode &qrCode);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void copyImage();
 | 
			
		||||
    void saveImage();
 | 
			
		||||
 | 
			
		||||
    Ui::QrCodeDialog *ui;
 | 
			
		||||
    QrCode *m_qrc;
 | 
			
		||||
    QPixmap m_pixmap;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										186
									
								
								src/dialog/txconfadvdialog.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								src/dialog/txconfadvdialog.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,186 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#include "txconfadvdialog.h"
 | 
			
		||||
#include "ui_txconfadvdialog.h"
 | 
			
		||||
#include "libwalletqt/WalletManager.h"
 | 
			
		||||
#include "qrcode/QrCode.h"
 | 
			
		||||
#include "dialog/qrcodedialog.h"
 | 
			
		||||
#include "utils/utils.h"
 | 
			
		||||
#include "libwalletqt/PendingTransactionInfo.h"
 | 
			
		||||
#include "libwalletqt/Transfer.h"
 | 
			
		||||
#include "libwalletqt/Input.h"
 | 
			
		||||
#include "model/ModelUtils.h"
 | 
			
		||||
 | 
			
		||||
#include <QFileDialog>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
TxConfAdvDialog::TxConfAdvDialog(AppContext *ctx, const QString &description, QWidget *parent)
 | 
			
		||||
        : QDialog(parent)
 | 
			
		||||
        , ui(new Ui::TxConfAdvDialog)
 | 
			
		||||
        , m_ctx(ctx)
 | 
			
		||||
        , m_exportUnsignedMenu(new QMenu(this))
 | 
			
		||||
        , m_exportSignedMenu(new QMenu(this))
 | 
			
		||||
{
 | 
			
		||||
    ui->setupUi(this);
 | 
			
		||||
 | 
			
		||||
    m_exportUnsignedMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::unsignedCopy);
 | 
			
		||||
    m_exportUnsignedMenu->addAction("Show as QR code", this, &TxConfAdvDialog::unsignedQrCode);
 | 
			
		||||
    m_exportUnsignedMenu->addAction("Save to file", this, &TxConfAdvDialog::unsignedSaveFile);
 | 
			
		||||
    ui->btn_exportUnsigned->setMenu(m_exportUnsignedMenu);
 | 
			
		||||
 | 
			
		||||
    m_exportSignedMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::signedCopy);
 | 
			
		||||
    m_exportSignedMenu->addAction("Save to file", this, &TxConfAdvDialog::signedSaveFile);
 | 
			
		||||
    ui->btn_exportSigned->setMenu(m_exportSignedMenu);
 | 
			
		||||
 | 
			
		||||
    if (m_ctx->currentWallet->viewOnly()) {
 | 
			
		||||
        ui->btn_exportSigned->hide();
 | 
			
		||||
        ui->btn_send->hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ui->label_description->setText(QString("Description: %1").arg(description));
 | 
			
		||||
 | 
			
		||||
    connect(ui->btn_sign, &QPushButton::clicked, this, &TxConfAdvDialog::signTransaction);
 | 
			
		||||
    connect(ui->btn_send, &QPushButton::clicked, this, &TxConfAdvDialog::broadcastTransaction);
 | 
			
		||||
    connect(ui->btn_close, &QPushButton::clicked, this, &TxConfAdvDialog::closeDialog);
 | 
			
		||||
 | 
			
		||||
    ui->inputs->setFont(ModelUtils::getMonospaceFont());
 | 
			
		||||
    ui->outputs->setFont(ModelUtils::getMonospaceFont());
 | 
			
		||||
 | 
			
		||||
    this->adjustSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::setTransaction(PendingTransaction *tx) {
 | 
			
		||||
    ui->btn_sign->hide();
 | 
			
		||||
 | 
			
		||||
    m_tx = tx;
 | 
			
		||||
    m_tx->refresh();
 | 
			
		||||
    PendingTransactionInfo *ptx = m_tx->transaction(0);
 | 
			
		||||
 | 
			
		||||
    ui->txid->setText(tx->txid().first());
 | 
			
		||||
 | 
			
		||||
    ui->amount->setText(WalletManager::displayAmount(tx->amount()));
 | 
			
		||||
    ui->fee->setText(WalletManager::displayAmount(ptx->fee()));
 | 
			
		||||
    ui->total->setText(WalletManager::displayAmount(tx->amount() + ptx->fee()));
 | 
			
		||||
 | 
			
		||||
    auto size_str = [this]{
 | 
			
		||||
        if (m_ctx->currentWallet->viewOnly()) {
 | 
			
		||||
            return QString("Size: %1 bytes (unsigned)").arg(QString::number(m_tx->unsignedTxToBin().size()));
 | 
			
		||||
        } else {
 | 
			
		||||
            auto size = m_tx->signedTxToHex(0).size() / 2;
 | 
			
		||||
            return QString("Size: %1 bytes (%2 bytes unsigned)").arg(QString::number(size), QString::number(m_tx->unsignedTxToBin().size()));
 | 
			
		||||
        }
 | 
			
		||||
    }();
 | 
			
		||||
    ui->label_size->setText(size_str);
 | 
			
		||||
 | 
			
		||||
    this->setupConstructionData(ptx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::setUnsignedTransaction(UnsignedTransaction *utx) {
 | 
			
		||||
    m_utx = utx;
 | 
			
		||||
    m_utx->refresh();
 | 
			
		||||
 | 
			
		||||
    ui->btn_exportUnsigned->hide();
 | 
			
		||||
    ui->btn_exportSigned->hide();
 | 
			
		||||
    ui->btn_sign->show();
 | 
			
		||||
    ui->btn_send->hide();
 | 
			
		||||
 | 
			
		||||
    ui->txid->setText("n/a");
 | 
			
		||||
    ui->label_size->setText("Size: n/a");
 | 
			
		||||
 | 
			
		||||
    ui->amount->setText(WalletManager::displayAmount(utx->amount(0)));
 | 
			
		||||
    ui->fee->setText(WalletManager::displayAmount(utx->fee(0)));
 | 
			
		||||
    ui->total->setText(WalletManager::displayAmount(utx->amount(0) + utx->fee(0)));
 | 
			
		||||
 | 
			
		||||
    ConstructionInfo *ci = m_utx->constructionInfo(0);
 | 
			
		||||
    this->setupConstructionData(ci);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
 | 
			
		||||
    QString inputs_str;
 | 
			
		||||
    auto inputs = ci->inputs();
 | 
			
		||||
    for (const auto& i: inputs) {
 | 
			
		||||
        inputs_str += QString("%1 %2\n").arg(i->pubKey(), WalletManager::displayAmount(i->amount()));
 | 
			
		||||
    }
 | 
			
		||||
    ui->inputs->setText(inputs_str);
 | 
			
		||||
    ui->label_inputs->setText(QString("Inputs (%1)").arg(QString::number(inputs.size())));
 | 
			
		||||
 | 
			
		||||
    QString outputs_str;
 | 
			
		||||
    auto outputs = ci->outputs();
 | 
			
		||||
    for (const auto& o: outputs) {
 | 
			
		||||
        outputs_str += QString("%1 %2\n").arg(o->address(), WalletManager::displayAmount(o->amount()));
 | 
			
		||||
    }
 | 
			
		||||
    ui->outputs->setText(outputs_str);
 | 
			
		||||
    ui->label_outputs->setText(QString("Outputs (%1)").arg(QString::number(outputs.size())));
 | 
			
		||||
 | 
			
		||||
    ui->label_ringSize->setText(QString("Ring size: %1").arg(QString::number(ci->minMixinCount() + 1)));
 | 
			
		||||
    ui->label_unlockTime->setText(QString("Unlock time: %1 (height)").arg(QString::number(ci->unlockTime())));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::signTransaction() {
 | 
			
		||||
    QString defaultName = QString("%1_signed_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
 | 
			
		||||
    QString fn = QFileDialog::getSaveFileName(this, "Save signed transaction to file", QDir::home().filePath(defaultName), "Transaction (*signed_monero_tx)");
 | 
			
		||||
    if(fn.isEmpty()) return;
 | 
			
		||||
 | 
			
		||||
    m_utx->sign(fn) ? QMessageBox::information(this, "Sign transaction", "Transaction saved successfully")
 | 
			
		||||
                    : QMessageBox::warning(this, "Sign transaction", "Failes to save transaction to file.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::unsignedSaveFile() {
 | 
			
		||||
    QString defaultName = QString("%1_unsigned_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
 | 
			
		||||
    QString fn = QFileDialog::getSaveFileName(this, "Save transaction to file", QDir::home().filePath(defaultName), "Transaction (*unsigned_monero_tx)");
 | 
			
		||||
    if(fn.isEmpty()) return;
 | 
			
		||||
 | 
			
		||||
    m_tx->saveToFile(fn) ? QMessageBox::information(this, "Transaction saved to file", "Transaction saved successfully")
 | 
			
		||||
                         : QMessageBox::warning(this, "Save transaction", "Failed to save transaction to file.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::signedSaveFile() {
 | 
			
		||||
    QString defaultName = QString("%1_signed_monero_tx").arg(QString::number(QDateTime::currentSecsSinceEpoch()));
 | 
			
		||||
    QString fn = QFileDialog::getSaveFileName(this, "Save transaction to file", QDir::home().filePath(defaultName), "Transaction (*signed_monero_tx)");
 | 
			
		||||
    if(fn.isEmpty()) return;
 | 
			
		||||
 | 
			
		||||
    m_tx->saveToFile(fn) ? QMessageBox::information(this, "Transaction saved to file", "Transaction saved successfully")
 | 
			
		||||
                         : QMessageBox::warning(this, "Save transaction", "Failed to save transaction to file.");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::unsignedQrCode() {
 | 
			
		||||
    if (m_tx->unsignedTxToBin().size() > 2953) {
 | 
			
		||||
        QMessageBox::warning(this, "Unable to show QR code", "Transaction size exceeds the maximum size for QR codes (2953 bytes).");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QrCode qr(m_tx->unsignedTxToBin(), QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::LOW);
 | 
			
		||||
    auto *dialog = new QrCodeDialog(this, qr, "Unsigned Transaction");
 | 
			
		||||
    dialog->exec();
 | 
			
		||||
    dialog->deleteLater();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::unsignedCopy() {
 | 
			
		||||
    Utils::copyToClipboard(m_tx->unsignedTxToBase64());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::signedCopy() {
 | 
			
		||||
    Utils::copyToClipboard(m_tx->signedTxToHex(0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::signedQrCode() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::broadcastTransaction() {
 | 
			
		||||
    if (m_tx == nullptr) return;
 | 
			
		||||
    m_ctx->currentWallet->commitTransactionAsync(m_tx);
 | 
			
		||||
    QDialog::accept();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfAdvDialog::closeDialog() {
 | 
			
		||||
    if (m_tx != nullptr)
 | 
			
		||||
        m_ctx->currentWallet->disposeTransaction(m_tx);
 | 
			
		||||
    if (m_utx != nullptr)
 | 
			
		||||
        m_ctx->currentWallet->disposeTransaction(m_utx);
 | 
			
		||||
    QDialog::reject();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TxConfAdvDialog::~TxConfAdvDialog() {
 | 
			
		||||
    delete ui;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/dialog/txconfadvdialog.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/dialog/txconfadvdialog.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_TXCONFADVDIALOG_H
 | 
			
		||||
#define FEATHER_TXCONFADVDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
#include <QStandardItemModel>
 | 
			
		||||
#include <QAbstractButton>
 | 
			
		||||
#include <QMenu>
 | 
			
		||||
 | 
			
		||||
#include "libwalletqt/PendingTransaction.h"
 | 
			
		||||
#include "appcontext.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
    class TxConfAdvDialog;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TxConfAdvDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit TxConfAdvDialog(AppContext *ctx, const QString &description, QWidget *parent = nullptr);
 | 
			
		||||
    ~TxConfAdvDialog() override;
 | 
			
		||||
 | 
			
		||||
    void setTransaction(PendingTransaction *tx);
 | 
			
		||||
    void setUnsignedTransaction(UnsignedTransaction *utx);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void setupConstructionData(ConstructionInfo *ci);
 | 
			
		||||
    void signTransaction();
 | 
			
		||||
    void broadcastTransaction();
 | 
			
		||||
    void closeDialog();
 | 
			
		||||
 | 
			
		||||
    void unsignedCopy();
 | 
			
		||||
    void unsignedQrCode();
 | 
			
		||||
    void unsignedSaveFile();
 | 
			
		||||
 | 
			
		||||
    void signedCopy();
 | 
			
		||||
    void signedQrCode();
 | 
			
		||||
    void signedSaveFile();
 | 
			
		||||
 | 
			
		||||
    Ui::TxConfAdvDialog *ui;
 | 
			
		||||
    AppContext *m_ctx;
 | 
			
		||||
    PendingTransaction *m_tx = nullptr;
 | 
			
		||||
    UnsignedTransaction *m_utx = nullptr;
 | 
			
		||||
    QMenu *m_exportUnsignedMenu;
 | 
			
		||||
    QMenu *m_exportSignedMenu;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_TXCONFADVDIALOG_H
 | 
			
		||||
							
								
								
									
										279
									
								
								src/dialog/txconfadvdialog.ui
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										279
									
								
								src/dialog/txconfadvdialog.ui
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,279 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<ui version="4.0">
 | 
			
		||||
 <class>TxConfAdvDialog</class>
 | 
			
		||||
 <widget class="QDialog" name="TxConfAdvDialog">
 | 
			
		||||
  <property name="geometry">
 | 
			
		||||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>800</width>
 | 
			
		||||
    <height>542</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="minimumSize">
 | 
			
		||||
   <size>
 | 
			
		||||
    <width>800</width>
 | 
			
		||||
    <height>0</height>
 | 
			
		||||
   </size>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="windowTitle">
 | 
			
		||||
   <string>Transaction</string>
 | 
			
		||||
  </property>
 | 
			
		||||
  <layout class="QVBoxLayout" name="verticalLayout">
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLabel" name="label">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
      <string>Transaction ID:</string>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLineEdit" name="txid">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
      <string>txid</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="readOnly">
 | 
			
		||||
      <bool>true</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="horizontalLayout_2">
 | 
			
		||||
     <item>
 | 
			
		||||
      <layout class="QFormLayout" name="formLayout">
 | 
			
		||||
       <item row="0" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_amount">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Amount: </string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="0" column="1">
 | 
			
		||||
        <widget class="QLabel" name="amount">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>TextLabel</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_fee">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Fee: </string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="1" column="1">
 | 
			
		||||
        <widget class="QLabel" name="fee">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>TextLabel</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="2" column="1">
 | 
			
		||||
        <widget class="Line" name="line_2">
 | 
			
		||||
         <property name="orientation">
 | 
			
		||||
          <enum>Qt::Horizontal</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="3" column="0">
 | 
			
		||||
        <widget class="QLabel" name="label_4">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Total:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item row="3" column="1">
 | 
			
		||||
        <widget class="QLabel" name="total">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>TextLabel</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="Line" name="line">
 | 
			
		||||
       <property name="orientation">
 | 
			
		||||
        <enum>Qt::Vertical</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
			
		||||
       <item>
 | 
			
		||||
        <widget class="QLabel" name="label_description">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Description:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <widget class="QLabel" name="label_size">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Size: </string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <widget class="QLabel" name="label_unlockTime">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Unlock time: </string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <widget class="QLabel" name="label_ringSize">
 | 
			
		||||
         <property name="text">
 | 
			
		||||
          <string>Ringsize:</string>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </item>
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <spacer name="verticalSpacer_2">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Vertical</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="sizeType">
 | 
			
		||||
      <enum>QSizePolicy::Minimum</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="sizeHint" stdset="0">
 | 
			
		||||
      <size>
 | 
			
		||||
       <width>20</width>
 | 
			
		||||
       <height>10</height>
 | 
			
		||||
      </size>
 | 
			
		||||
     </property>
 | 
			
		||||
    </spacer>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLabel" name="label_inputs">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
      <string>Inputs</string>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QTextEdit" name="inputs">
 | 
			
		||||
     <property name="sizePolicy">
 | 
			
		||||
      <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
 | 
			
		||||
       <horstretch>0</horstretch>
 | 
			
		||||
       <verstretch>0</verstretch>
 | 
			
		||||
      </sizepolicy>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="maximumSize">
 | 
			
		||||
      <size>
 | 
			
		||||
       <width>16777215</width>
 | 
			
		||||
       <height>100</height>
 | 
			
		||||
      </size>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="readOnly">
 | 
			
		||||
      <bool>true</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QLabel" name="label_outputs">
 | 
			
		||||
     <property name="text">
 | 
			
		||||
      <string>Outputs</string>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <widget class="QTextEdit" name="outputs">
 | 
			
		||||
     <property name="sizePolicy">
 | 
			
		||||
      <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
 | 
			
		||||
       <horstretch>0</horstretch>
 | 
			
		||||
       <verstretch>0</verstretch>
 | 
			
		||||
      </sizepolicy>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="maximumSize">
 | 
			
		||||
      <size>
 | 
			
		||||
       <width>16777215</width>
 | 
			
		||||
       <height>100</height>
 | 
			
		||||
      </size>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="readOnly">
 | 
			
		||||
      <bool>true</bool>
 | 
			
		||||
     </property>
 | 
			
		||||
    </widget>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <spacer name="verticalSpacer">
 | 
			
		||||
     <property name="orientation">
 | 
			
		||||
      <enum>Qt::Vertical</enum>
 | 
			
		||||
     </property>
 | 
			
		||||
     <property name="sizeHint" stdset="0">
 | 
			
		||||
      <size>
 | 
			
		||||
       <width>20</width>
 | 
			
		||||
       <height>0</height>
 | 
			
		||||
      </size>
 | 
			
		||||
     </property>
 | 
			
		||||
    </spacer>
 | 
			
		||||
   </item>
 | 
			
		||||
   <item>
 | 
			
		||||
    <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QToolButton" name="btn_exportUnsigned">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Export unsigned</string>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="popupMode">
 | 
			
		||||
        <enum>QToolButton::InstantPopup</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QToolButton" name="btn_exportSigned">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Export signed</string>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="popupMode">
 | 
			
		||||
        <enum>QToolButton::InstantPopup</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <spacer name="horizontalSpacer">
 | 
			
		||||
       <property name="orientation">
 | 
			
		||||
        <enum>Qt::Horizontal</enum>
 | 
			
		||||
       </property>
 | 
			
		||||
       <property name="sizeHint" stdset="0">
 | 
			
		||||
        <size>
 | 
			
		||||
         <width>40</width>
 | 
			
		||||
         <height>20</height>
 | 
			
		||||
        </size>
 | 
			
		||||
       </property>
 | 
			
		||||
      </spacer>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QPushButton" name="btn_sign">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Sign</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QPushButton" name="btn_send">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Send</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
     <item>
 | 
			
		||||
      <widget class="QPushButton" name="btn_close">
 | 
			
		||||
       <property name="text">
 | 
			
		||||
        <string>Close</string>
 | 
			
		||||
       </property>
 | 
			
		||||
      </widget>
 | 
			
		||||
     </item>
 | 
			
		||||
    </layout>
 | 
			
		||||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <resources/>
 | 
			
		||||
 <connections/>
 | 
			
		||||
</ui>
 | 
			
		||||
| 
						 | 
				
			
			@ -6,12 +6,15 @@
 | 
			
		|||
#include "appcontext.h"
 | 
			
		||||
#include "utils/config.h"
 | 
			
		||||
#include "model/ModelUtils.h"
 | 
			
		||||
#include "libwalletqt/WalletManager.h"
 | 
			
		||||
#include "txconfadvdialog.h"
 | 
			
		||||
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
 | 
			
		||||
TxConfDialog::TxConfDialog(PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent)
 | 
			
		||||
TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent)
 | 
			
		||||
        : QDialog(parent)
 | 
			
		||||
        , ui(new Ui::TxConfDialog)
 | 
			
		||||
        , m_ctx(ctx)
 | 
			
		||||
        , m_tx(tx)
 | 
			
		||||
        , m_address(address)
 | 
			
		||||
        , m_description(description)
 | 
			
		||||
| 
						 | 
				
			
			@ -43,29 +46,16 @@ TxConfDialog::TxConfDialog(PendingTransaction *tx, const QString &address, const
 | 
			
		|||
    ui->label_address->setFont(ModelUtils::getMonospaceFont());
 | 
			
		||||
    ui->label_address->setToolTip(address);
 | 
			
		||||
 | 
			
		||||
    connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::showAdvanced);
 | 
			
		||||
    ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Send");
 | 
			
		||||
 | 
			
		||||
    connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::setShowAdvanced);
 | 
			
		||||
 | 
			
		||||
    this->adjustSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TxConfDialog::showAdvanced() {
 | 
			
		||||
    const auto amount = m_tx->amount() / AppContext::cdiv;
 | 
			
		||||
    const auto fee = m_tx->fee() / AppContext::cdiv;
 | 
			
		||||
 | 
			
		||||
    QString body = QString("Address: %2\n").arg(m_address.left(60));
 | 
			
		||||
    body += m_address.mid(60) + "\n";
 | 
			
		||||
    if(!m_description.isEmpty())
 | 
			
		||||
        body = QString("%1Description: %2\n").arg(body, m_description);
 | 
			
		||||
    body = QString("%1Amount: %2 XMR\n").arg(body, QString::number(amount));
 | 
			
		||||
    body = QString("%1Fee: %2 XMR\n").arg(body, QString::number(fee));
 | 
			
		||||
    body = QString("%1Ringsize: %2").arg(body, QString::number(m_mixin + 1));
 | 
			
		||||
 | 
			
		||||
    auto subaddrIndices = m_tx->subaddrIndices();
 | 
			
		||||
    for (int i = 0; i < subaddrIndices.count(); ++i){
 | 
			
		||||
        body = QString("%1\nSpending address index: %2").arg(body, QString::number(subaddrIndices.at(i).toInt()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QMessageBox::information(this, "Transaction information", body);
 | 
			
		||||
void TxConfDialog::setShowAdvanced() {
 | 
			
		||||
    this->showAdvanced = true;
 | 
			
		||||
    QDialog::reject();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TxConfDialog::~TxConfDialog() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
#include <QDialog>
 | 
			
		||||
#include "libwalletqt/PendingTransaction.h"
 | 
			
		||||
#include "libwalletqt/WalletManager.h"
 | 
			
		||||
#include "appcontext.h"
 | 
			
		||||
 | 
			
		||||
namespace Ui {
 | 
			
		||||
    class TxConfDialog;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,13 +18,18 @@ class TxConfDialog : public QDialog
 | 
			
		|||
Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit TxConfDialog(PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent = nullptr);
 | 
			
		||||
    explicit TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent = nullptr);
 | 
			
		||||
    ~TxConfDialog() override;
 | 
			
		||||
 | 
			
		||||
    bool showAdvanced = false;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void showAdvanced();
 | 
			
		||||
    void setShowAdvanced();
 | 
			
		||||
    void saveToFile();
 | 
			
		||||
    void copyToClipboard();
 | 
			
		||||
 | 
			
		||||
    Ui::TxConfDialog *ui;
 | 
			
		||||
    AppContext *m_ctx;
 | 
			
		||||
    PendingTransaction *m_tx;
 | 
			
		||||
    QString m_address;
 | 
			
		||||
    QString m_description;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
   <rect>
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>655</width>
 | 
			
		||||
    <width>844</width>
 | 
			
		||||
    <height>248</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										53
									
								
								src/libwalletqt/ConstructionInfo.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/libwalletqt/ConstructionInfo.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2014-2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#include "ConstructionInfo.h"
 | 
			
		||||
 | 
			
		||||
#include "Input.h"
 | 
			
		||||
#include "Transfer.h"
 | 
			
		||||
 | 
			
		||||
quint64 ConstructionInfo::unlockTime() const {
 | 
			
		||||
    return m_unlockTime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QSet<quint32> ConstructionInfo::subaddressIndices() const {
 | 
			
		||||
    return m_subaddressIndices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVector<QString> ConstructionInfo::subaddresses() const {
 | 
			
		||||
    return m_subaddresses;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint64 ConstructionInfo::minMixinCount() const {
 | 
			
		||||
    return m_minMixinCount;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QList<Input *> ConstructionInfo::inputs() const {
 | 
			
		||||
    return m_inputs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QList<Transfer *> ConstructionInfo::outputs() const {
 | 
			
		||||
    return m_outputs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConstructionInfo::ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent)
 | 
			
		||||
        : QObject(parent)
 | 
			
		||||
        , m_unlockTime(pimpl->unlockTime())
 | 
			
		||||
        , m_minMixinCount(pimpl->minMixinCount())
 | 
			
		||||
{
 | 
			
		||||
    for (auto const &i : pimpl->inputs())
 | 
			
		||||
    {
 | 
			
		||||
        Input *input = new Input(i.amount, QString::fromStdString(i.pubkey), this);
 | 
			
		||||
        m_inputs.append(input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (auto const &o : pimpl->outputs())
 | 
			
		||||
    {
 | 
			
		||||
        Transfer *output = new Transfer(o.amount, QString::fromStdString(o.address), this);
 | 
			
		||||
        m_outputs.append(output);
 | 
			
		||||
    }
 | 
			
		||||
    for (uint32_t i : pimpl->subaddressIndices())
 | 
			
		||||
    {
 | 
			
		||||
        m_subaddressIndices.insert(i);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								src/libwalletqt/ConstructionInfo.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/libwalletqt/ConstructionInfo.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2014-2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_CONSTRUCTIONINFO_H
 | 
			
		||||
#define FEATHER_CONSTRUCTIONINFO_H
 | 
			
		||||
 | 
			
		||||
#include <wallet/api/wallet2_api.h>
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QSet>
 | 
			
		||||
 | 
			
		||||
class Input;
 | 
			
		||||
class Transfer;
 | 
			
		||||
 | 
			
		||||
class ConstructionInfo : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
    Q_PROPERTY(quint64 unlockTime READ unlockTime)
 | 
			
		||||
    Q_PROPERTY(QSet<quint32> subaddressIndices READ subaddressIndices)
 | 
			
		||||
    Q_PROPERTY(QVector<QString> subaddresses READ subaddresses)
 | 
			
		||||
    Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
 | 
			
		||||
    Q_PROPERTY(QList<Input*> inputs READ inputs)
 | 
			
		||||
    Q_PROPERTY(QList<Transfer*> outputs READ outputs)
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    quint64 unlockTime() const;
 | 
			
		||||
    QSet<quint32> subaddressIndices() const;
 | 
			
		||||
    QVector<QString> subaddresses() const;
 | 
			
		||||
    quint64 minMixinCount() const;
 | 
			
		||||
    QList<Input*> inputs() const;
 | 
			
		||||
    QList<Transfer*> outputs() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    explicit ConstructionInfo(const Monero::TransactionConstructionInfo *pimpl, QObject *parent = nullptr);
 | 
			
		||||
 | 
			
		||||
    friend class PendingTransactionInfo;
 | 
			
		||||
    friend class UnsignedTransaction;
 | 
			
		||||
    quint64 m_unlockTime;
 | 
			
		||||
    QSet<quint32> m_subaddressIndices;
 | 
			
		||||
    QVector<QString> m_subaddresses;
 | 
			
		||||
    quint64 m_minMixinCount;
 | 
			
		||||
    mutable QList<Input*> m_inputs;
 | 
			
		||||
    mutable QList<Transfer*> m_outputs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_CONSTRUCTIONINFO_H
 | 
			
		||||
							
								
								
									
										29
									
								
								src/libwalletqt/Input.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/libwalletqt/Input.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2014-2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_INPUT_H
 | 
			
		||||
#define FEATHER_INPUT_H
 | 
			
		||||
 | 
			
		||||
#include <wallet/api/wallet2_api.h>
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
class Input : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
    Q_PROPERTY(quint64 amount READ amount)
 | 
			
		||||
    Q_PROPERTY(QString pubKey READ pubKey)
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    explicit Input(uint64_t _amount, QString _address,  QObject *parent = nullptr): QObject(parent), m_amount(_amount), m_pubkey(std::move(_address)) {};
 | 
			
		||||
 | 
			
		||||
    friend class ConstructionInfo;
 | 
			
		||||
    quint64 m_amount;
 | 
			
		||||
    QString m_pubkey;
 | 
			
		||||
public:
 | 
			
		||||
    quint64 amount() const { return m_amount; }
 | 
			
		||||
    QString pubKey() const { return m_pubkey; }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_INPUT_H
 | 
			
		||||
| 
						 | 
				
			
			@ -16,10 +16,12 @@ QString PendingTransaction::errorString() const
 | 
			
		|||
 | 
			
		||||
bool PendingTransaction::commit()
 | 
			
		||||
{
 | 
			
		||||
    // Save transaction to file if fileName is set.
 | 
			
		||||
    if(!m_fileName.isEmpty())
 | 
			
		||||
        return m_pimpl->commit(m_fileName.toStdString());
 | 
			
		||||
    return m_pimpl->commit(m_fileName.toStdString());
 | 
			
		||||
    return m_pimpl->commit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PendingTransaction::saveToFile(const QString &fileName)
 | 
			
		||||
{
 | 
			
		||||
    return m_pimpl->commit(fileName.toStdString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint64 PendingTransaction::amount() const
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +39,6 @@ quint64 PendingTransaction::fee() const
 | 
			
		|||
    return m_pimpl->fee();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QStringList PendingTransaction::txid() const
 | 
			
		||||
{
 | 
			
		||||
    QStringList list;
 | 
			
		||||
| 
						 | 
				
			
			@ -63,9 +64,33 @@ QList<QVariant> PendingTransaction::subaddrIndices() const
 | 
			
		|||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PendingTransaction::setFilename(const QString &fileName)
 | 
			
		||||
QByteArray PendingTransaction::unsignedTxToBin() const {
 | 
			
		||||
    return QByteArray::fromStdString(m_pimpl->unsignedTxToBin());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString PendingTransaction::unsignedTxToBase64() const
 | 
			
		||||
{
 | 
			
		||||
    m_fileName = fileName;
 | 
			
		||||
    return QString::fromStdString(m_pimpl->unsignedTxToBase64());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString PendingTransaction::signedTxToHex(int index) const
 | 
			
		||||
{
 | 
			
		||||
    return QString::fromStdString(m_pimpl->signedTxToHex(index));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PendingTransactionInfo * PendingTransaction::transaction(int index) const {
 | 
			
		||||
    return m_pending_tx_info[index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PendingTransaction::refresh()
 | 
			
		||||
{
 | 
			
		||||
    qDeleteAll(m_pending_tx_info);
 | 
			
		||||
    m_pending_tx_info.clear();
 | 
			
		||||
 | 
			
		||||
    m_pimpl->refresh();
 | 
			
		||||
    for (const auto i : m_pimpl->getAll()) {
 | 
			
		||||
        m_pending_tx_info.append(new PendingTransactionInfo(i, this));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PendingTransaction::PendingTransaction(Monero::PendingTransaction *pt, QObject *parent)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,8 @@
 | 
			
		|||
#include <QVariant>
 | 
			
		||||
 | 
			
		||||
#include <wallet/api/wallet2_api.h>
 | 
			
		||||
#include "PendingTransactionInfo.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//namespace Monero {
 | 
			
		||||
//class PendingTransaction;
 | 
			
		||||
| 
						 | 
				
			
			@ -30,7 +32,7 @@ public:
 | 
			
		|||
    enum Status {
 | 
			
		||||
        Status_Ok       = Monero::PendingTransaction::Status_Ok,
 | 
			
		||||
        Status_Error    = Monero::PendingTransaction::Status_Error,
 | 
			
		||||
        Status_Critical    = Monero::PendingTransaction::Status_Critical
 | 
			
		||||
        Status_Critical = Monero::PendingTransaction::Status_Critical
 | 
			
		||||
    };
 | 
			
		||||
    Q_ENUM(Status)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,21 +47,27 @@ public:
 | 
			
		|||
    Status status() const;
 | 
			
		||||
    QString errorString() const;
 | 
			
		||||
    Q_INVOKABLE bool commit();
 | 
			
		||||
    bool saveToFile(const QString &fileName);
 | 
			
		||||
    quint64 amount() const;
 | 
			
		||||
    quint64 dust() const;
 | 
			
		||||
    quint64 fee() const;
 | 
			
		||||
    QStringList txid() const;
 | 
			
		||||
    quint64 txCount() const;
 | 
			
		||||
    QList<QVariant> subaddrIndices() const;
 | 
			
		||||
    Q_INVOKABLE void setFilename(const QString &fileName);
 | 
			
		||||
    QByteArray unsignedTxToBin() const;
 | 
			
		||||
    QString unsignedTxToBase64() const;
 | 
			
		||||
    QString signedTxToHex(int index) const;
 | 
			
		||||
    void refresh();
 | 
			
		||||
 | 
			
		||||
    PendingTransactionInfo * transaction(int index) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = 0);
 | 
			
		||||
    explicit PendingTransaction(Monero::PendingTransaction * pt, QObject *parent = nullptr);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    friend class Wallet;
 | 
			
		||||
    Monero::PendingTransaction * m_pimpl;
 | 
			
		||||
    QString m_fileName;
 | 
			
		||||
    mutable QList<PendingTransactionInfo*> m_pending_tx_info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // PENDINGTRANSACTION_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										32
									
								
								src/libwalletqt/PendingTransactionInfo.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/libwalletqt/PendingTransactionInfo.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2014-2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#include "PendingTransactionInfo.h"
 | 
			
		||||
#include "Input.h"
 | 
			
		||||
#include "Transfer.h"
 | 
			
		||||
 | 
			
		||||
quint64 PendingTransactionInfo::fee() const {
 | 
			
		||||
    return m_fee;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint64 PendingTransactionInfo::dust() const {
 | 
			
		||||
    return m_dust;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PendingTransactionInfo::dustAddedToFee() const {
 | 
			
		||||
    return m_dustAddedToFee;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString PendingTransactionInfo::txKey() const {
 | 
			
		||||
    return m_txKey;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PendingTransactionInfo::PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent)
 | 
			
		||||
    : ConstructionInfo(pimpl->constructionData(), parent)
 | 
			
		||||
    , m_fee(pimpl->fee())
 | 
			
		||||
    , m_dust(pimpl->dust())
 | 
			
		||||
    , m_dustAddedToFee(pimpl->dustAddedToFee())
 | 
			
		||||
    , m_txKey(QString::fromStdString(pimpl->txKey()))
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								src/libwalletqt/PendingTransactionInfo.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/libwalletqt/PendingTransactionInfo.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2014-2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_PENDINGTRANSACTIONINFO_H
 | 
			
		||||
#define FEATHER_PENDINGTRANSACTIONINFO_H
 | 
			
		||||
 | 
			
		||||
#include <wallet/api/wallet2_api.h>
 | 
			
		||||
#include "ConstructionInfo.h"
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QSet>
 | 
			
		||||
 | 
			
		||||
class Input;
 | 
			
		||||
class Transfer;
 | 
			
		||||
 | 
			
		||||
class PendingTransactionInfo : public ConstructionInfo
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
    Q_PROPERTY(quint64 fee READ fee)
 | 
			
		||||
    Q_PROPERTY(quint64 dust READ dust)
 | 
			
		||||
    Q_PROPERTY(bool dustAddedToFee READ dustAddedToFee)
 | 
			
		||||
    Q_PROPERTY(QString txKey READ txKey)
 | 
			
		||||
    Q_PROPERTY(quint64 unlockTime READ unlockTime)
 | 
			
		||||
    Q_PROPERTY(QSet<quint32> subaddressIndices READ subaddressIndices)
 | 
			
		||||
    Q_PROPERTY(QVector<QString> subaddresses READ subaddresses)
 | 
			
		||||
    Q_PROPERTY(quint64 minMixinCount READ minMixinCount)
 | 
			
		||||
    Q_PROPERTY(QList<Input*> inputs READ inputs)
 | 
			
		||||
    Q_PROPERTY(QList<Transfer*> outputs READ outputs)
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    quint64 fee() const;
 | 
			
		||||
    quint64 dust() const;
 | 
			
		||||
    bool dustAddedToFee() const;
 | 
			
		||||
    QString txKey() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    explicit PendingTransactionInfo(const Monero::PendingTransactionInfo *pimpl, QObject *parent = nullptr);
 | 
			
		||||
 | 
			
		||||
    friend class PendingTransaction;
 | 
			
		||||
    quint64 m_fee;
 | 
			
		||||
    quint64 m_dust;
 | 
			
		||||
    bool m_dustAddedToFee;
 | 
			
		||||
    QString m_txKey;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_PENDINGTRANSACTIONINFO_H
 | 
			
		||||
| 
						 | 
				
			
			@ -17,6 +17,7 @@ private:
 | 
			
		|||
    explicit Transfer(uint64_t _amount, QString _address,  QObject *parent = 0): QObject(parent), m_amount(_amount), m_address(std::move(_address)) {};
 | 
			
		||||
private:
 | 
			
		||||
    friend class TransactionInfo;
 | 
			
		||||
    friend class ConstructionInfo;
 | 
			
		||||
    quint64 m_amount;
 | 
			
		||||
    QString m_address;
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,6 +83,21 @@ void UnsignedTransaction::setFilename(const QString &fileName)
 | 
			
		|||
    m_fileName = fileName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ConstructionInfo * UnsignedTransaction::constructionInfo(int index) const {
 | 
			
		||||
    return m_construction_info[index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UnsignedTransaction::refresh()
 | 
			
		||||
{
 | 
			
		||||
    qDeleteAll(m_construction_info);
 | 
			
		||||
    m_construction_info.clear();
 | 
			
		||||
 | 
			
		||||
    m_pimpl->refresh();
 | 
			
		||||
    for (const auto i : m_pimpl->getAll()) {
 | 
			
		||||
        m_construction_info.append(new ConstructionInfo(i, this));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UnsignedTransaction::UnsignedTransaction(Monero::UnsignedTransaction *pt, Monero::Wallet *walletImpl, QObject *parent)
 | 
			
		||||
    : QObject(parent), m_pimpl(pt), m_walletImpl(walletImpl)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,14 +7,13 @@
 | 
			
		|||
#include <QObject>
 | 
			
		||||
 | 
			
		||||
#include <wallet/api/wallet2_api.h>
 | 
			
		||||
#include "libwalletqt/PendingTransactionInfo.h"
 | 
			
		||||
 | 
			
		||||
class UnsignedTransaction : public QObject
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
    Q_PROPERTY(Status status READ status)
 | 
			
		||||
    Q_PROPERTY(QString errorString READ errorString)
 | 
			
		||||
  //  Q_PROPERTY(QList<qulonglong> amount READ amount)
 | 
			
		||||
  //  Q_PROPERTY(QList<qulonglong> fee READ fee)
 | 
			
		||||
    Q_PROPERTY(quint64 txCount READ txCount)
 | 
			
		||||
    Q_PROPERTY(QString confirmationMessage READ confirmationMessage)
 | 
			
		||||
    Q_PROPERTY(QStringList recipientAddress READ recipientAddress)
 | 
			
		||||
| 
						 | 
				
			
			@ -41,15 +40,19 @@ public:
 | 
			
		|||
    quint64 minMixinCount() const;
 | 
			
		||||
    Q_INVOKABLE bool sign(const QString &fileName) const;
 | 
			
		||||
    Q_INVOKABLE void setFilename(const QString &fileName);
 | 
			
		||||
    void refresh();
 | 
			
		||||
 | 
			
		||||
    ConstructionInfo * constructionInfo(int index) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = 0);
 | 
			
		||||
    explicit UnsignedTransaction(Monero::UnsignedTransaction * pt, Monero::Wallet *walletImpl, QObject *parent = nullptr);
 | 
			
		||||
    ~UnsignedTransaction();
 | 
			
		||||
private:
 | 
			
		||||
    friend class Wallet;
 | 
			
		||||
    Monero::UnsignedTransaction * m_pimpl;
 | 
			
		||||
    QString m_fileName;
 | 
			
		||||
    Monero::Wallet * m_walletImpl;
 | 
			
		||||
    mutable QList<ConstructionInfo*> m_construction_info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // UNSIGNEDTRANSACTION_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -529,7 +529,7 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
 | 
			
		|||
{
 | 
			
		||||
    m_scheduler.run([this, key_image, dst_addr, outputs, priority] {
 | 
			
		||||
        PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority);
 | 
			
		||||
        emit transactionCreated(tx, dst_addr, "", 0); // todo: return true mixincount
 | 
			
		||||
        emit transactionCreated(tx, dst_addr, "", 10); // todo: return true mixincount
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -556,6 +556,21 @@ UnsignedTransaction * Wallet::loadTxFile(const QString &fileName)
 | 
			
		|||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UnsignedTransaction * Wallet::loadTxFromBase64Str(const QString &unsigned_tx)
 | 
			
		||||
{
 | 
			
		||||
    Monero::UnsignedTransaction * ptImpl = m_walletImpl->loadUnsignedTxFromBase64Str(unsigned_tx.toStdString());
 | 
			
		||||
    UnsignedTransaction * result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PendingTransaction * Wallet::loadSignedTxFile(const QString &fileName)
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "Tying to load " << fileName;
 | 
			
		||||
    Monero::PendingTransaction * ptImpl = m_walletImpl->loadSignedTx(fileName.toStdString());
 | 
			
		||||
    PendingTransaction * result = new PendingTransaction(ptImpl, this);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Wallet::submitTxFile(const QString &fileName) const
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "Trying to submit " << fileName;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -250,6 +250,12 @@ public:
 | 
			
		|||
    //! Sign a transfer from file
 | 
			
		||||
    Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName);
 | 
			
		||||
 | 
			
		||||
    //! Load an unsigned transaction from a base64 encoded string
 | 
			
		||||
    Q_INVOKABLE UnsignedTransaction * loadTxFromBase64Str(const QString &unsigned_tx);
 | 
			
		||||
 | 
			
		||||
    //! Load a signed transaction from file
 | 
			
		||||
    Q_INVOKABLE PendingTransaction * loadSignedTxFile(const QString &fileName);
 | 
			
		||||
 | 
			
		||||
    //! Submit a transfer from file
 | 
			
		||||
    Q_INVOKABLE bool submitTxFile(const QString &fileName) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,12 +13,15 @@
 | 
			
		|||
#include "widgets/ccswidget.h"
 | 
			
		||||
#include "widgets/redditwidget.h"
 | 
			
		||||
#include "dialog/txconfdialog.h"
 | 
			
		||||
#include "dialog/txconfadvdialog.h"
 | 
			
		||||
#include "dialog/debuginfodialog.h"
 | 
			
		||||
#include "dialog/walletinfodialog.h"
 | 
			
		||||
#include "dialog/torinfodialog.h"
 | 
			
		||||
#include "dialog/viewonlydialog.h"
 | 
			
		||||
#include "dialog/broadcasttxdialog.h"
 | 
			
		||||
#include "utils/utils.h"
 | 
			
		||||
#include "utils/config.h"
 | 
			
		||||
#include "utils/daemonrpc.h"
 | 
			
		||||
#include "components.h"
 | 
			
		||||
#include "calcwindow.h"
 | 
			
		||||
#include "ui_mainwindow.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -474,6 +477,10 @@ void MainWindow::initMenu() {
 | 
			
		|||
    // Tools
 | 
			
		||||
    connect(ui->actionSignVerify, &QAction::triggered, this, &MainWindow::menuSignVerifyClicked);
 | 
			
		||||
    connect(ui->actionVerifyTxProof, &QAction::triggered, this, &MainWindow::menuVerifyTxProof);
 | 
			
		||||
    connect(ui->actionLoadUnsignedTxFromFile, &QAction::triggered, this, &MainWindow::loadUnsignedTx);
 | 
			
		||||
    connect(ui->actionLoadUnsignedTxFromClipboard, &QAction::triggered, this, &MainWindow::loadUnsignedTxFromClipboard);
 | 
			
		||||
    connect(ui->actionLoadSignedTxFromFile, &QAction::triggered, this, &MainWindow::loadSignedTx);
 | 
			
		||||
    connect(ui->actionLoadSignedTxFromText, &QAction::triggered, this, &MainWindow::loadSignedTxFromText);
 | 
			
		||||
 | 
			
		||||
    // About screen
 | 
			
		||||
    connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::menuAboutClicked);
 | 
			
		||||
| 
						 | 
				
			
			@ -702,15 +709,26 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QStrin
 | 
			
		|||
    } else {
 | 
			
		||||
        const auto &description = m_ctx->tmpTxDescription;
 | 
			
		||||
 | 
			
		||||
        auto *dialog = new TxConfDialog(tx, address, description, mixin, this);
 | 
			
		||||
        auto *dialog = new TxConfDialog(m_ctx, tx, address, description, mixin, this);
 | 
			
		||||
        switch (dialog->exec()) {
 | 
			
		||||
            case QDialog::Rejected:
 | 
			
		||||
                m_ctx->onCancelTransaction(tx, address);
 | 
			
		||||
            {
 | 
			
		||||
                if (!dialog->showAdvanced)
 | 
			
		||||
                    m_ctx->onCancelTransaction(tx, address);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case QDialog::Accepted:
 | 
			
		||||
                m_ctx->currentWallet->commitTransactionAsync(tx);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (dialog->showAdvanced) {
 | 
			
		||||
            auto *dialog_adv = new TxConfAdvDialog(m_ctx, description, this);
 | 
			
		||||
            dialog_adv->setTransaction(tx);
 | 
			
		||||
            dialog_adv->exec();
 | 
			
		||||
            dialog_adv->deleteLater();
 | 
			
		||||
        }
 | 
			
		||||
        dialog->deleteLater();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1157,6 +1175,64 @@ void MainWindow::cleanupBeforeClose() {
 | 
			
		|||
    this->saveGeo();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::loadUnsignedTx() {
 | 
			
		||||
    QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*unsigned_monero_tx)");
 | 
			
		||||
    if (fn.isEmpty()) return;
 | 
			
		||||
    UnsignedTransaction *tx = m_ctx->currentWallet->loadTxFile(fn);
 | 
			
		||||
    auto err = m_ctx->currentWallet->errorString();
 | 
			
		||||
    if (!err.isEmpty()) {
 | 
			
		||||
        QMessageBox::warning(this, "Load transaction from file", QString("Failed to load transaction.\n\n%1").arg(err));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this->createUnsignedTxDialog(tx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::loadUnsignedTxFromClipboard() {
 | 
			
		||||
    QString unsigned_tx = Utils::copyFromClipboard();
 | 
			
		||||
    if (unsigned_tx.isEmpty()) {
 | 
			
		||||
        QMessageBox::warning(this, "Load unsigned transaction from clipboard", "Clipboard is empty");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    UnsignedTransaction *tx = m_ctx->currentWallet->loadTxFromBase64Str(unsigned_tx);
 | 
			
		||||
    auto err = m_ctx->currentWallet->errorString();
 | 
			
		||||
    if (!err.isEmpty()) {
 | 
			
		||||
        QMessageBox::warning(this, "Load unsigned transaction from clipboard", QString("Failed to load transaction.\n\n%1").arg(err));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this->createUnsignedTxDialog(tx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::loadSignedTx() {
 | 
			
		||||
    QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*signed_monero_tx)");
 | 
			
		||||
    if (fn.isEmpty()) return;
 | 
			
		||||
    PendingTransaction *tx = m_ctx->currentWallet->loadSignedTxFile(fn);
 | 
			
		||||
    auto err = m_ctx->currentWallet->errorString();
 | 
			
		||||
    if (!err.isEmpty()) {
 | 
			
		||||
        QMessageBox::warning(this, "Load signed transaction from file", err);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto *dialog = new TxConfAdvDialog(m_ctx, "", this);
 | 
			
		||||
    dialog->setTransaction(tx);
 | 
			
		||||
    dialog->exec();
 | 
			
		||||
    dialog->deleteLater();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::loadSignedTxFromText() {
 | 
			
		||||
    auto dialog = new BroadcastTxDialog(this, m_ctx);
 | 
			
		||||
    dialog->exec();
 | 
			
		||||
    dialog->deleteLater();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::createUnsignedTxDialog(UnsignedTransaction *tx) {
 | 
			
		||||
    auto *dialog = new TxConfAdvDialog(m_ctx, "", this);
 | 
			
		||||
    dialog->setUnsignedTransaction(tx);
 | 
			
		||||
    dialog->exec();
 | 
			
		||||
    dialog->deleteLater();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MainWindow::~MainWindow() {
 | 
			
		||||
    delete ui;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,10 +101,15 @@ public slots:
 | 
			
		|||
    void onAddContact(const QString &address, const QString &name);
 | 
			
		||||
    void showRestoreHeightDialog();
 | 
			
		||||
 | 
			
		||||
    // offline tx signing
 | 
			
		||||
    void exportKeyImages();
 | 
			
		||||
    void importKeyImages();
 | 
			
		||||
    void exportOutputs();
 | 
			
		||||
    void importOutputs();
 | 
			
		||||
    void loadUnsignedTx();
 | 
			
		||||
    void loadUnsignedTxFromClipboard();
 | 
			
		||||
    void loadSignedTx();
 | 
			
		||||
    void loadSignedTxFromText();
 | 
			
		||||
 | 
			
		||||
    // libwalletqt
 | 
			
		||||
    void onBalanceUpdated(double balance, double unlocked, const QString &balance_str, const QString &unlocked_str);
 | 
			
		||||
| 
						 | 
				
			
			@ -136,6 +141,7 @@ private:
 | 
			
		|||
    void showDebugInfo();
 | 
			
		||||
    void showNodeExhaustedMessage();
 | 
			
		||||
    void showWSNodeExhaustedMessage();
 | 
			
		||||
    void createUnsignedTxDialog(UnsignedTransaction *tx);
 | 
			
		||||
 | 
			
		||||
    WalletWizard *createWizard(WalletWizard::Page startPage);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -375,9 +375,26 @@
 | 
			
		|||
    <property name="title">
 | 
			
		||||
     <string>Tools</string>
 | 
			
		||||
    </property>
 | 
			
		||||
    <widget class="QMenu" name="menuLoad_transaction">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Load unsigned transaction</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <addaction name="actionLoadUnsignedTxFromFile"/>
 | 
			
		||||
     <addaction name="actionLoadUnsignedTxFromClipboard"/>
 | 
			
		||||
    </widget>
 | 
			
		||||
    <widget class="QMenu" name="menuLoad_signed_transaction">
 | 
			
		||||
     <property name="title">
 | 
			
		||||
      <string>Broadcast transaction</string>
 | 
			
		||||
     </property>
 | 
			
		||||
     <addaction name="actionLoadSignedTxFromFile"/>
 | 
			
		||||
     <addaction name="actionLoadSignedTxFromText"/>
 | 
			
		||||
    </widget>
 | 
			
		||||
    <addaction name="actionSignVerify"/>
 | 
			
		||||
    <addaction name="actionVerifyTxProof"/>
 | 
			
		||||
    <addaction name="separator"/>
 | 
			
		||||
    <addaction name="menuLoad_transaction"/>
 | 
			
		||||
    <addaction name="menuLoad_signed_transaction"/>
 | 
			
		||||
    <addaction name="separator"/>
 | 
			
		||||
    <addaction name="actionCalculator"/>
 | 
			
		||||
    <addaction name="actionCreateDesktopEntry"/>
 | 
			
		||||
   </widget>
 | 
			
		||||
| 
						 | 
				
			
			@ -611,6 +628,36 @@
 | 
			
		|||
    <string>Show XMRig</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionImportTransaction">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Transaction</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionSubmitTransaction">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>Submit transaction file</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionLoadUnsignedTxFromFile">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>From file</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionLoadSignedTxFromFile">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>From file</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionLoadUnsignedTxFromClipboard">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>From clipboard</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
  <action name="actionLoadSignedTxFromText">
 | 
			
		||||
   <property name="text">
 | 
			
		||||
    <string>From text</string>
 | 
			
		||||
   </property>
 | 
			
		||||
  </action>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <layoutdefault spacing="6" margin="11"/>
 | 
			
		||||
 <customwidgets>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,7 +141,8 @@ void ReceiveWidget::setQrCode(const QString &address){
 | 
			
		|||
void ReceiveWidget::showQrCodeDialog() {
 | 
			
		||||
    QModelIndex index = ui->addresses->currentIndex();
 | 
			
		||||
    QString address = index.model()->data(index.siblingAtColumn(SubaddressModel::Address), Qt::UserRole).toString();
 | 
			
		||||
    auto *dialog = new QrCodeDialog(this, address, "Address");
 | 
			
		||||
    QrCode qr(address, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
 | 
			
		||||
    auto *dialog = new QrCodeDialog(this, qr, "Address");
 | 
			
		||||
    dialog->exec();
 | 
			
		||||
    dialog->deleteLater();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include "sendwidget.h"
 | 
			
		||||
#include "widgets/ccswidget.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										89
									
								
								src/utils/daemonrpc.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/utils/daemonrpc.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#include "daemonrpc.h"
 | 
			
		||||
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
DaemonRpc::DaemonRpc(QObject *parent, UtilsNetworking *network, QString daemonAddress)
 | 
			
		||||
        : QObject(parent)
 | 
			
		||||
        , m_network(network)
 | 
			
		||||
        , m_daemonAddress(std::move(daemonAddress))
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DaemonRpc::sendRawTransaction(const QString &tx_as_hex, bool do_not_relay, bool do_sanity_checks) {
 | 
			
		||||
    QJsonObject req;
 | 
			
		||||
    req["tx_as_hex"] = tx_as_hex;
 | 
			
		||||
    req["do_not_relay"] = do_not_relay;
 | 
			
		||||
    req["do_sanity_checks"] = do_sanity_checks;
 | 
			
		||||
 | 
			
		||||
    QString url = QString("%1/send_raw_transaction").arg(m_daemonAddress);
 | 
			
		||||
    QNetworkReply *reply = m_network->postJson(url, req);
 | 
			
		||||
    connect(reply, &QNetworkReply::finished, std::bind(&DaemonRpc::onResponse, this, reply, Endpoint::SEND_RAW_TRANSACTION));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DaemonRpc::onResponse(QNetworkReply *reply, Endpoint endpoint) {
 | 
			
		||||
    const auto ok = reply->error() == QNetworkReply::NoError;
 | 
			
		||||
    const auto err = reply->errorString();
 | 
			
		||||
 | 
			
		||||
    QByteArray data = reply->readAll();
 | 
			
		||||
    QJsonObject obj;
 | 
			
		||||
    if (!data.isEmpty() && Utils::validateJSON(data)) {
 | 
			
		||||
        auto doc = QJsonDocument::fromJson(data);
 | 
			
		||||
        obj = doc.object();
 | 
			
		||||
    }
 | 
			
		||||
    else if (!ok) {
 | 
			
		||||
        emit ApiResponse(DaemonResponse(false, endpoint, err));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        emit ApiResponse(DaemonResponse(false, endpoint, "Invalid response from daemon"));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (obj.value("status").toString() != "OK") {
 | 
			
		||||
        QString failedMsg;
 | 
			
		||||
        switch (endpoint) {
 | 
			
		||||
            case SEND_RAW_TRANSACTION:
 | 
			
		||||
                failedMsg = this->onSendRawTransactionFailed(obj);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                failedMsg = obj.value("status").toString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit ApiResponse(DaemonResponse(false, endpoint, failedMsg, obj));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    reply->deleteLater();
 | 
			
		||||
    emit ApiResponse(DaemonResponse(true, endpoint, "", obj));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString DaemonRpc::onSendRawTransactionFailed(const QJsonObject &obj) {
 | 
			
		||||
    QString message = [&obj]{
 | 
			
		||||
        if (obj.value("double_spend").toBool())
 | 
			
		||||
            return "Transaction is a double spend";
 | 
			
		||||
        if (obj.value("fee_too_low").toBool())
 | 
			
		||||
            return "Fee is too low";
 | 
			
		||||
        if (obj.value("invalid_input").toBool())
 | 
			
		||||
            return "Output is invalid";
 | 
			
		||||
        if (obj.value("low_mixin").toBool())
 | 
			
		||||
            return "Mixin count is too low";
 | 
			
		||||
        if (obj.value("overspend").toBool())
 | 
			
		||||
            return "Transaction uses more money than available";
 | 
			
		||||
        if (obj.value("too_big").toBool())
 | 
			
		||||
            return "Transaction size is too big";
 | 
			
		||||
        return "Daemon returned an unknown error";
 | 
			
		||||
    }();
 | 
			
		||||
 | 
			
		||||
    return QString("Transaction failed: %1").arg(message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DaemonRpc::setDaemonAddress(const QString &daemonAddress) {
 | 
			
		||||
    m_daemonAddress = daemonAddress;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DaemonRpc::setNetwork(UtilsNetworking *network) {
 | 
			
		||||
    m_network = network;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								src/utils/daemonrpc.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/utils/daemonrpc.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
// SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
// Copyright (c) 2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#ifndef FEATHER_DAEMON_RPC_H
 | 
			
		||||
#define FEATHER_DAEMON_RPC_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
 | 
			
		||||
#include "utils/networking.h"
 | 
			
		||||
 | 
			
		||||
class DaemonRpc : public QObject {
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    enum Endpoint {
 | 
			
		||||
        SEND_RAW_TRANSACTION = 0
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct DaemonResponse {
 | 
			
		||||
        explicit DaemonResponse(bool ok, Endpoint endpoint, QString status, QJsonObject obj = {})
 | 
			
		||||
                : ok(ok), endpoint(endpoint), status(std::move(status)), obj(std::move(obj)) {};
 | 
			
		||||
 | 
			
		||||
        bool ok;
 | 
			
		||||
        DaemonRpc::Endpoint endpoint;
 | 
			
		||||
        QString status;
 | 
			
		||||
        QJsonObject obj;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    explicit DaemonRpc(QObject *parent, UtilsNetworking *network, QString daemonAddress);
 | 
			
		||||
 | 
			
		||||
    void sendRawTransaction(const QString &tx_as_hex, bool do_not_relay = false, bool do_sanity_checks = true);
 | 
			
		||||
 | 
			
		||||
    void setDaemonAddress(const QString &daemonAddress);
 | 
			
		||||
    void setNetwork(UtilsNetworking *network);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
    void ApiResponse(DaemonResponse resp);
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
    void onResponse(QNetworkReply *reply, Endpoint endpoint);
 | 
			
		||||
    QString onSendRawTransactionFailed(const QJsonObject &obj);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    UtilsNetworking *m_network;
 | 
			
		||||
    QString m_daemonAddress;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //FEATHER_DAEMON_RPC_H
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +68,7 @@ QByteArray Utils::fileOpenQRC(const QString &path) {
 | 
			
		|||
bool Utils::fileWrite(const QString &path, const QString &data) {
 | 
			
		||||
    QFile file(path);
 | 
			
		||||
    if(file.open(QIODevice::WriteOnly)){
 | 
			
		||||
        QTextStream out(&file); out << data << endl;
 | 
			
		||||
        QTextStream out(&file); out << data << Qt::endl;
 | 
			
		||||
        file.close();
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -362,6 +362,15 @@ void Utils::copyToClipboard(const QString &string){
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::copyFromClipboard() {
 | 
			
		||||
    QClipboard * clipboard = QApplication::clipboard();
 | 
			
		||||
    if (!clipboard) {
 | 
			
		||||
        qWarning() << "Unable to access clipboard";
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
    return clipboard->text();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Utils::blockExplorerLink(const QString &blockExplorer, NetworkType::Type nettype, const QString &txid) {
 | 
			
		||||
    if (blockExplorer == "exploremonero.com") {
 | 
			
		||||
        if (nettype == NetworkType::MAINNET) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,6 +85,7 @@ public:
 | 
			
		|||
    static QStandardItem *qStandardItem(const QString &text);
 | 
			
		||||
    static QStandardItem *qStandardItem(const QString &text, QFont &font);
 | 
			
		||||
    static void copyToClipboard(const QString &string);
 | 
			
		||||
    static QString copyFromClipboard();
 | 
			
		||||
    static QString blockExplorerLink(const QString &blockExplorer, NetworkType::Type nettype, const QString &txid);
 | 
			
		||||
    static QString getUnixAccountName();
 | 
			
		||||
    static QString xdgDesktopEntry();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,6 @@ void XmrToApi::getOrderStatus(const QString &uuid) {
 | 
			
		|||
void XmrToApi::onResponse(QNetworkReply *reply, Endpoint endpoint) {
 | 
			
		||||
    const auto ok = reply->error() == QNetworkReply::NoError;
 | 
			
		||||
    const auto err = reply->errorString();
 | 
			
		||||
    reply->deleteLater();
 | 
			
		||||
 | 
			
		||||
    QByteArray data = reply->readAll();
 | 
			
		||||
    QJsonObject obj;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +63,7 @@ void XmrToApi::onResponse(QNetworkReply *reply, Endpoint endpoint) {
 | 
			
		|||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    reply->deleteLater();
 | 
			
		||||
    emit ApiResponse(XmrToResponse(true, endpoint, "", obj));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue