Browse Source

qtification - 1st round

pull/183/head
miodragpop 4 years ago
parent
commit
2f9838c21f
  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
INCLUDEPATH += src/3rdparty/
INCLUDEPATH += src/
mac: LIBS+= -Wl,-dead_strip
mac: LIBS+= -Wl,-dead_strip_dylibs
@ -72,7 +73,6 @@ HEADERS += \
src/3rdparty/qrcode/BitBuffer.hpp \
src/3rdparty/qrcode/QrCode.hpp \
src/3rdparty/qrcode/QrSegment.hpp \
src/3rdparty/json/json.hpp \
src/settings.h \
src/txtablemodel.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"
using json = nlohmann::json;
ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
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) {
main->logger->write("refreshing state");
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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.
QTimer::singleShot(1000, [=]() { this->doRPCSetConnection(connection); });
},
[=] (auto reply, auto res) {
[=] (QNetworkReply* reply, const QJsonValue &res) {
// Failed, see what it is.
auto err = reply->error();
//qDebug() << err << ":" << QString::fromStdString(res.dump());
//qDebug() << err << res;
if (err == QNetworkReply::NetworkError::ConnectionRefusedError) {
refused();
@ -504,9 +503,9 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
this->showError(explanation);
} else if (err == QNetworkReply::NetworkError::InternalServerError &&
!res.is_discarded()) {
!res.isNull()) {
// 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;
status = status.left(status.length() - 3) + QString(".").repeated(dots);
@ -759,16 +758,19 @@ Connection::~Connection() {
delete request;
}
void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
const std::function<void(QNetworkReply*, const json&)>& ne) {
void Connection::doRPC(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb,
const std::function<void(QNetworkReply*, const QJsonValue&)>& ne) {
if (shutdownInProgress) {
// Ignoring RPC because shutdown in progress
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, [=] {
reply->deleteLater();
@ -777,15 +779,20 @@ void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
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) {
auto parsed = json::parse(reply->readAll(), nullptr, false);
ne(reply, parsed);
return;
}
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (parsed.is_discarded()) {
if (parsed.isNull()) {
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) {
doRPC(payload, cb, [=] (auto reply, auto parsed) {
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
this->showTxError(QString::fromStdString(parsed["error"]["message"]));
void Connection::doRPCWithDefaultErrorHandling(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb) {
doRPC(payload, cb, [=] (QNetworkReply* reply, const QJsonValue &parsed) {
if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
this->showTxError(parsed["error"].toObject()["message"].toString());
} else {
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) {
// Ignored error handling
});

36
src/connection.h

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

45
src/mainwindow.cpp

@ -22,7 +22,6 @@
#include "requestdialog.h"
#include "websockets.h"
using json = nlohmann::json;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
@ -280,7 +279,7 @@ void MainWindow::setupSettingsModal() {
Settings::getInstance()->setSaveZtxs(checked);
});
std::string currency_name;
QString currency_name;
try {
currency_name = Settings::getInstance()->get_currency_name();
} catch (const std::exception& e) {
@ -310,11 +309,11 @@ void MainWindow::setupSettingsModal() {
});
// 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);
settings.comboBoxCurrency->setCurrentIndex(currency_index);
QObject::connect(settings.comboBoxCurrency, &QComboBox::currentTextChanged, [=] (QString ticker) {
this->slot_change_currency(ticker.toStdString());
this->slot_change_currency(ticker);
rpc->refresh(true);
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)
return;
getRPC()->validateAddress(address, [=] (json props) {
getRPC()->validateAddress(address, [=] (QJsonValue props) {
QDialog d(this);
Ui_ValidateAddress va;
va.setupUi(&d);
@ -636,11 +635,19 @@ void MainWindow::validateAddress() {
va.lblAddress->setText(address);
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(
QPair<QString, QString>(
QString::fromStdString(it.key()), QString::fromStdString(it.value().dump()))
QPair<QString, QString>( property_name,
property_value )
);
}
@ -916,9 +923,9 @@ void MainWindow::getViewKey(QString addr) {
vui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
};
auto fnAddKey = [=](json key) {
auto fnAddKey = [=](QJsonValue key) {
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);
};
@ -988,9 +995,9 @@ void MainWindow::exportKeys(QString addr) {
rpc->getAllPrivKeys(fnUpdateUIWithKeys);
}
else {
auto fnAddKey = [=](json key) {
auto fnAddKey = [=](QJsonValue key) {
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);
};
@ -1168,7 +1175,7 @@ void MainWindow::setupMarketTab() {
auto ticker = s->get_currency_name();
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");
}
@ -1285,8 +1292,8 @@ void MainWindow::setupTransactionsTab() {
}
void MainWindow::addNewZaddr() {
rpc->newZaddr( [=] (json reply) {
QString addr = QString::fromStdString(reply.get<json::string_t>());
rpc->newZaddr( [=] (QJsonValue reply) {
QString addr = reply.toString();
// Make sure the RPC class reloads the z-addrs for future use
rpc->refreshAddresses();
@ -1329,9 +1336,9 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
void MainWindow::setupReceiveTab() {
auto addNewTAddr = [=] () {
rpc->newTaddr([=] (json reply) {
rpc->newTaddr([=] (QJsonValue reply) {
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
rpc->refreshAddresses();
@ -1541,7 +1548,7 @@ void MainWindow::updateLabels() {
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;
Settings::getInstance()->set_currency_name(currency_name);
@ -1549,7 +1556,7 @@ void MainWindow::slot_change_currency(const std::string& currency_name)
rpc->refreshPrice();
// Include currency
std::string saved_currency_name;
QString saved_currency_name;
try {
saved_currency_name = Settings::getInstance()->get_currency_name();
} catch (const std::exception& e) {

4
src/mainwindow.h

@ -10,8 +10,6 @@ class Settings;
class WSServer;
class WormholeClient;
using json = nlohmann::json;
// Struct used to hold destination info when sending a Tx.
struct ToFields {
QString addr;
@ -85,7 +83,7 @@ private:
void setupMarketTab();
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 setupSettingsModal();
void setupStatusBar();

1
src/precompiled.h

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

414
src/rpc.cpp

@ -8,7 +8,6 @@
#include "version.h"
#include "websockets.h"
using json = nlohmann::json;
RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this);
@ -102,18 +101,18 @@ void RPC::setConnection(Connection* c) {
refresh(true);
}
json RPC::makePayload(std::string method, std::string params) {
json payload = {
QJsonValue RPC::makePayload(QString method, QString params) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "42" },
{"method", method },
{"params", {params}}
{"params", QJsonArray {params}}
};
return payload;
}
json RPC::makePayload(std::string method) {
json payload = {
QJsonValue RPC::makePayload(QString method) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "42" },
{"method", method },
@ -121,41 +120,41 @@ json RPC::makePayload(std::string method) {
return payload;
}
void RPC::getTAddresses(const std::function<void(json)>& cb) {
std::string method = "getaddressesbyaccount";
std::string params = "";
conn->doRPCWithDefaultErrorHandling(makePayload(method, std::string("")), cb);
void RPC::getTAddresses(const std::function<void(QJsonValue)>& cb) {
QString method = "getaddressesbyaccount";
QString params = "";
conn->doRPCWithDefaultErrorHandling(makePayload(method, ""), cb);
}
void RPC::getZAddresses(const std::function<void(json)>& cb) {
std::string method = "z_listaddresses";
void RPC::getZAddresses(const std::function<void(QJsonValue)>& cb) {
QString method = "z_listaddresses";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
}
void RPC::getTransparentUnspent(const std::function<void(json)>& cb) {
json payload = {
void RPC::getTransparentUnspent(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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);
}
void RPC::getZUnspent(const std::function<void(json)>& cb) {
json payload = {
void RPC::getZUnspent(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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);
}
void RPC::newZaddr(const std::function<void(json)>& cb) {
json payload = {
void RPC::newZaddr(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_getnewaddress"},
@ -165,33 +164,33 @@ void RPC::newZaddr(const std::function<void(json)>& 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);
}
void RPC::getZViewKey(QString addr, const std::function<void(json)>& cb) {
std::string method = "z_exportviewingkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb);
void RPC::getZViewKey(QString addr, const std::function<void(QJsonValue)>& cb) {
QString method = "z_exportviewingkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
}
void RPC::getZPrivKey(QString addr, const std::function<void(json)>& cb) {
std::string method = "z_exportkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb);
void RPC::getZPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
QString method = "z_exportkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
}
void RPC::getTPrivKey(QString addr, const std::function<void(json)>& cb) {
std::string method = "dumpprivkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb);
void RPC::getTPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
QString method = "dumpprivkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
}
void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(json)>& cb) {
json payload = {
void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_importkey"},
{"params", { privkey.toStdString(), (rescan? "yes" : "no") }},
{"params", QJsonArray { privkey, (rescan ? "yes" : "no") }},
};
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
void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(json)>& cb) {
json payload;
void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(QJsonValue)>& cb) {
QJsonObject payload;
// 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") ) {
@ -209,7 +208,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "importprivkey"},
{"params", { privkey.toStdString(), "", "false", "0", "128" }},
{"params", QJsonArray { privkey, "", "false", "0", "128" }},
};
} else {
qDebug() << "Detected new-style HUSH WIF";
@ -217,7 +216,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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);
}
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";
conn->doRPCWithDefaultErrorHandling(makePayload(method.toStdString(), address.toStdString()), cb);
conn->doRPCWithDefaultErrorHandling(makePayload(method, address), cb);
}
void RPC::getBalance(const std::function<void(json)>& cb) {
json payload = {
void RPC::getBalance(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_gettotalbalance"},
{"params", {0}} // Get Unconfirmed balance as well.
{"params", QJsonArray {0}} // Get Unconfirmed balance as well.
};
conn->doRPCWithDefaultErrorHandling(payload, cb);
}
void RPC::getTransactions(const std::function<void(json)>& cb) {
std::string method = "listtransactions";
void RPC::getTransactions(const std::function<void(QJsonValue)>& cb) {
QString method = "listtransactions";
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) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_sendmany"},
{"params", params}
};
conn->doRPC(payload, cb, [=] (auto reply, auto parsed) {
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
err(QString::fromStdString(parsed["error"]["message"]));
conn->doRPC(payload, cb, [=] (QNetworkReply *reply, const QJsonValue &parsed) {
if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
err(parsed["error"].toObject()["message"].toString());
} else {
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
auto fnDoBatchGetPrivKeys = [=](json getAddressPayload, std::string privKeyDumpMethodName) {
conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (json resp) {
auto fnDoBatchGetPrivKeys = [=](QJsonValue getAddressPayload, QString privKeyDumpMethodName) {
conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (QJsonValue resp) {
QList<QString> addrs;
for (auto addr : resp.get<json::array_t>()) {
addrs.push_back(QString::fromStdString(addr.get<json::string_t>()));
for (auto addr : resp.toArray()) {
addrs.push_back(addr.toString());
}
// Then, do a batch request to get all the private keys
conn->doBatchRPC<QString>(
addrs,
[=] (auto addr) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", privKeyDumpMethodName},
{"params", { addr.toStdString() }},
{"params", QJsonArray { addr }},
};
return payload;
},
[=] (QMap<QString, json>* privkeys) {
[=] (QMap<QString, QJsonValue>* privkeys) {
QList<QPair<QString, QString>> allTKeys;
for (QString addr: privkeys->keys()) {
allTKeys.push_back(
QPair<QString, QString>(
addr,
QString::fromStdString(privkeys->value(addr).get<json::string_t>())));
privkeys->value(addr).toString()));
}
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.
json payloadT = {
QJsonObject payloadT = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getaddressesbyaccount"},
{"params", {""} }
{"params", QJsonArray {""} }
};
json payloadZ = {
QJsonObject payloadZ = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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
void RPC::fillTxJsonParams(json& params, Tx tx) {
Q_ASSERT(params.is_array());
void RPC::fillTxJsonParams(QJsonArray& params, Tx tx) {
Q_ASSERT(QJsonValue(params).isArray());
// 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 (int i=0; i < tx.toAddrs.size(); i++) {
auto toAddr = tx.toAddrs[i];
// Construct the JSON params
json rec = json::object();
rec["address"] = toAddr.addr.toStdString();
QJsonObject rec;
rec["address"] = toAddr.addr;
// Force it through string for rounding. Without this, decimal points beyond 8 places
// 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())
rec["memo"] = toAddr.encodedMemo.toStdString();
rec["memo"] = toAddr.encodedMemo;
allRecepients.push_back(rec);
}
// Add sender
params.push_back(tx.fromAddr.toStdString());
params.push_back(tx.fromAddr);
params.push_back(allRecepients);
// 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(tx.fee);
}
}
@ -440,36 +442,36 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// 1. For each z-Addr, get list of received txs
conn->doBatchRPC<QString>(zaddrs,
[=] (QString zaddr) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "z_lrba"},
{"method", "z_listreceivedbyaddress"},
{"params", {zaddr.toStdString(), 0}} // Accept 0 conf as well.
{"params", QJsonArray {zaddr, 0}} // Accept 0 conf as well.
};
return payload;
},
[=] (QMap<QString, json>* zaddrTxids) {
[=] (QMap<QString, QJsonValue>* zaddrTxids) {
// Process all txids, removing duplicates. This can happen if the same address
// appears multiple times in a single tx's outputs.
QSet<QString> txids;
QMap<QString, QString> memos;
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
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
usedAddresses->insert(zaddr, true);
// Filter out change txs
if (! i["change"].get<json::boolean_t>()) {
auto txid = QString::fromStdString(i["txid"].get<json::string_t>());
if (! i.toObject()["change"].toBool()) {
auto txid = i.toObject()["txid"].toString();
txids.insert(txid);
// Check for Memos
QString memoBytes = QString::fromStdString(i["memo"].get<json::string_t>());
QString memoBytes = i.toObject()["memo"].toString();
if (!memoBytes.startsWith("f600")) {
QString memo(QByteArray::fromHex(
QByteArray::fromStdString(i["memo"].get<json::string_t>())));
i.toObject()["memo"].toString().toUtf8()));
if (!memo.trimmed().isEmpty())
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.
conn->doBatchRPC<QString>(txids.toList(),
[=] (QString txid) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "gettx"},
{"method", "gettransaction"},
{"params", {txid.toStdString()}}
{"params", QJsonArray {txid}}
};
return payload;
},
[=] (QMap<QString, json>* txidDetails) {
[=] (QMap<QString, QJsonValue>* txidDetails) {
QList<TransactionItem> txdata;
// 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& i : it.value().get<json::array_t>()) {
for (const auto& i : it.value().toArray()) {
// Filter out change txs
if (i["change"].get<json::boolean_t>())
if (i.toObject()["change"].toBool())
continue;
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
auto txidInfo = txidDetails->value(txid);
qint64 timestamp;
if (txidInfo.find("time") != txidInfo.end()) {
timestamp = txidInfo["time"].get<json::number_unsigned_t>();
if (!txidInfo.toObject()["time"].isUndefined()) {
timestamp = txidInfo.toObject()["time"].toInt();
} else {
timestamp = txidInfo["blocktime"].get<json::number_unsigned_t>();
timestamp = txidInfo.toObject()["blocktime"].toInt();
}
auto amount = i["amount"].get<json::number_float_t>();
auto confirmations = (unsigned long)txidInfo["confirmations"].get<json::number_unsigned_t>();
auto amount = i.toObject()["amount"].toDouble();
auto confirmations = (unsigned long)txidInfo["confirmations"].toInt();
TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount,
confirmations, "", memos.value(zaddr + txid, "") };
@ -547,12 +549,13 @@ void RPC::getInfoThenRefresh(bool force) {
return noConnection();
static bool prevCallSucceeded = false;
std::string method = "getinfo";
conn->doRPC(makePayload(method), [=] (const json& reply) {
QString method = "getinfo";
conn->doRPC(makePayload(method), [=] (const QJsonValue& reply) {
prevCallSucceeded = true;
// Testnet?
if (!reply["testnet"].is_null()) {
Settings::getInstance()->setTestnet(reply["testnet"].get<json::boolean_t>());
if (!reply["testnet"].isNull()) {
Settings::getInstance()->setTestnet(reply["testnet"].toBool());
};
// TODO: checkmark only when getinfo.synced == true!
@ -561,20 +564,20 @@ void RPC::getInfoThenRefresh(bool force) {
main->statusIcon->setPixmap(i.pixmap(16, 16));
static int lastBlock = 0;
int curBlock = reply["blocks"].get<json::number_integer_t>();
int longestchain = reply["longestchain"].get<json::number_integer_t>();
int version = reply["version"].get<json::number_integer_t>();
int p2pport = reply["p2pport"].get<json::number_integer_t>();
int rpcport = reply["rpcport"].get<json::number_integer_t>();
int notarized = reply["notarized"].get<json::number_integer_t>();
int protocolversion = reply["protocolversion"].get<json::number_integer_t>();
int curBlock = reply["blocks"].toInt();
int longestchain = reply["longestchain"].toInt();
int version = reply["version"].toInt();
int p2pport = reply["p2pport"].toInt();
int rpcport = reply["rpcport"].toInt();
int notarized = reply["notarized"].toInt();
int protocolversion = reply["protocolversion"].toInt();
int lag = curBlock - notarized;
int blocks_until_halving= 340000 - curBlock;
char halving_days[8];
sprintf(halving_days, "%.2f", (double) (blocks_until_halving * 150) / (60*60*24) );
QString ntzhash = QString::fromStdString( reply["notarizedhash"].get<json::string_t>() );
QString ntztxid = QString::fromStdString( reply["notarizedtxid"].get<json::string_t>() );
QString kmdver = QString::fromStdString( reply["KMDversion"].get<json::string_t>() );
QString ntzhash = reply["notarizedhash"].toString();
QString ntztxid = reply["notarizedtxid"].toString();
QString kmdver = reply["KMDversion"].toString();
Settings::getInstance()->setZcashdVersion(version);
@ -598,7 +601,7 @@ void RPC::getInfoThenRefresh(bool force) {
refreshTransactions();
}
int connections = reply["connections"].get<json::number_integer_t>();
int connections = reply["connections"].toInt();
Settings::getInstance()->setPeers(connections);
if (connections == 0) {
@ -608,15 +611,15 @@ void RPC::getInfoThenRefresh(bool force) {
}
// Get network sol/s
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getnetworksolps"}
};
std::string method = "getnetworksolps";
conn->doRPCIgnoreError(makePayload(method), [=](const json& reply) {
qint64 solrate = reply.get<json::number_unsigned_t>();
QString method = "getnetworksolps";
conn->doRPCIgnoreError(makePayload(method), [=](const QJsonValue& reply) {
qint64 solrate = reply.toInt();
ui->numconnections->setText(QString::number(connections));
ui->solrate->setText(QString::number(solrate) % " Sol/s");
@ -629,42 +632,42 @@ void RPC::getInfoThenRefresh(bool force) {
{"method", "getnetworkinfo"}
};
conn->doRPCIgnoreError(payload, [=](const json& reply) {
QString clientname = QString::fromStdString( reply["subversion"].get<json::string_t>() );
QString localservices = QString::fromStdString( reply["localservices"].get<json::string_t>() );
conn->doRPCIgnoreError(payload, [=](const QJsonValue& reply) {
QString clientname = reply["subversion"].toString();
QString localservices = reply["localservices"].toString();
ui->clientname->setText(clientname);
ui->localservices->setText(localservices);
});
conn->doRPCIgnoreError(makePayload("getwalletinfo"), [=](const json& reply) {
int txcount = reply["txcount"].get<json::number_integer_t>();
conn->doRPCIgnoreError(makePayload("getwalletinfo"), [=](const QJsonValue& reply) {
int txcount = reply["txcount"].toInt();
ui->txcount->setText(QString::number(txcount));
});
//TODO: If -zindex is enabled, show stats
conn->doRPCIgnoreError(makePayload("getchaintxstats"), [=](const json& reply) {
int txcount = reply["txcount"].get<json::number_integer_t>();
conn->doRPCIgnoreError(makePayload("getchaintxstats"), [=](const QJsonValue& reply) {
int txcount = reply["txcount"].toInt();
ui->chaintxcount->setText(QString::number(txcount));
});
// Call to see if the blockchain is syncing.
conn->doRPCIgnoreError(makePayload("getblockchaininfo"), [=](const json& reply) {
auto progress = reply["verificationprogress"].get<double>();
conn->doRPCIgnoreError(makePayload("getblockchaininfo"), [=](const QJsonValue& reply) {
auto progress = reply["verificationprogress"].toDouble();
// TODO: use getinfo.synced
bool isSyncing = progress < 0.9999; // 99.99%
int blockNumber = reply["blocks"].get<json::number_unsigned_t>();
int blockNumber = reply["blocks"].toInt();
int estimatedheight = 0;
if (reply.find("estimatedheight") != reply.end()) {
estimatedheight = reply["estimatedheight"].get<json::number_unsigned_t>();
if (!reply.toObject()["estimatedheight"].isUndefined()) {
estimatedheight = reply["estimatedheight"].toInt();
}
auto s = Settings::getInstance();
s->setSyncing(isSyncing);
s->setBlockNumber(blockNumber);
std::string ticker = s->get_currency_name();
QString ticker = s->get_currency_name();
// Update hushd tab
if (isSyncing) {
@ -690,7 +693,7 @@ void RPC::getInfoThenRefresh(bool force) {
}
QString price = "";
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
@ -721,7 +724,7 @@ void RPC::getInfoThenRefresh(bool force) {
main->statusIcon->setToolTip(tooltip);
});
}, [=](QNetworkReply* reply, const json&) {
}, [=](QNetworkReply* reply, const QJsonValue&) {
// hushd has probably disappeared.
this->noConnection();
@ -744,9 +747,9 @@ void RPC::refreshAddresses() {
auto newzaddresses = new QList<QString>();
getZAddresses([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
auto addr = QString::fromStdString(it.get<json::string_t>());
getZAddresses([=] (QJsonValue reply) {
for (const auto& it : reply.toArray()) {
auto addr = it.toString();
newzaddresses->push_back(addr);
}
@ -760,9 +763,9 @@ void RPC::refreshAddresses() {
auto newtaddresses = new QList<QString>();
getTAddresses([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
auto addr = QString::fromStdString(it.get<json::string_t>());
getTAddresses([=] (QJsonValue reply) {
for (const auto& it : reply.toArray()) {
auto addr = it.toString();
if (Settings::isTAddress(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.
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;
for (auto& it : reply.get<json::array_t>()) {
QString qsAddr = QString::fromStdString(it["address"]);
auto confirmations = it["confirmations"].get<json::number_unsigned_t>();
for (const auto& it : reply.toArray()) {
QString qsAddr = it.toObject()["address"].toString();
auto confirmations = it.toObject()["confirmations"].toInt();
if (confirmations == 0) {
anyUnconfirmed = true;
}
newUtxos->push_back(
UnspentOutput{ qsAddr, QString::fromStdString(it["txid"]),
Settings::getDecimalString(it["amount"].get<json::number_float_t>()),
(int)confirmations, it["spendable"].get<json::boolean_t>() });
UnspentOutput{ qsAddr, it.toObject()["txid"].toString(),
Settings::getDecimalString(it.toObject()["amount"].toDouble()),
(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;
};
@ -808,10 +811,11 @@ void RPC::refreshBalances() {
return noConnection();
// 1. Get the Balances
getBalance([=] (json reply) {
auto balT = QString::fromStdString(reply["transparent"]).toDouble();
auto balZ = QString::fromStdString(reply["private"]).toDouble();
auto balTotal = QString::fromStdString(reply["total"]).toDouble();
getBalance([=] (QJsonValue reply) {
auto balT = reply["transparent"].toString().toDouble();
auto balZ = reply["private"].toString().toDouble();
auto balTotal = reply["total"].toString().toDouble();
AppDataModel::getInstance()->setBalances(balT, balZ);
@ -833,10 +837,10 @@ void RPC::refreshBalances() {
auto newBalances = new QMap<QString, double>();
// 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);
getZUnspent([=] (json reply) {
getZUnspent([=] (QJsonValue reply) {
auto anyZUnconfirmed = processUnspent(reply, newBalances, newUtxos);
// Swap out the balances and UTXOs
@ -857,24 +861,24 @@ void RPC::refreshTransactions() {
if (conn == nullptr)
return noConnection();
getTransactions([=] (json reply) {
getTransactions([=] (QJsonValue reply) {
QList<TransactionItem> txdata;
for (auto& it : reply.get<json::array_t>()) {
for (const auto& it : reply.toArray()) {
double fee = 0;
if (!it["fee"].is_null()) {
fee = it["fee"].get<json::number_float_t>();
if (!it.toObject()["fee"].isNull()) {
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{
QString::fromStdString(it["category"]),
(qint64)it["time"].get<json::number_unsigned_t>(),
it.toObject()["category"].toString(),
(qint64)it.toObject()["time"].toInt(),
address,
QString::fromStdString(it["txid"]),
it["amount"].get<json::number_float_t>() + fee,
(unsigned long)it["confirmations"].get<json::number_unsigned_t>(),
it.toObject()["txid"].toString(),
it.toObject()["amount"].toDouble() + fee,
(unsigned long)it.toObject()["confirmations"].toInt(),
"", "" };
txdata.push_back(tx);
@ -910,16 +914,16 @@ void RPC::refreshSentZTrans() {
// Look up all the txids to get the confirmation count for them.
conn->doBatchRPC<QString>(txids,
[=] (QString txid) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "senttxid"},
{"method", "gettransaction"},
{"params", {txid.toStdString()}}
{"params", QJsonArray {txid}}
};
return payload;
},
[=] (QMap<QString, json>* txidList) {
[=] (QMap<QString, QJsonValue>* txidList) {
auto newSentZTxs = sentZTxs;
// Update the original sent list with the confirmation count
// TODO: This whole thing is kinda inefficient. We should probably just update the file
@ -927,11 +931,11 @@ void RPC::refreshSentZTrans() {
// sent items.
for (TransactionItem& sentTx: newSentZTxs) {
auto j = txidList->value(sentTx.txid);
if (j.is_null())
if (j.isNull())
continue;
auto error = j["confirmations"].is_null();
auto error = j["confirmations"].isNull();
if (!error)
sentTx.confirmations = j["confirmations"].get<json::number_unsigned_t>();
sentTx.confirmations = j["confirmations"].toInt();
}
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 errStr)> error) {
// First, create the json params
json params = json::array();
QJsonArray params;
fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl;
//std::cout << std::setw(2) << params << std::endl;
sendZTransaction(params, [=](const json& reply) {
QString opid = QString::fromStdString(reply.get<json::string_t>());
sendZTransaction(params, [=](const QJsonValue& reply) {
QString opid = reply.toString();
// And then start monitoring the transaction
addNewTxToWatch( opid, WatchedTx { opid, tx, computed, error} );
@ -975,35 +979,35 @@ void RPC::watchTxStatus() {
return noConnection();
// 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) {
// 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
QString id = QString::fromStdString(it["id"]);
QString id = it.toObject()["id"].toString();
if (watchingOps.contains(id)) {
// log any txs we are watching
// "creation_time": 1515969376,
// "execution_secs": 50.416337,
// And if it ended up successful
QString status = QString::fromStdString(it["status"]);
QString status = it.toObject()["status"].toString();
main->loadingLabel->setVisible(false);
if (status == "success") {
auto txid = QString::fromStdString(it["result"]["txid"]);
auto txid = it.toObject()["result"].toObject()["txid"].toString();
SentTxStore::addToSentTx(watchingOps[id].tx, txid);
auto wtx = watchingOps[id];
watchingOps.remove(id);
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(true);
} else if (status == "failed") {
// 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];
watchingOps.remove(id);
@ -1116,11 +1120,18 @@ void RPC::refreshPrice() {
reply->deleteLater();
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) {
qDebug() << "Parsing price feed response";
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
qDebug() << QString::fromStdString(parsed["error"]["message"]);
if (!parsed.isEmpty() && !parsed["error"].toObject()["message"].isNull()) {
qDebug() << parsed["error"].toObject()["message"].toString();
} else {
qDebug() << reply->errorString();
}
@ -1130,9 +1141,8 @@ void RPC::refreshPrice() {
}
qDebug() << "No network errors";
auto all = reply->readAll();
auto parsed = json::parse(all, nullptr, false);
if (parsed.is_discarded()) {
if (parsed.isEmpty()) {
s->setZECPrice(0);
s->setBTCPrice(0);
return;
@ -1140,51 +1150,53 @@ void RPC::refreshPrice() {
qDebug() << "Parsed JSON";
const json& item = parsed.get<json::object_t>();
const json& hush = item["hush"].get<json::object_t>();
std::string ticker = s->get_currency_name();
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::tolower(c); });
fprintf(stderr,"ticker=%s\n", ticker.c_str());
const QJsonValue& item = parsed;
const QJsonValue& hush = item["hush"].toObject();
QString ticker = s->get_currency_name();
ticker = ticker.toLower();
fprintf(stderr,"ticker=%s\n", ticker.toLocal8Bit().data());
//qDebug() << "Ticker = " + ticker;
if (hush[ticker] >= 0) {
if (!hush[ticker].isUndefined()) {
qDebug() << "Found hush key in price json";
//QString price = QString::fromStdString(hush["usd"].get<json::string_t>());
qDebug() << "HUSH = $" << QString::number((double)hush["usd"]) << " USD";
qDebug() << "HUSH = " << QString::number((double)hush["eur"]) << " EUR";
qDebug() << "HUSH = " << QString::number((int) 100000000 * (double) hush["btc"]) << " sat ";
//QString price = hush["usd"].toString());
qDebug() << "HUSH = $" << QString::number(hush["usd"].toDouble()) << " USD";
qDebug() << "HUSH = " << QString::number(hush["eur"].toDouble()) << " EUR";
qDebug() << "HUSH = " << QString::number((int) 100000000 * hush["btc"].toDouble()) << " sat ";
s->setZECPrice( hush[ticker] );
s->setBTCPrice( (unsigned int) 100000000 * (double)hush["btc"] );
s->setZECPrice( hush[ticker].toDouble() );
s->setBTCPrice( (unsigned int) 100000000 * hush["btc"].toDouble() );
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::tolower(c); });
qDebug() << "ticker=" << QString::fromStdString(ticker);
ticker = ticker.toLower();
qDebug() << "ticker=" << ticker;
// TODO: work harder to prevent coredumps!
auto price = hush[ticker];
auto vol = hush[ticker + "_24h_vol"];
auto mcap = hush[ticker + "_market_cap"];
auto price = hush[ticker].toDouble();
auto vol = hush[ticker + "_24h_vol"].toDouble();
auto mcap = hush[ticker + "_market_cap"].toDouble();
auto btcprice = hush["btc"];
auto btcvol = hush["btc_24h_vol"];
auto btcmcap = hush["btc_market_cap"];
auto btcprice = hush["btc"].toDouble();
auto btcvol = hush["btc_24h_vol"].toDouble();
auto btcmcap = hush["btc_market_cap"].toDouble();
s->set_price(ticker, price);
s->set_volume(ticker, vol);
s->set_volume("BTC", btcvol);
s->set_marketcap(ticker, mcap);
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" );
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
if (price > 0)
ui->volumeLocal->setText( QString::number((double) vol / (double) price) + " HUSH");
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->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + QString::fromStdString(ticker) );
//ui->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + ticker );
refresh(true);
return;
@ -1209,7 +1221,7 @@ void RPC::shutdownZcashd() {
return;
}
std::string method = "stop";
QString method = "stop";
conn->doRPCWithDefaultErrorHandling(makePayload(method), [=](auto) {});
conn->shutdown();

40
src/rpc.h

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

1
src/sendtab.cpp

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

41
src/settings.cpp

@ -163,9 +163,9 @@ double Settings::getZECPrice() {
return zecPrice;
}
double Settings::get_price(std::string currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); });
QString ticker = QString::fromStdString(currency);
double Settings::get_price(QString currency) {
currency = currency.toLower();
QString ticker = currency;
auto search = prices.find(currency);
if (search != prices.end()) {
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) {
QString ticker = QString::fromStdString(curr);
void Settings::set_price(QString curr, double price) {
QString ticker = curr;
qDebug() << "Setting price of " << ticker << "=" << QString::number(price);
prices.insert( std::make_pair(curr, price) );
prices.insert( std::make_pair(curr, price) );
}
void Settings::set_volume(std::string curr, double volume) {
QString ticker = QString::fromStdString(curr);
void Settings::set_volume(QString curr, double volume) {
QString ticker = curr;
qDebug() << "Setting volume of " << ticker << "=" << QString::number(volume);
volumes.insert( std::make_pair(curr, volume) );
}
double Settings::get_volume(std::string currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); });
QString ticker = QString::fromStdString(currency);
double Settings::get_volume(QString currency) {
currency = currency.toLower();
QString ticker = currency;
auto search = volumes.find(currency);
if (search != volumes.end()) {
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) {
QString ticker = QString::fromStdString(curr);
void Settings::set_marketcap(QString curr, double marketcap) {
QString ticker = curr;
qDebug() << "Setting marketcap of " << ticker << "=" << QString::number(marketcap);
marketcaps.insert( std::make_pair(curr, marketcap) );
}
double Settings::get_marketcap(std::string currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); });
QString ticker = QString::fromStdString(currency);
double Settings::get_marketcap(QString currency) {
currency = currency.toLower();
QString ticker = currency;
auto search = marketcaps.find(currency);
if (search != marketcaps.end()) {
qDebug() << "Found marketcap of " << ticker << " = " << search->second;
@ -281,7 +282,7 @@ void Settings::saveRestore(QDialog* d) {
QString Settings::getUSDFormat(double bal) {
//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) {
@ -341,13 +342,13 @@ bool Settings::addToZcashConf(QString confLocation, QString line) {
return true;
}
std::string Settings::get_currency_name() {
QString Settings::get_currency_name() {
// 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) {
QSettings().setValue("options/currency_name", QString::fromStdString(currency_name));
void Settings::set_currency_name(QString currency_name) {
QSettings().setValue("options/currency_name", currency_name);
}

22
src/settings.h

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

4
src/websockets.cpp

@ -784,9 +784,9 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, st
return;
}
json params = json::array();
QJsonArray params;
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
mainwindow->getRPC()->executeTransaction(tx,

Loading…
Cancel
Save