Browse Source

Merge pull request #183 from miodragpop/dev

Qtification - 1st round
pull/184/head
Duke Leto 4 years ago
committed by GitHub
parent
commit
97b21b2e57
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      silentdragon.pro
  2. 18928
      src/3rdparty/json/json.hpp
  3. 45
      src/connection.cpp
  4. 36
      src/connection.h
  5. 45
      src/mainwindow.cpp
  6. 4
      src/mainwindow.h
  7. 1
      src/precompiled.h
  8. 414
      src/rpc.cpp
  9. 40
      src/rpc.h
  10. 1
      src/sendtab.cpp
  11. 41
      src/settings.cpp
  12. 22
      src/settings.h
  13. 4
      src/websockets.cpp

2
silentdragon.pro

@ -25,6 +25,7 @@ DEFINES += \
QT_DEPRECATED_WARNINGS QT_DEPRECATED_WARNINGS
INCLUDEPATH += src/3rdparty/ INCLUDEPATH += src/3rdparty/
INCLUDEPATH += src/
mac: LIBS+= -Wl,-dead_strip mac: LIBS+= -Wl,-dead_strip
mac: LIBS+= -Wl,-dead_strip_dylibs mac: LIBS+= -Wl,-dead_strip_dylibs
@ -72,7 +73,6 @@ HEADERS += \
src/3rdparty/qrcode/BitBuffer.hpp \ src/3rdparty/qrcode/BitBuffer.hpp \
src/3rdparty/qrcode/QrCode.hpp \ src/3rdparty/qrcode/QrCode.hpp \
src/3rdparty/qrcode/QrSegment.hpp \ src/3rdparty/qrcode/QrSegment.hpp \
src/3rdparty/json/json.hpp \
src/settings.h \ src/settings.h \
src/txtablemodel.h \ src/txtablemodel.h \
src/senttxstore.h \ src/senttxstore.h \

18928
src/3rdparty/json/json.hpp

File diff suppressed because it is too large

45
src/connection.cpp

@ -9,7 +9,6 @@
#include "precompiled.h" #include "precompiled.h"
using json = nlohmann::json;
ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) { ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
this->main = main; this->main = main;
@ -477,7 +476,7 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> c
void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<void(void)> refused) { void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<void(void)> refused) {
main->logger->write("refreshing state"); main->logger->write("refreshing state");
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "getinfo"} {"method", "getinfo"}
@ -489,10 +488,10 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
// Delay 1 second to ensure loading (splash) is seen at least 1 second. // Delay 1 second to ensure loading (splash) is seen at least 1 second.
QTimer::singleShot(1000, [=]() { this->doRPCSetConnection(connection); }); QTimer::singleShot(1000, [=]() { this->doRPCSetConnection(connection); });
}, },
[=] (auto reply, auto res) { [=] (QNetworkReply* reply, const QJsonValue &res) {
// Failed, see what it is. // Failed, see what it is.
auto err = reply->error(); auto err = reply->error();
//qDebug() << err << ":" << QString::fromStdString(res.dump()); //qDebug() << err << res;
if (err == QNetworkReply::NetworkError::ConnectionRefusedError) { if (err == QNetworkReply::NetworkError::ConnectionRefusedError) {
refused(); refused();
@ -504,9 +503,9 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
this->showError(explanation); this->showError(explanation);
} else if (err == QNetworkReply::NetworkError::InternalServerError && } else if (err == QNetworkReply::NetworkError::InternalServerError &&
!res.is_discarded()) { !res.isNull()) {
// The server is loading, so just poll until it succeeds // The server is loading, so just poll until it succeeds
QString status = QString::fromStdString(res["error"]["message"]); QString status = res["error"].toObject()["message"].toString();
{ {
static int dots = 0; static int dots = 0;
status = status.left(status.length() - 3) + QString(".").repeated(dots); status = status.left(status.length() - 3) + QString(".").repeated(dots);
@ -759,16 +758,19 @@ Connection::~Connection() {
delete request; delete request;
} }
void Connection::doRPC(const json& payload, const std::function<void(json)>& cb, void Connection::doRPC(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb,
const std::function<void(QNetworkReply*, const json&)>& ne) { const std::function<void(QNetworkReply*, const QJsonValue&)>& ne) {
if (shutdownInProgress) { if (shutdownInProgress) {
// Ignoring RPC because shutdown in progress // Ignoring RPC because shutdown in progress
return; return;
} }
qDebug() << "RPC:" << QString::fromStdString(payload["method"]) << QString::fromStdString(payload.dump()); qDebug() << "RPC:" << payload["method"].toString() << payload;
QNetworkReply *reply = restclient->post(*request, QByteArray::fromStdString(payload.dump())); QJsonDocument jd_rpc_call(payload.toObject());
QByteArray ba_rpc_call = jd_rpc_call.toJson();
QNetworkReply *reply = restclient->post(*request, ba_rpc_call);
QObject::connect(reply, &QNetworkReply::finished, [=] { QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater(); reply->deleteLater();
@ -777,15 +779,20 @@ void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
return; return;
} }
QJsonDocument jd_reply = QJsonDocument::fromJson(reply->readAll());
QJsonValue parsed;
if (jd_reply.isObject())
parsed = jd_reply.object();
else
parsed = jd_reply.array();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
auto parsed = json::parse(reply->readAll(), nullptr, false);
ne(reply, parsed); ne(reply, parsed);
return; return;
} }
auto parsed = json::parse(reply->readAll(), nullptr, false); if (parsed.isNull()) {
if (parsed.is_discarded()) {
ne(reply, "Unknown error"); ne(reply, "Unknown error");
} }
@ -793,17 +800,17 @@ void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
}); });
} }
void Connection::doRPCWithDefaultErrorHandling(const json& payload, const std::function<void(json)>& cb) { void Connection::doRPCWithDefaultErrorHandling(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb) {
doRPC(payload, cb, [=] (auto reply, auto parsed) { doRPC(payload, cb, [=] (QNetworkReply* reply, const QJsonValue &parsed) {
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) { if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
this->showTxError(QString::fromStdString(parsed["error"]["message"])); this->showTxError(parsed["error"].toObject()["message"].toString());
} else { } else {
this->showTxError(reply->errorString()); this->showTxError(reply->errorString());
} }
}); });
} }
void Connection::doRPCIgnoreError(const json& payload, const std::function<void(json)>& cb) { void Connection::doRPCIgnoreError(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb) {
doRPC(payload, cb, [=] (auto, auto) { doRPC(payload, cb, [=] (auto, auto) {
// Ignored error handling // Ignored error handling
}); });

36
src/connection.h

@ -5,8 +5,6 @@
#include "ui_connection.h" #include "ui_connection.h"
#include "precompiled.h" #include "precompiled.h"
using json = nlohmann::json;
class RPC; class RPC;
enum ConnectionType { enum ConnectionType {
@ -99,19 +97,19 @@ public:
void shutdown(); void shutdown();
void doRPC(const json& payload, const std::function<void(json)>& cb, void doRPC(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb,
const std::function<void(QNetworkReply*, const json&)>& ne); const std::function<void(QNetworkReply*, const QJsonValue&)>& ne);
void doRPCWithDefaultErrorHandling(const json& payload, const std::function<void(json)>& cb); void doRPCWithDefaultErrorHandling(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb);
void doRPCIgnoreError(const json& payload, const std::function<void(json)>& cb) ; void doRPCIgnoreError(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb) ;
void showTxError(const QString& error); void showTxError(const QString& error);
// Batch method. Note: Because of the template, it has to be in the header file. // Batch method. Note: Because of the template, it has to be in the header file.
template<class T> template<class T>
void doBatchRPC(const QList<T>& payloads, void doBatchRPC(const QList<T>& payloads,
std::function<json(T)> payloadGenerator, std::function<QJsonValue(T)> payloadGenerator,
std::function<void(QMap<T, json>*)> cb) { std::function<void(QMap<T, QJsonValue>*)> cb) {
auto responses = new QMap<T, json>(); // zAddr -> list of responses for each call. auto responses = new QMap<T, QJsonValue>(); // zAddr -> list of responses for each call.
int totalSize = payloads.size(); int totalSize = payloads.size();
if (totalSize == 0) if (totalSize == 0)
return; return;
@ -120,17 +118,21 @@ public:
// any overlapping calls // any overlapping calls
static QMap<QString, bool> inProgress; static QMap<QString, bool> inProgress;
QString method = QString::fromStdString(payloadGenerator(payloads[0])["method"]); QString method = payloadGenerator(payloads[0])["method"].toString();
//if (inProgress.value(method, false)) { //if (inProgress.value(method, false)) {
// qDebug() << "In progress batch, skipping"; // qDebug() << "In progress batch, skipping";
// return; // return;
//} //}
for (auto item: payloads) { for (auto item: payloads) {
json payload = payloadGenerator(item); QJsonValue payload = payloadGenerator(item);
inProgress[method] = true; inProgress[method] = true;
QNetworkReply *reply = restclient->post(*request, QByteArray::fromStdString(payload.dump())); QJsonDocument jd_rpc_call(payload.toObject());
QByteArray ba_rpc_call = jd_rpc_call.toJson();
QNetworkReply *reply = restclient->post(*request, ba_rpc_call);
QObject::connect(reply, &QNetworkReply::finished, [=] { QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater(); reply->deleteLater();
@ -140,16 +142,16 @@ public:
} }
auto all = reply->readAll(); auto all = reply->readAll();
auto parsed = json::parse(all.toStdString(), nullptr, false); auto parsed = QJsonDocument::fromJson(all);
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qDebug() << QString::fromStdString(parsed.dump()); qDebug() << parsed.toJson();
qDebug() << reply->errorString(); qDebug() << reply->errorString();
(*responses)[item] = json::object(); // Empty object (*responses)[item] = {}; // Empty object
} else { } else {
if (parsed.is_discarded()) { if (parsed.isEmpty()) {
(*responses)[item] = json::object(); // Empty object (*responses)[item] = {}; // Empty object
} else { } else {
(*responses)[item] = parsed["result"]; (*responses)[item] = parsed["result"];
} }

45
src/mainwindow.cpp

@ -22,7 +22,6 @@
#include "requestdialog.h" #include "requestdialog.h"
#include "websockets.h" #include "websockets.h"
using json = nlohmann::json;
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
@ -280,7 +279,7 @@ void MainWindow::setupSettingsModal() {
Settings::getInstance()->setSaveZtxs(checked); Settings::getInstance()->setSaveZtxs(checked);
}); });
std::string currency_name; QString currency_name;
try { try {
currency_name = Settings::getInstance()->get_currency_name(); currency_name = Settings::getInstance()->get_currency_name();
} catch (const std::exception& e) { } catch (const std::exception& e) {
@ -310,11 +309,11 @@ void MainWindow::setupSettingsModal() {
}); });
// Set local currency // Set local currency
QString ticker = QString::fromStdString( Settings::getInstance()->get_currency_name() ); QString ticker = Settings::getInstance()->get_currency_name();
int currency_index = settings.comboBoxCurrency->findText(ticker, Qt::MatchExactly); int currency_index = settings.comboBoxCurrency->findText(ticker, Qt::MatchExactly);
settings.comboBoxCurrency->setCurrentIndex(currency_index); settings.comboBoxCurrency->setCurrentIndex(currency_index);
QObject::connect(settings.comboBoxCurrency, &QComboBox::currentTextChanged, [=] (QString ticker) { QObject::connect(settings.comboBoxCurrency, &QComboBox::currentTextChanged, [=] (QString ticker) {
this->slot_change_currency(ticker.toStdString()); this->slot_change_currency(ticker);
rpc->refresh(true); rpc->refresh(true);
QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok); QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok);
}); });
@ -625,7 +624,7 @@ void MainWindow::validateAddress() {
if (!ok) if (!ok)
return; return;
getRPC()->validateAddress(address, [=] (json props) { getRPC()->validateAddress(address, [=] (QJsonValue props) {
QDialog d(this); QDialog d(this);
Ui_ValidateAddress va; Ui_ValidateAddress va;
va.setupUi(&d); va.setupUi(&d);
@ -636,11 +635,19 @@ void MainWindow::validateAddress() {
va.lblAddress->setText(address); va.lblAddress->setText(address);
QList<QPair<QString, QString>> propsList; QList<QPair<QString, QString>> propsList;
for (auto it = props.begin(); it != props.end(); it++) {
for (QString property_name: props.toObject().keys()) {
QString property_value;
if (props.toObject()[property_name].isString())
property_value = props.toObject()[property_name].toString();
else
property_value = props.toObject()[property_name].toBool() ? "true" : "false" ;
propsList.append( propsList.append(
QPair<QString, QString>( QPair<QString, QString>( property_name,
QString::fromStdString(it.key()), QString::fromStdString(it.value().dump())) property_value )
); );
} }
@ -916,9 +923,9 @@ void MainWindow::getViewKey(QString addr) {
vui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(true); vui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
}; };
auto fnAddKey = [=](json key) { auto fnAddKey = [=](QJsonValue key) {
QList<QPair<QString, QString>> singleAddrKey; QList<QPair<QString, QString>> singleAddrKey;
singleAddrKey.push_back(QPair<QString, QString>(addr, QString::fromStdString(key.get<json::string_t>()))); singleAddrKey.push_back(QPair<QString, QString>(addr, key.toString()));
fnUpdateUIWithKeys(singleAddrKey); fnUpdateUIWithKeys(singleAddrKey);
}; };
@ -988,9 +995,9 @@ void MainWindow::exportKeys(QString addr) {
rpc->getAllPrivKeys(fnUpdateUIWithKeys); rpc->getAllPrivKeys(fnUpdateUIWithKeys);
} }
else { else {
auto fnAddKey = [=](json key) { auto fnAddKey = [=](QJsonValue key) {
QList<QPair<QString, QString>> singleAddrKey; QList<QPair<QString, QString>> singleAddrKey;
singleAddrKey.push_back(QPair<QString, QString>(addr, QString::fromStdString(key.get<json::string_t>()))); singleAddrKey.push_back(QPair<QString, QString>(addr, key.toString()));
fnUpdateUIWithKeys(singleAddrKey); fnUpdateUIWithKeys(singleAddrKey);
}; };
@ -1168,7 +1175,7 @@ void MainWindow::setupMarketTab() {
auto ticker = s->get_currency_name(); auto ticker = s->get_currency_name();
ui->volume->setText(QString::number((double) s->get_volume("HUSH") ,'f',8) + " HUSH"); ui->volume->setText(QString::number((double) s->get_volume("HUSH") ,'f',8) + " HUSH");
ui->volumeLocal->setText(QString::number((double) s->get_volume(ticker) ,'f',8) + " " + QString::fromStdString(ticker)); ui->volumeLocal->setText(QString::number((double) s->get_volume(ticker) ,'f',8) + " " + ticker);
ui->volumeBTC->setText(QString::number((double) s->get_volume("BTC") ,'f',8) + " BTC"); ui->volumeBTC->setText(QString::number((double) s->get_volume("BTC") ,'f',8) + " BTC");
} }
@ -1285,8 +1292,8 @@ void MainWindow::setupTransactionsTab() {
} }
void MainWindow::addNewZaddr() { void MainWindow::addNewZaddr() {
rpc->newZaddr( [=] (json reply) { rpc->newZaddr( [=] (QJsonValue reply) {
QString addr = QString::fromStdString(reply.get<json::string_t>()); QString addr = reply.toString();
// Make sure the RPC class reloads the z-addrs for future use // Make sure the RPC class reloads the z-addrs for future use
rpc->refreshAddresses(); rpc->refreshAddresses();
@ -1329,9 +1336,9 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
void MainWindow::setupReceiveTab() { void MainWindow::setupReceiveTab() {
auto addNewTAddr = [=] () { auto addNewTAddr = [=] () {
rpc->newTaddr([=] (json reply) { rpc->newTaddr([=] (QJsonValue reply) {
qDebug() << "New addr button clicked"; qDebug() << "New addr button clicked";
QString addr = QString::fromStdString(reply.get<json::string_t>()); QString addr = reply.toString();
// Make sure the RPC class reloads the t-addrs for future use // Make sure the RPC class reloads the t-addrs for future use
rpc->refreshAddresses(); rpc->refreshAddresses();
@ -1541,7 +1548,7 @@ void MainWindow::updateLabels() {
updateLabelsAutoComplete(); updateLabelsAutoComplete();
} }
void MainWindow::slot_change_currency(const std::string& currency_name) void MainWindow::slot_change_currency(const QString& currency_name)
{ {
qDebug() << "slot_change_currency"; //<< ": " << currency_name; qDebug() << "slot_change_currency"; //<< ": " << currency_name;
Settings::getInstance()->set_currency_name(currency_name); Settings::getInstance()->set_currency_name(currency_name);
@ -1549,7 +1556,7 @@ void MainWindow::slot_change_currency(const std::string& currency_name)
rpc->refreshPrice(); rpc->refreshPrice();
// Include currency // Include currency
std::string saved_currency_name; QString saved_currency_name;
try { try {
saved_currency_name = Settings::getInstance()->get_currency_name(); saved_currency_name = Settings::getInstance()->get_currency_name();
} catch (const std::exception& e) { } catch (const std::exception& e) {

4
src/mainwindow.h

@ -10,8 +10,6 @@ class Settings;
class WSServer; class WSServer;
class WormholeClient; class WormholeClient;
using json = nlohmann::json;
// Struct used to hold destination info when sending a Tx. // Struct used to hold destination info when sending a Tx.
struct ToFields { struct ToFields {
QString addr; QString addr;
@ -85,7 +83,7 @@ private:
void setupMarketTab(); void setupMarketTab();
void slot_change_theme(const QString& themeName); void slot_change_theme(const QString& themeName);
void slot_change_currency(const std::string& currencyName); void slot_change_currency(const QString& currencyName);
void setupTurnstileDialog(); void setupTurnstileDialog();
void setupSettingsModal(); void setupSettingsModal();
void setupStatusBar(); void setupStatusBar();

1
src/precompiled.h

@ -70,7 +70,6 @@
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
#include "3rdparty/json/json.hpp"
#include "3rdparty/qrcode/QrCode.hpp" #include "3rdparty/qrcode/QrCode.hpp"
#define SODIUM_STATIC #define SODIUM_STATIC

414
src/rpc.cpp

@ -8,7 +8,6 @@
#include "version.h" #include "version.h"
#include "websockets.h" #include "websockets.h"
using json = nlohmann::json;
RPC::RPC(MainWindow* main) { RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this); auto cl = new ConnectionLoader(main, this);
@ -102,18 +101,18 @@ void RPC::setConnection(Connection* c) {
refresh(true); refresh(true);
} }
json RPC::makePayload(std::string method, std::string params) { QJsonValue RPC::makePayload(QString method, QString params) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "42" }, {"id", "42" },
{"method", method }, {"method", method },
{"params", {params}} {"params", QJsonArray {params}}
}; };
return payload; return payload;
} }
json RPC::makePayload(std::string method) { QJsonValue RPC::makePayload(QString method) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "42" }, {"id", "42" },
{"method", method }, {"method", method },
@ -121,41 +120,41 @@ json RPC::makePayload(std::string method) {
return payload; return payload;
} }
void RPC::getTAddresses(const std::function<void(json)>& cb) { void RPC::getTAddresses(const std::function<void(QJsonValue)>& cb) {
std::string method = "getaddressesbyaccount"; QString method = "getaddressesbyaccount";
std::string params = ""; QString params = "";
conn->doRPCWithDefaultErrorHandling(makePayload(method, std::string("")), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method, ""), cb);
} }
void RPC::getZAddresses(const std::function<void(json)>& cb) { void RPC::getZAddresses(const std::function<void(QJsonValue)>& cb) {
std::string method = "z_listaddresses"; QString method = "z_listaddresses";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
} }
void RPC::getTransparentUnspent(const std::function<void(json)>& cb) { void RPC::getTransparentUnspent(const std::function<void(QJsonValue)>& cb) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "listunspent"}, {"method", "listunspent"},
{"params", {0}} // Get UTXOs with 0 confirmations as well. {"params", QJsonArray {0}} // Get UTXOs with 0 confirmations as well.
}; };
conn->doRPCWithDefaultErrorHandling(payload, cb); conn->doRPCWithDefaultErrorHandling(payload, cb);
} }
void RPC::getZUnspent(const std::function<void(json)>& cb) { void RPC::getZUnspent(const std::function<void(QJsonValue)>& cb) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "z_listunspent"}, {"method", "z_listunspent"},
{"params", {0}} // Get UTXOs with 0 confirmations as well. {"params", QJsonArray {0}} // Get UTXOs with 0 confirmations as well.
}; };
conn->doRPCWithDefaultErrorHandling(payload, cb); conn->doRPCWithDefaultErrorHandling(payload, cb);
} }
void RPC::newZaddr(const std::function<void(json)>& cb) { void RPC::newZaddr(const std::function<void(QJsonValue)>& cb) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "z_getnewaddress"}, {"method", "z_getnewaddress"},
@ -165,33 +164,33 @@ void RPC::newZaddr(const std::function<void(json)>& cb) {
conn->doRPCWithDefaultErrorHandling(payload, cb); conn->doRPCWithDefaultErrorHandling(payload, cb);
} }
void RPC::newTaddr(const std::function<void(json)>& cb) { void RPC::newTaddr(const std::function<void(QJsonValue)>& cb) {
std::string method = "getnewaddress"; QString method = "getnewaddress";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
} }
void RPC::getZViewKey(QString addr, const std::function<void(json)>& cb) { void RPC::getZViewKey(QString addr, const std::function<void(QJsonValue)>& cb) {
std::string method = "z_exportviewingkey"; QString method = "z_exportviewingkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
} }
void RPC::getZPrivKey(QString addr, const std::function<void(json)>& cb) { void RPC::getZPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
std::string method = "z_exportkey"; QString method = "z_exportkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
} }
void RPC::getTPrivKey(QString addr, const std::function<void(json)>& cb) { void RPC::getTPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
std::string method = "dumpprivkey"; QString method = "dumpprivkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
} }
void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(json)>& cb) { void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(QJsonValue)>& cb) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "z_importkey"}, {"method", "z_importkey"},
{"params", { privkey.toStdString(), (rescan? "yes" : "no") }}, {"params", QJsonArray { privkey, (rescan ? "yes" : "no") }},
}; };
conn->doRPCWithDefaultErrorHandling(payload, cb); conn->doRPCWithDefaultErrorHandling(payload, cb);
@ -199,8 +198,8 @@ void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(
// TODO: support rescan height and prefix // TODO: support rescan height and prefix
void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(json)>& cb) { void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(QJsonValue)>& cb) {
json payload; QJsonObject payload;
// If privkey starts with 5, K or L, use old-style Hush params, same as BTC+ZEC // If privkey starts with 5, K or L, use old-style Hush params, same as BTC+ZEC
if( privkey.startsWith("5") || privkey.startsWith("K") || privkey.startsWith("L") ) { if( privkey.startsWith("5") || privkey.startsWith("K") || privkey.startsWith("L") ) {
@ -209,7 +208,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "importprivkey"}, {"method", "importprivkey"},
{"params", { privkey.toStdString(), "", "false", "0", "128" }}, {"params", QJsonArray { privkey, "", "false", "0", "128" }},
}; };
} else { } else {
qDebug() << "Detected new-style HUSH WIF"; qDebug() << "Detected new-style HUSH WIF";
@ -217,7 +216,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "importprivkey"}, {"method", "importprivkey"},
{"params", { privkey.toStdString(), (rescan? "yes" : "no") }}, {"params", QJsonArray { privkey, (rescan? "yes" : "no") }},
}; };
} }
@ -226,39 +225,39 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
conn->doRPCWithDefaultErrorHandling(payload, cb); conn->doRPCWithDefaultErrorHandling(payload, cb);
} }
void RPC::validateAddress(QString address, const std::function<void(json)>& cb) { void RPC::validateAddress(QString address, const std::function<void(QJsonValue)>& cb) {
QString method = address.startsWith("z") ? "z_validateaddress" : "validateaddress"; QString method = address.startsWith("z") ? "z_validateaddress" : "validateaddress";
conn->doRPCWithDefaultErrorHandling(makePayload(method.toStdString(), address.toStdString()), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method, address), cb);
} }
void RPC::getBalance(const std::function<void(json)>& cb) { void RPC::getBalance(const std::function<void(QJsonValue)>& cb) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "z_gettotalbalance"}, {"method", "z_gettotalbalance"},
{"params", {0}} // Get Unconfirmed balance as well. {"params", QJsonArray {0}} // Get Unconfirmed balance as well.
}; };
conn->doRPCWithDefaultErrorHandling(payload, cb); conn->doRPCWithDefaultErrorHandling(payload, cb);
} }
void RPC::getTransactions(const std::function<void(json)>& cb) { void RPC::getTransactions(const std::function<void(QJsonValue)>& cb) {
std::string method = "listtransactions"; QString method = "listtransactions";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
} }
void RPC::sendZTransaction(json params, const std::function<void(json)>& cb, void RPC::sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) { const std::function<void(QString)>& err) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "z_sendmany"}, {"method", "z_sendmany"},
{"params", params} {"params", params}
}; };
conn->doRPC(payload, cb, [=] (auto reply, auto parsed) { conn->doRPC(payload, cb, [=] (QNetworkReply *reply, const QJsonValue &parsed) {
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) { if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
err(QString::fromStdString(parsed["error"]["message"])); err(parsed["error"].toObject()["message"].toString());
} else { } else {
err(reply->errorString()); err(reply->errorString());
} }
@ -299,32 +298,32 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
}; };
// A utility fn to do the batch calling // A utility fn to do the batch calling
auto fnDoBatchGetPrivKeys = [=](json getAddressPayload, std::string privKeyDumpMethodName) { auto fnDoBatchGetPrivKeys = [=](QJsonValue getAddressPayload, QString privKeyDumpMethodName) {
conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (json resp) { conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (QJsonValue resp) {
QList<QString> addrs; QList<QString> addrs;
for (auto addr : resp.get<json::array_t>()) { for (auto addr : resp.toArray()) {
addrs.push_back(QString::fromStdString(addr.get<json::string_t>())); addrs.push_back(addr.toString());
} }
// Then, do a batch request to get all the private keys // Then, do a batch request to get all the private keys
conn->doBatchRPC<QString>( conn->doBatchRPC<QString>(
addrs, addrs,
[=] (auto addr) { [=] (auto addr) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", privKeyDumpMethodName}, {"method", privKeyDumpMethodName},
{"params", { addr.toStdString() }}, {"params", QJsonArray { addr }},
}; };
return payload; return payload;
}, },
[=] (QMap<QString, json>* privkeys) { [=] (QMap<QString, QJsonValue>* privkeys) {
QList<QPair<QString, QString>> allTKeys; QList<QPair<QString, QString>> allTKeys;
for (QString addr: privkeys->keys()) { for (QString addr: privkeys->keys()) {
allTKeys.push_back( allTKeys.push_back(
QPair<QString, QString>( QPair<QString, QString>(
addr, addr,
QString::fromStdString(privkeys->value(addr).get<json::string_t>()))); privkeys->value(addr).toString()));
} }
fnCombineTwoLists(allTKeys); fnCombineTwoLists(allTKeys);
@ -335,14 +334,14 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
}; };
// First get all the t and z addresses. // First get all the t and z addresses.
json payloadT = { QJsonObject payloadT = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "getaddressesbyaccount"}, {"method", "getaddressesbyaccount"},
{"params", {""} } {"params", QJsonArray {""} }
}; };
json payloadZ = { QJsonObject payloadZ = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "z_listaddresses"} {"method", "z_listaddresses"}
@ -354,29 +353,31 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
// Build the RPC JSON Parameters for this tx // Build the RPC JSON Parameters for this tx
void RPC::fillTxJsonParams(json& params, Tx tx) { void RPC::fillTxJsonParams(QJsonArray& params, Tx tx) {
Q_ASSERT(params.is_array());
Q_ASSERT(QJsonValue(params).isArray());
// Get all the addresses and amounts // Get all the addresses and amounts
json allRecepients = json::array(); QJsonArray allRecepients;
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box // For each addr/amt/memo, construct the JSON and also build the confirm dialog box
for (int i=0; i < tx.toAddrs.size(); i++) { for (int i=0; i < tx.toAddrs.size(); i++) {
auto toAddr = tx.toAddrs[i]; auto toAddr = tx.toAddrs[i];
// Construct the JSON params // Construct the JSON params
json rec = json::object(); QJsonObject rec;
rec["address"] = toAddr.addr.toStdString(); rec["address"] = toAddr.addr;
// Force it through string for rounding. Without this, decimal points beyond 8 places // Force it through string for rounding. Without this, decimal points beyond 8 places
// will appear, causing an "invalid amount" error // will appear, causing an "invalid amount" error
rec["amount"] = Settings::getDecimalString(toAddr.amount).toStdString(); //.toDouble(); rec["amount"] = Settings::getDecimalString(toAddr.amount); //.toDouble();
if (toAddr.addr.startsWith("z") && !toAddr.encodedMemo.trimmed().isEmpty()) if (toAddr.addr.startsWith("z") && !toAddr.encodedMemo.trimmed().isEmpty())
rec["memo"] = toAddr.encodedMemo.toStdString(); rec["memo"] = toAddr.encodedMemo;
allRecepients.push_back(rec); allRecepients.push_back(rec);
} }
// Add sender // Add sender
params.push_back(tx.fromAddr.toStdString()); params.push_back(tx.fromAddr);
params.push_back(allRecepients); params.push_back(allRecepients);
// Add fees if custom fees are allowed. // Add fees if custom fees are allowed.
@ -384,6 +385,7 @@ void RPC::fillTxJsonParams(json& params, Tx tx) {
params.push_back(1); // minconf params.push_back(1); // minconf
params.push_back(tx.fee); params.push_back(tx.fee);
} }
} }
@ -440,36 +442,36 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// 1. For each z-Addr, get list of received txs // 1. For each z-Addr, get list of received txs
conn->doBatchRPC<QString>(zaddrs, conn->doBatchRPC<QString>(zaddrs,
[=] (QString zaddr) { [=] (QString zaddr) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "z_lrba"}, {"id", "z_lrba"},
{"method", "z_listreceivedbyaddress"}, {"method", "z_listreceivedbyaddress"},
{"params", {zaddr.toStdString(), 0}} // Accept 0 conf as well. {"params", QJsonArray {zaddr, 0}} // Accept 0 conf as well.
}; };
return payload; return payload;
}, },
[=] (QMap<QString, json>* zaddrTxids) { [=] (QMap<QString, QJsonValue>* zaddrTxids) {
// Process all txids, removing duplicates. This can happen if the same address // Process all txids, removing duplicates. This can happen if the same address
// appears multiple times in a single tx's outputs. // appears multiple times in a single tx's outputs.
QSet<QString> txids; QSet<QString> txids;
QMap<QString, QString> memos; QMap<QString, QString> memos;
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
auto zaddr = it.key(); auto zaddr = it.key();
for (auto& i : it.value().get<json::array_t>()) { for (const auto& i : it.value().toArray()) {
// Mark the address as used // Mark the address as used
usedAddresses->insert(zaddr, true); usedAddresses->insert(zaddr, true);
// Filter out change txs // Filter out change txs
if (! i["change"].get<json::boolean_t>()) { if (! i.toObject()["change"].toBool()) {
auto txid = QString::fromStdString(i["txid"].get<json::string_t>()); auto txid = i.toObject()["txid"].toString();
txids.insert(txid); txids.insert(txid);
// Check for Memos // Check for Memos
QString memoBytes = QString::fromStdString(i["memo"].get<json::string_t>()); QString memoBytes = i.toObject()["memo"].toString();
if (!memoBytes.startsWith("f600")) { if (!memoBytes.startsWith("f600")) {
QString memo(QByteArray::fromHex( QString memo(QByteArray::fromHex(
QByteArray::fromStdString(i["memo"].get<json::string_t>()))); i.toObject()["memo"].toString().toUtf8()));
if (!memo.trimmed().isEmpty()) if (!memo.trimmed().isEmpty())
memos[zaddr + txid] = memo; memos[zaddr + txid] = memo;
} }
@ -480,40 +482,40 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// 2. For all txids, go and get the details of that txid. // 2. For all txids, go and get the details of that txid.
conn->doBatchRPC<QString>(txids.toList(), conn->doBatchRPC<QString>(txids.toList(),
[=] (QString txid) { [=] (QString txid) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "gettx"}, {"id", "gettx"},
{"method", "gettransaction"}, {"method", "gettransaction"},
{"params", {txid.toStdString()}} {"params", QJsonArray {txid}}
}; };
return payload; return payload;
}, },
[=] (QMap<QString, json>* txidDetails) { [=] (QMap<QString, QJsonValue>* txidDetails) {
QList<TransactionItem> txdata; QList<TransactionItem> txdata;
// Combine them both together. For every zAddr's txid, get the amount, fee, confirmations and time // Combine them both together. For every zAddr's txid, get the amount, fee, confirmations and time
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
for (auto& i : it.value().get<json::array_t>()) { for (const auto& i : it.value().toArray()) {
// Filter out change txs // Filter out change txs
if (i["change"].get<json::boolean_t>()) if (i.toObject()["change"].toBool())
continue; continue;
auto zaddr = it.key(); auto zaddr = it.key();
auto txid = QString::fromStdString(i["txid"].get<json::string_t>()); auto txid = i.toObject()["txid"].toString();
// Lookup txid in the map // Lookup txid in the map
auto txidInfo = txidDetails->value(txid); auto txidInfo = txidDetails->value(txid);
qint64 timestamp; qint64 timestamp;
if (txidInfo.find("time") != txidInfo.end()) { if (!txidInfo.toObject()["time"].isUndefined()) {
timestamp = txidInfo["time"].get<json::number_unsigned_t>(); timestamp = txidInfo.toObject()["time"].toInt();
} else { } else {
timestamp = txidInfo["blocktime"].get<json::number_unsigned_t>(); timestamp = txidInfo.toObject()["blocktime"].toInt();
} }
auto amount = i["amount"].get<json::number_float_t>(); auto amount = i.toObject()["amount"].toDouble();
auto confirmations = (unsigned long)txidInfo["confirmations"].get<json::number_unsigned_t>(); auto confirmations = (unsigned long)txidInfo["confirmations"].toInt();
TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount, TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount,
confirmations, "", memos.value(zaddr + txid, "") }; confirmations, "", memos.value(zaddr + txid, "") };
@ -547,12 +549,13 @@ void RPC::getInfoThenRefresh(bool force) {
return noConnection(); return noConnection();
static bool prevCallSucceeded = false; static bool prevCallSucceeded = false;
std::string method = "getinfo"; QString method = "getinfo";
conn->doRPC(makePayload(method), [=] (const json& reply) {
conn->doRPC(makePayload(method), [=] (const QJsonValue& reply) {
prevCallSucceeded = true; prevCallSucceeded = true;
// Testnet? // Testnet?
if (!reply["testnet"].is_null()) { if (!reply["testnet"].isNull()) {
Settings::getInstance()->setTestnet(reply["testnet"].get<json::boolean_t>()); Settings::getInstance()->setTestnet(reply["testnet"].toBool());
}; };
// TODO: checkmark only when getinfo.synced == true! // TODO: checkmark only when getinfo.synced == true!
@ -561,20 +564,20 @@ void RPC::getInfoThenRefresh(bool force) {
main->statusIcon->setPixmap(i.pixmap(16, 16)); main->statusIcon->setPixmap(i.pixmap(16, 16));
static int lastBlock = 0; static int lastBlock = 0;
int curBlock = reply["blocks"].get<json::number_integer_t>(); int curBlock = reply["blocks"].toInt();
int longestchain = reply["longestchain"].get<json::number_integer_t>(); int longestchain = reply["longestchain"].toInt();
int version = reply["version"].get<json::number_integer_t>(); int version = reply["version"].toInt();
int p2pport = reply["p2pport"].get<json::number_integer_t>(); int p2pport = reply["p2pport"].toInt();
int rpcport = reply["rpcport"].get<json::number_integer_t>(); int rpcport = reply["rpcport"].toInt();
int notarized = reply["notarized"].get<json::number_integer_t>(); int notarized = reply["notarized"].toInt();
int protocolversion = reply["protocolversion"].get<json::number_integer_t>(); int protocolversion = reply["protocolversion"].toInt();
int lag = curBlock - notarized; int lag = curBlock - notarized;
int blocks_until_halving= 340000 - curBlock; int blocks_until_halving= 340000 - curBlock;
char halving_days[8]; char halving_days[8];
sprintf(halving_days, "%.2f", (double) (blocks_until_halving * 150) / (60*60*24) ); sprintf(halving_days, "%.2f", (double) (blocks_until_halving * 150) / (60*60*24) );
QString ntzhash = QString::fromStdString( reply["notarizedhash"].get<json::string_t>() ); QString ntzhash = reply["notarizedhash"].toString();
QString ntztxid = QString::fromStdString( reply["notarizedtxid"].get<json::string_t>() ); QString ntztxid = reply["notarizedtxid"].toString();
QString kmdver = QString::fromStdString( reply["KMDversion"].get<json::string_t>() ); QString kmdver = reply["KMDversion"].toString();
Settings::getInstance()->setZcashdVersion(version); Settings::getInstance()->setZcashdVersion(version);
@ -598,7 +601,7 @@ void RPC::getInfoThenRefresh(bool force) {
refreshTransactions(); refreshTransactions();
} }
int connections = reply["connections"].get<json::number_integer_t>(); int connections = reply["connections"].toInt();
Settings::getInstance()->setPeers(connections); Settings::getInstance()->setPeers(connections);
if (connections == 0) { if (connections == 0) {
@ -608,15 +611,15 @@ void RPC::getInfoThenRefresh(bool force) {
} }
// Get network sol/s // Get network sol/s
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "someid"}, {"id", "someid"},
{"method", "getnetworksolps"} {"method", "getnetworksolps"}
}; };
std::string method = "getnetworksolps"; QString method = "getnetworksolps";
conn->doRPCIgnoreError(makePayload(method), [=](const json& reply) { conn->doRPCIgnoreError(makePayload(method), [=](const QJsonValue& reply) {
qint64 solrate = reply.get<json::number_unsigned_t>(); qint64 solrate = reply.toInt();
ui->numconnections->setText(QString::number(connections)); ui->numconnections->setText(QString::number(connections));
ui->solrate->setText(QString::number(solrate) % " Sol/s"); ui->solrate->setText(QString::number(solrate) % " Sol/s");
@ -629,42 +632,42 @@ void RPC::getInfoThenRefresh(bool force) {
{"method", "getnetworkinfo"} {"method", "getnetworkinfo"}
}; };
conn->doRPCIgnoreError(payload, [=](const json& reply) { conn->doRPCIgnoreError(payload, [=](const QJsonValue& reply) {
QString clientname = QString::fromStdString( reply["subversion"].get<json::string_t>() ); QString clientname = reply["subversion"].toString();
QString localservices = QString::fromStdString( reply["localservices"].get<json::string_t>() ); QString localservices = reply["localservices"].toString();
ui->clientname->setText(clientname); ui->clientname->setText(clientname);
ui->localservices->setText(localservices); ui->localservices->setText(localservices);
}); });
conn->doRPCIgnoreError(makePayload("getwalletinfo"), [=](const json& reply) { conn->doRPCIgnoreError(makePayload("getwalletinfo"), [=](const QJsonValue& reply) {
int txcount = reply["txcount"].get<json::number_integer_t>(); int txcount = reply["txcount"].toInt();
ui->txcount->setText(QString::number(txcount)); ui->txcount->setText(QString::number(txcount));
}); });
//TODO: If -zindex is enabled, show stats //TODO: If -zindex is enabled, show stats
conn->doRPCIgnoreError(makePayload("getchaintxstats"), [=](const json& reply) { conn->doRPCIgnoreError(makePayload("getchaintxstats"), [=](const QJsonValue& reply) {
int txcount = reply["txcount"].get<json::number_integer_t>(); int txcount = reply["txcount"].toInt();
ui->chaintxcount->setText(QString::number(txcount)); ui->chaintxcount->setText(QString::number(txcount));
}); });
// Call to see if the blockchain is syncing. // Call to see if the blockchain is syncing.
conn->doRPCIgnoreError(makePayload("getblockchaininfo"), [=](const json& reply) { conn->doRPCIgnoreError(makePayload("getblockchaininfo"), [=](const QJsonValue& reply) {
auto progress = reply["verificationprogress"].get<double>(); auto progress = reply["verificationprogress"].toDouble();
// TODO: use getinfo.synced // TODO: use getinfo.synced
bool isSyncing = progress < 0.9999; // 99.99% bool isSyncing = progress < 0.9999; // 99.99%
int blockNumber = reply["blocks"].get<json::number_unsigned_t>(); int blockNumber = reply["blocks"].toInt();
int estimatedheight = 0; int estimatedheight = 0;
if (reply.find("estimatedheight") != reply.end()) { if (!reply.toObject()["estimatedheight"].isUndefined()) {
estimatedheight = reply["estimatedheight"].get<json::number_unsigned_t>(); estimatedheight = reply["estimatedheight"].toInt();
} }
auto s = Settings::getInstance(); auto s = Settings::getInstance();
s->setSyncing(isSyncing); s->setSyncing(isSyncing);
s->setBlockNumber(blockNumber); s->setBlockNumber(blockNumber);
std::string ticker = s->get_currency_name(); QString ticker = s->get_currency_name();
// Update hushd tab // Update hushd tab
if (isSyncing) { if (isSyncing) {
@ -690,7 +693,7 @@ void RPC::getInfoThenRefresh(bool force) {
} }
QString price = ""; QString price = "";
if (ticker_price > 0) { if (ticker_price > 0) {
price = QString(", ") % "HUSH" % "=" % QString::number( (double)ticker_price,'f',8) % " " % QString::fromStdString(ticker) % " " % extra; price = QString(", ") % "HUSH" % "=" % QString::number( (double)ticker_price,'f',8) % " " % ticker % " " % extra;
} }
// Update the status bar // Update the status bar
@ -721,7 +724,7 @@ void RPC::getInfoThenRefresh(bool force) {
main->statusIcon->setToolTip(tooltip); main->statusIcon->setToolTip(tooltip);
}); });
}, [=](QNetworkReply* reply, const json&) { }, [=](QNetworkReply* reply, const QJsonValue&) {
// hushd has probably disappeared. // hushd has probably disappeared.
this->noConnection(); this->noConnection();
@ -744,9 +747,9 @@ void RPC::refreshAddresses() {
auto newzaddresses = new QList<QString>(); auto newzaddresses = new QList<QString>();
getZAddresses([=] (json reply) { getZAddresses([=] (QJsonValue reply) {
for (auto& it : reply.get<json::array_t>()) { for (const auto& it : reply.toArray()) {
auto addr = QString::fromStdString(it.get<json::string_t>()); auto addr = it.toString();
newzaddresses->push_back(addr); newzaddresses->push_back(addr);
} }
@ -760,9 +763,9 @@ void RPC::refreshAddresses() {
auto newtaddresses = new QList<QString>(); auto newtaddresses = new QList<QString>();
getTAddresses([=] (json reply) { getTAddresses([=] (QJsonValue reply) {
for (auto& it : reply.get<json::array_t>()) { for (const auto& it : reply.toArray()) {
auto addr = QString::fromStdString(it.get<json::string_t>()); auto addr = it.toString();
if (Settings::isTAddress(addr)) if (Settings::isTAddress(addr))
newtaddresses->push_back(addr); newtaddresses->push_back(addr);
} }
@ -784,21 +787,21 @@ void RPC::updateUI(bool anyUnconfirmed) {
}; };
// Function to process reply of the listunspent and z_listunspent API calls, used below. // Function to process reply of the listunspent and z_listunspent API calls, used below.
bool RPC::processUnspent(const json& reply, QMap<QString, double>* balancesMap, QList<UnspentOutput>* newUtxos) { bool RPC::processUnspent(const QJsonValue& reply, QMap<QString, double>* balancesMap, QList<UnspentOutput>* newUtxos) {
bool anyUnconfirmed = false; bool anyUnconfirmed = false;
for (auto& it : reply.get<json::array_t>()) { for (const auto& it : reply.toArray()) {
QString qsAddr = QString::fromStdString(it["address"]); QString qsAddr = it.toObject()["address"].toString();
auto confirmations = it["confirmations"].get<json::number_unsigned_t>(); auto confirmations = it.toObject()["confirmations"].toInt();
if (confirmations == 0) { if (confirmations == 0) {
anyUnconfirmed = true; anyUnconfirmed = true;
} }
newUtxos->push_back( newUtxos->push_back(
UnspentOutput{ qsAddr, QString::fromStdString(it["txid"]), UnspentOutput{ qsAddr, it.toObject()["txid"].toString(),
Settings::getDecimalString(it["amount"].get<json::number_float_t>()), Settings::getDecimalString(it.toObject()["amount"].toDouble()),
(int)confirmations, it["spendable"].get<json::boolean_t>() }); (int)confirmations, it.toObject()["spendable"].toBool() });
(*balancesMap)[qsAddr] = (*balancesMap)[qsAddr] + it["amount"].get<json::number_float_t>(); (*balancesMap)[qsAddr] = (*balancesMap)[qsAddr] + it.toObject()["amount"].toDouble();
} }
return anyUnconfirmed; return anyUnconfirmed;
}; };
@ -808,10 +811,11 @@ void RPC::refreshBalances() {
return noConnection(); return noConnection();
// 1. Get the Balances // 1. Get the Balances
getBalance([=] (json reply) { getBalance([=] (QJsonValue reply) {
auto balT = QString::fromStdString(reply["transparent"]).toDouble();
auto balZ = QString::fromStdString(reply["private"]).toDouble(); auto balT = reply["transparent"].toString().toDouble();
auto balTotal = QString::fromStdString(reply["total"]).toDouble(); auto balZ = reply["private"].toString().toDouble();
auto balTotal = reply["total"].toString().toDouble();
AppDataModel::getInstance()->setBalances(balT, balZ); AppDataModel::getInstance()->setBalances(balT, balZ);
@ -833,10 +837,10 @@ void RPC::refreshBalances() {
auto newBalances = new QMap<QString, double>(); auto newBalances = new QMap<QString, double>();
// Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI // Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI
getTransparentUnspent([=] (json reply) { getTransparentUnspent([=] (QJsonValue reply) {
auto anyTUnconfirmed = processUnspent(reply, newBalances, newUtxos); auto anyTUnconfirmed = processUnspent(reply, newBalances, newUtxos);
getZUnspent([=] (json reply) { getZUnspent([=] (QJsonValue reply) {
auto anyZUnconfirmed = processUnspent(reply, newBalances, newUtxos); auto anyZUnconfirmed = processUnspent(reply, newBalances, newUtxos);
// Swap out the balances and UTXOs // Swap out the balances and UTXOs
@ -857,24 +861,24 @@ void RPC::refreshTransactions() {
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
getTransactions([=] (json reply) { getTransactions([=] (QJsonValue reply) {
QList<TransactionItem> txdata; QList<TransactionItem> txdata;
for (auto& it : reply.get<json::array_t>()) { for (const auto& it : reply.toArray()) {
double fee = 0; double fee = 0;
if (!it["fee"].is_null()) { if (!it.toObject()["fee"].isNull()) {
fee = it["fee"].get<json::number_float_t>(); fee = it.toObject()["fee"].toDouble();
} }
QString address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"])); QString address = (it.toObject()["address"].isNull() ? "" : it.toObject()["address"].toString());
TransactionItem tx{ TransactionItem tx{
QString::fromStdString(it["category"]), it.toObject()["category"].toString(),
(qint64)it["time"].get<json::number_unsigned_t>(), (qint64)it.toObject()["time"].toInt(),
address, address,
QString::fromStdString(it["txid"]), it.toObject()["txid"].toString(),
it["amount"].get<json::number_float_t>() + fee, it.toObject()["amount"].toDouble() + fee,
(unsigned long)it["confirmations"].get<json::number_unsigned_t>(), (unsigned long)it.toObject()["confirmations"].toInt(),
"", "" }; "", "" };
txdata.push_back(tx); txdata.push_back(tx);
@ -910,16 +914,16 @@ void RPC::refreshSentZTrans() {
// Look up all the txids to get the confirmation count for them. // Look up all the txids to get the confirmation count for them.
conn->doBatchRPC<QString>(txids, conn->doBatchRPC<QString>(txids,
[=] (QString txid) { [=] (QString txid) {
json payload = { QJsonObject payload = {
{"jsonrpc", "1.0"}, {"jsonrpc", "1.0"},
{"id", "senttxid"}, {"id", "senttxid"},
{"method", "gettransaction"}, {"method", "gettransaction"},
{"params", {txid.toStdString()}} {"params", QJsonArray {txid}}
}; };
return payload; return payload;
}, },
[=] (QMap<QString, json>* txidList) { [=] (QMap<QString, QJsonValue>* txidList) {
auto newSentZTxs = sentZTxs; auto newSentZTxs = sentZTxs;
// Update the original sent list with the confirmation count // Update the original sent list with the confirmation count
// TODO: This whole thing is kinda inefficient. We should probably just update the file // TODO: This whole thing is kinda inefficient. We should probably just update the file
@ -927,11 +931,11 @@ void RPC::refreshSentZTrans() {
// sent items. // sent items.
for (TransactionItem& sentTx: newSentZTxs) { for (TransactionItem& sentTx: newSentZTxs) {
auto j = txidList->value(sentTx.txid); auto j = txidList->value(sentTx.txid);
if (j.is_null()) if (j.isNull())
continue; continue;
auto error = j["confirmations"].is_null(); auto error = j["confirmations"].isNull();
if (!error) if (!error)
sentTx.confirmations = j["confirmations"].get<json::number_unsigned_t>(); sentTx.confirmations = j["confirmations"].toInt();
} }
transactionsTableModel->addZSentData(newSentZTxs); transactionsTableModel->addZSentData(newSentZTxs);
@ -953,12 +957,12 @@ void RPC::executeTransaction(Tx tx,
const std::function<void(QString opid, QString txid)> computed, const std::function<void(QString opid, QString txid)> computed,
const std::function<void(QString opid, QString errStr)> error) { const std::function<void(QString opid, QString errStr)> error) {
// First, create the json params // First, create the json params
json params = json::array(); QJsonArray params;
fillTxJsonParams(params, tx); fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl; //std::cout << std::setw(2) << params << std::endl;
sendZTransaction(params, [=](const json& reply) { sendZTransaction(params, [=](const QJsonValue& reply) {
QString opid = QString::fromStdString(reply.get<json::string_t>()); QString opid = reply.toString();
// And then start monitoring the transaction // And then start monitoring the transaction
addNewTxToWatch( opid, WatchedTx { opid, tx, computed, error} ); addNewTxToWatch( opid, WatchedTx { opid, tx, computed, error} );
@ -975,35 +979,35 @@ void RPC::watchTxStatus() {
return noConnection(); return noConnection();
// Make an RPC to load pending operation statues // Make an RPC to load pending operation statues
conn->doRPCIgnoreError(makePayload("z_getoperationstatus"), [=] (const json& reply) { conn->doRPCIgnoreError(makePayload("z_getoperationstatus"), [=] (const QJsonValue& reply) {
// conn->doRPCIgnoreError(payload, [=] (const json& reply) { // conn->doRPCIgnoreError(payload, [=] (const json& reply) {
// There's an array for each item in the status // There's an array for each item in the status
for (auto& it : reply.get<json::array_t>()) { for (const auto& it : reply.toArray()) {
// If we were watching this Tx and its status became "success", then we'll show a status bar alert // If we were watching this Tx and its status became "success", then we'll show a status bar alert
QString id = QString::fromStdString(it["id"]); QString id = it.toObject()["id"].toString();
if (watchingOps.contains(id)) { if (watchingOps.contains(id)) {
// log any txs we are watching // log any txs we are watching
// "creation_time": 1515969376, // "creation_time": 1515969376,
// "execution_secs": 50.416337, // "execution_secs": 50.416337,
// And if it ended up successful // And if it ended up successful
QString status = QString::fromStdString(it["status"]); QString status = it.toObject()["status"].toString();
main->loadingLabel->setVisible(false); main->loadingLabel->setVisible(false);
if (status == "success") { if (status == "success") {
auto txid = QString::fromStdString(it["result"]["txid"]); auto txid = it.toObject()["result"].toObject()["txid"].toString();
SentTxStore::addToSentTx(watchingOps[id].tx, txid); SentTxStore::addToSentTx(watchingOps[id].tx, txid);
auto wtx = watchingOps[id]; auto wtx = watchingOps[id];
watchingOps.remove(id); watchingOps.remove(id);
wtx.completed(id, txid); wtx.completed(id, txid);
qDebug() << "opid "<< id << " started at "<<QString::number((unsigned int)it["creation_time"])<<" took " << QString::number((double)it["execution_secs"]) << " seconds"; qDebug() << "opid "<< id << " started at "<<QString::number((unsigned int)it.toObject()["creation_time"].toInt()) << " took " << QString::number((double)it.toObject()["execution_secs"].toDouble()) << " seconds";
// Refresh balances to show unconfirmed balances // Refresh balances to show unconfirmed balances
refresh(true); refresh(true);
} else if (status == "failed") { } else if (status == "failed") {
// If it failed, then we'll actually show a warning. // If it failed, then we'll actually show a warning.
auto errorMsg = QString::fromStdString(it["error"]["message"]); auto errorMsg = it.toObject()["error"].toObject()["message"].toString();
auto wtx = watchingOps[id]; auto wtx = watchingOps[id];
watchingOps.remove(id); watchingOps.remove(id);
@ -1116,11 +1120,18 @@ void RPC::refreshPrice() {
reply->deleteLater(); reply->deleteLater();
try { try {
QByteArray ba_raw_reply = reply->readAll();
QString raw_reply = QString::fromUtf8(ba_raw_reply);
QByteArray unescaped_raw_reply = raw_reply.toUtf8();
QJsonDocument jd_reply = QJsonDocument::fromJson(unescaped_raw_reply);
QJsonObject parsed = jd_reply.object();
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Parsing price feed response"; qDebug() << "Parsing price feed response";
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) { if (!parsed.isEmpty() && !parsed["error"].toObject()["message"].isNull()) {
qDebug() << QString::fromStdString(parsed["error"]["message"]); qDebug() << parsed["error"].toObject()["message"].toString();
} else { } else {
qDebug() << reply->errorString(); qDebug() << reply->errorString();
} }
@ -1130,9 +1141,8 @@ void RPC::refreshPrice() {
} }
qDebug() << "No network errors"; qDebug() << "No network errors";
auto all = reply->readAll();
auto parsed = json::parse(all, nullptr, false); if (parsed.isEmpty()) {
if (parsed.is_discarded()) {
s->setZECPrice(0); s->setZECPrice(0);
s->setBTCPrice(0); s->setBTCPrice(0);
return; return;
@ -1140,51 +1150,53 @@ void RPC::refreshPrice() {
qDebug() << "Parsed JSON"; qDebug() << "Parsed JSON";
const json& item = parsed.get<json::object_t>(); const QJsonValue& item = parsed;
const json& hush = item["hush"].get<json::object_t>(); const QJsonValue& hush = item["hush"].toObject();
std::string ticker = s->get_currency_name(); QString ticker = s->get_currency_name();
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::tolower(c); }); ticker = ticker.toLower();
fprintf(stderr,"ticker=%s\n", ticker.c_str()); fprintf(stderr,"ticker=%s\n", ticker.toLocal8Bit().data());
//qDebug() << "Ticker = " + ticker; //qDebug() << "Ticker = " + ticker;
if (hush[ticker] >= 0) { if (!hush[ticker].isUndefined()) {
qDebug() << "Found hush key in price json"; qDebug() << "Found hush key in price json";
//QString price = QString::fromStdString(hush["usd"].get<json::string_t>()); //QString price = hush["usd"].toString());
qDebug() << "HUSH = $" << QString::number((double)hush["usd"]) << " USD"; qDebug() << "HUSH = $" << QString::number(hush["usd"].toDouble()) << " USD";
qDebug() << "HUSH = " << QString::number((double)hush["eur"]) << " EUR"; qDebug() << "HUSH = " << QString::number(hush["eur"].toDouble()) << " EUR";
qDebug() << "HUSH = " << QString::number((int) 100000000 * (double) hush["btc"]) << " sat "; qDebug() << "HUSH = " << QString::number((int) 100000000 * hush["btc"].toDouble()) << " sat ";
s->setZECPrice( hush[ticker] ); s->setZECPrice( hush[ticker].toDouble() );
s->setBTCPrice( (unsigned int) 100000000 * (double)hush["btc"] ); s->setBTCPrice( (unsigned int) 100000000 * hush["btc"].toDouble() );
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::tolower(c); }); ticker = ticker.toLower();
qDebug() << "ticker=" << QString::fromStdString(ticker); qDebug() << "ticker=" << ticker;
// TODO: work harder to prevent coredumps! // TODO: work harder to prevent coredumps!
auto price = hush[ticker]; auto price = hush[ticker].toDouble();
auto vol = hush[ticker + "_24h_vol"]; auto vol = hush[ticker + "_24h_vol"].toDouble();
auto mcap = hush[ticker + "_market_cap"]; auto mcap = hush[ticker + "_market_cap"].toDouble();
auto btcprice = hush["btc"]; auto btcprice = hush["btc"].toDouble();
auto btcvol = hush["btc_24h_vol"]; auto btcvol = hush["btc_24h_vol"].toDouble();
auto btcmcap = hush["btc_market_cap"]; auto btcmcap = hush["btc_market_cap"].toDouble();
s->set_price(ticker, price); s->set_price(ticker, price);
s->set_volume(ticker, vol); s->set_volume(ticker, vol);
s->set_volume("BTC", btcvol); s->set_volume("BTC", btcvol);
s->set_marketcap(ticker, mcap); s->set_marketcap(ticker, mcap);
qDebug() << "Volume = " << (double) vol; qDebug() << "Volume = " << (double) vol;
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::toupper(c); });
ui->volume->setText( QString::number((double) vol, 'f', 2) + " " + QString::fromStdString(ticker) ); ticker = ticker.toUpper();
ui->volume->setText( QString::number((double) vol, 'f', 2) + " " + ticker );
ui->volumeBTC->setText( QString::number((double) btcvol, 'f', 2) + " BTC" ); ui->volumeBTC->setText( QString::number((double) btcvol, 'f', 2) + " BTC" );
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::toupper(c); });
ticker = ticker.toUpper();
// We don't get an actual HUSH volume stat, so we calculate it // We don't get an actual HUSH volume stat, so we calculate it
if (price > 0) if (price > 0)
ui->volumeLocal->setText( QString::number((double) vol / (double) price) + " HUSH"); ui->volumeLocal->setText( QString::number((double) vol / (double) price) + " HUSH");
qDebug() << "Mcap = " << (double) mcap; qDebug() << "Mcap = " << (double) mcap;
ui->marketcap->setText( QString::number( (double) mcap, 'f', 2) + " " + QString::fromStdString(ticker) ); ui->marketcap->setText( QString::number( (double) mcap, 'f', 2) + " " + ticker );
ui->marketcapBTC->setText( QString::number((double) btcmcap, 'f', 2) + " BTC" ); ui->marketcapBTC->setText( QString::number((double) btcmcap, 'f', 2) + " BTC" );
//ui->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + QString::fromStdString(ticker) ); //ui->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + ticker );
refresh(true); refresh(true);
return; return;
@ -1209,7 +1221,7 @@ void RPC::shutdownZcashd() {
return; return;
} }
std::string method = "stop"; QString method = "stop";
conn->doRPCWithDefaultErrorHandling(makePayload(method), [=](auto) {}); conn->doRPCWithDefaultErrorHandling(makePayload(method), [=](auto) {});
conn->shutdown(); conn->shutdown();

40
src/rpc.h

@ -9,8 +9,6 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "connection.h" #include "connection.h"
using json = nlohmann::json;
class Turnstile; class Turnstile;
struct TransactionItem { struct TransactionItem {
@ -54,8 +52,8 @@ public:
const std::function<void(QString opid, QString txid)> computed, const std::function<void(QString opid, QString txid)> computed,
const std::function<void(QString opid, QString errStr)> error); const std::function<void(QString opid, QString errStr)> error);
void fillTxJsonParams(json& params, Tx tx); void fillTxJsonParams(QJsonArray& params, Tx tx);
void sendZTransaction(json params, const std::function<void(json)>& cb, const std::function<void(QString)>& err); void sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& err);
void watchTxStatus(); void watchTxStatus();
const QMap<QString, WatchedTx> getWatchingTxns() { return watchingOps; } const QMap<QString, WatchedTx> getWatchingTxns() { return watchingOps; }
@ -68,15 +66,15 @@ public:
const QMap<QString, double>* getAllBalances() { return allBalances; } const QMap<QString, double>* getAllBalances() { return allBalances; }
const QMap<QString, bool>* getUsedAddresses() { return usedAddresses; } const QMap<QString, bool>* getUsedAddresses() { return usedAddresses; }
void newZaddr(const std::function<void(json)>& cb); void newZaddr(const std::function<void(QJsonValue)>& cb);
void newTaddr(const std::function<void(json)>& cb); void newTaddr(const std::function<void(QJsonValue)>& cb);
void getZPrivKey(QString addr, const std::function<void(json)>& cb); void getZPrivKey(QString addr, const std::function<void(QJsonValue)>& cb);
void getZViewKey(QString addr, const std::function<void(json)>& cb); void getZViewKey(QString addr, const std::function<void(QJsonValue)>& cb);
void getTPrivKey(QString addr, const std::function<void(json)>& cb); void getTPrivKey(QString addr, const std::function<void(QJsonValue)>& cb);
void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb); void importZPrivKey(QString addr, bool rescan, const std::function<void(QJsonValue)>& cb);
void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb); void importTPrivKey(QString addr, bool rescan, const std::function<void(QJsonValue)>& cb);
void validateAddress(QString address, const std::function<void(json)>& cb); void validateAddress(QString address, const std::function<void(QJsonValue)>& cb);
void shutdownZcashd(); void shutdownZcashd();
void noConnection(); void noConnection();
@ -97,20 +95,20 @@ private:
void refreshSentZTrans(); void refreshSentZTrans();
void refreshReceivedZTrans(QList<QString> zaddresses); void refreshReceivedZTrans(QList<QString> zaddresses);
bool processUnspent (const json& reply, QMap<QString, double>* newBalances, QList<UnspentOutput>* newUtxos); bool processUnspent (const QJsonValue& reply, QMap<QString, double>* newBalances, QList<UnspentOutput>* newUtxos);
void updateUI (bool anyUnconfirmed); void updateUI (bool anyUnconfirmed);
void getInfoThenRefresh(bool force); void getInfoThenRefresh(bool force);
void getBalance(const std::function<void(json)>& cb); void getBalance(const std::function<void(QJsonValue)>& cb);
json makePayload(std::string method, std::string params); QJsonValue makePayload(QString method, QString params);
json makePayload(std::string method); QJsonValue makePayload(QString method);
void getTransparentUnspent (const std::function<void(json)>& cb); void getTransparentUnspent (const std::function<void(QJsonValue)>& cb);
void getZUnspent (const std::function<void(json)>& cb); void getZUnspent (const std::function<void(QJsonValue)>& cb);
void getTransactions (const std::function<void(json)>& cb); void getTransactions (const std::function<void(QJsonValue)>& cb);
void getZAddresses (const std::function<void(json)>& cb); void getZAddresses (const std::function<void(QJsonValue)>& cb);
void getTAddresses (const std::function<void(json)>& cb); void getTAddresses (const std::function<void(QJsonValue)>& cb);
Connection* conn = nullptr; Connection* conn = nullptr;
std::shared_ptr<QProcess> ezcashd = nullptr; std::shared_ptr<QProcess> ezcashd = nullptr;

1
src/sendtab.cpp

@ -10,7 +10,6 @@
#include "recurring.h" #include "recurring.h"
#include <QFileDialog> #include <QFileDialog>
using json = nlohmann::json;
void MainWindow::setupSendTab() { void MainWindow::setupSendTab() {
// Create the validator for send to/amount fields // Create the validator for send to/amount fields

41
src/settings.cpp

@ -163,9 +163,9 @@ double Settings::getZECPrice() {
return zecPrice; return zecPrice;
} }
double Settings::get_price(std::string currency) { double Settings::get_price(QString currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); }); currency = currency.toLower();
QString ticker = QString::fromStdString(currency); QString ticker = currency;
auto search = prices.find(currency); auto search = prices.find(currency);
if (search != prices.end()) { if (search != prices.end()) {
qDebug() << "Found price of " << ticker << " = " << search->second; qDebug() << "Found price of " << ticker << " = " << search->second;
@ -176,21 +176,22 @@ double Settings::get_price(std::string currency) {
} }
} }
void Settings::set_price(std::string curr, double price) { void Settings::set_price(QString curr, double price) {
QString ticker = QString::fromStdString(curr); QString ticker = curr;
qDebug() << "Setting price of " << ticker << "=" << QString::number(price); qDebug() << "Setting price of " << ticker << "=" << QString::number(price);
prices.insert( std::make_pair(curr, price) ); prices.insert( std::make_pair(curr, price) );
prices.insert( std::make_pair(curr, price) );
} }
void Settings::set_volume(std::string curr, double volume) { void Settings::set_volume(QString curr, double volume) {
QString ticker = QString::fromStdString(curr); QString ticker = curr;
qDebug() << "Setting volume of " << ticker << "=" << QString::number(volume); qDebug() << "Setting volume of " << ticker << "=" << QString::number(volume);
volumes.insert( std::make_pair(curr, volume) ); volumes.insert( std::make_pair(curr, volume) );
} }
double Settings::get_volume(std::string currency) { double Settings::get_volume(QString currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); }); currency = currency.toLower();
QString ticker = QString::fromStdString(currency); QString ticker = currency;
auto search = volumes.find(currency); auto search = volumes.find(currency);
if (search != volumes.end()) { if (search != volumes.end()) {
qDebug() << "Found volume of " << ticker << " = " << search->second; qDebug() << "Found volume of " << ticker << " = " << search->second;
@ -201,15 +202,15 @@ double Settings::get_volume(std::string currency) {
} }
} }
void Settings::set_marketcap(std::string curr, double marketcap) { void Settings::set_marketcap(QString curr, double marketcap) {
QString ticker = QString::fromStdString(curr); QString ticker = curr;
qDebug() << "Setting marketcap of " << ticker << "=" << QString::number(marketcap); qDebug() << "Setting marketcap of " << ticker << "=" << QString::number(marketcap);
marketcaps.insert( std::make_pair(curr, marketcap) ); marketcaps.insert( std::make_pair(curr, marketcap) );
} }
double Settings::get_marketcap(std::string currency) { double Settings::get_marketcap(QString currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); }); currency = currency.toLower();
QString ticker = QString::fromStdString(currency); QString ticker = currency;
auto search = marketcaps.find(currency); auto search = marketcaps.find(currency);
if (search != marketcaps.end()) { if (search != marketcaps.end()) {
qDebug() << "Found marketcap of " << ticker << " = " << search->second; qDebug() << "Found marketcap of " << ticker << " = " << search->second;
@ -281,7 +282,7 @@ void Settings::saveRestore(QDialog* d) {
QString Settings::getUSDFormat(double bal) { QString Settings::getUSDFormat(double bal) {
//TODO: respect current locale! //TODO: respect current locale!
return QLocale(QLocale::English).toString(bal * Settings::getInstance()->getZECPrice(), 'f', 8) + " " + QString::fromStdString(Settings::getInstance()->get_currency_name()); return QLocale(QLocale::English).toString(bal * Settings::getInstance()->getZECPrice(), 'f', 8) + " " +Settings::getInstance()->get_currency_name();
} }
QString Settings::getDecimalString(double amt) { QString Settings::getDecimalString(double amt) {
@ -341,13 +342,13 @@ bool Settings::addToZcashConf(QString confLocation, QString line) {
return true; return true;
} }
std::string Settings::get_currency_name() { QString Settings::get_currency_name() {
// Load from the QT Settings. // Load from the QT Settings.
return QSettings().value("options/currency_name", "BTC").toString().toStdString(); return QSettings().value("options/currency_name", "BTC").toString();
} }
void Settings::set_currency_name(std::string currency_name) { void Settings::set_currency_name(QString currency_name) {
QSettings().setValue("options/currency_name", QString::fromStdString(currency_name)); QSettings().setValue("options/currency_name", currency_name);
} }

22
src/settings.h

@ -85,8 +85,8 @@ public:
QString get_theme_name(); QString get_theme_name();
void set_theme_name(QString theme_name); void set_theme_name(QString theme_name);
std::string get_currency_name(); QString get_currency_name();
void set_currency_name(std::string currency_name); void set_currency_name(QString currency_name);
void setUsingZcashConf(QString confLocation); void setUsingZcashConf(QString confLocation);
const QString& getZcashdConfLocation() { return _confLocation; } const QString& getZcashdConfLocation() { return _confLocation; }
@ -97,12 +97,12 @@ public:
double getZECPrice(); double getZECPrice();
double get_fiat_price(); double get_fiat_price();
unsigned int getBTCPrice(); unsigned int getBTCPrice();
double get_price(std::string currency); double get_price(QString currency);
void set_price(std::string currency, double price); void set_price(QString currency, double price);
double get_volume(std::string ticker); double get_volume(QString ticker);
void set_volume(std::string curr, double volume); void set_volume(QString curr, double volume);
double get_marketcap(std::string curr); double get_marketcap(QString curr);
void set_marketcap(std::string curr, double marketcap); void set_marketcap(QString curr, double marketcap);
void setPeers(int peers); void setPeers(int peers);
int getPeers(); int getPeers();
@ -165,9 +165,9 @@ private:
double zecPrice = 0.0; double zecPrice = 0.0;
double fiat_price = 0.0; double fiat_price = 0.0;
unsigned int btcPrice = 0; unsigned int btcPrice = 0;
std::map<std::string, double> prices; std::map<QString, double> prices;
std::map<std::string, double> volumes; std::map<QString, double> volumes;
std::map<std::string, double> marketcaps; std::map<QString, double> marketcaps;
}; };
#endif // SETTINGS_H #endif // SETTINGS_H

4
src/websockets.cpp

@ -784,9 +784,9 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, st
return; return;
} }
json params = json::array(); QJsonArray params;
mainwindow->getRPC()->fillTxJsonParams(params, tx); mainwindow->getRPC()->fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl; //std::cout << std::setw(2) << params << std::endl;
// And send the Tx // And send the Tx
mainwindow->getRPC()->executeTransaction(tx, mainwindow->getRPC()->executeTransaction(tx,

Loading…
Cancel
Save