mirror of
https://github.com/wownero/wowlet.git
synced 2026-11-12 19:24:13 +01:00
Offline transaction signing
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
+10
-1
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user