diff --git a/README.md b/README.md index 79b2e89..356e2f1 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ You need a C++14 compatible compiler like g++ or clang++ ``` git clone https://github.com/adityapk00/zcash-qt-wallet.git cd zcash-qt-wallet -/path/to/qt5/bin/qmake zcash-qt-wallet.pro CONFIG+=DEBUG +/path/to/qt5/bin/qmake zcash-qt-wallet.pro CONFIG+=debug make -j$(nproc) ./zcash-qt-wallet diff --git a/src/balancestablemodel.cpp b/src/balancestablemodel.cpp index 569eeae..9b5eaac 100644 --- a/src/balancestablemodel.cpp +++ b/src/balancestablemodel.cpp @@ -1,4 +1,5 @@ #include "balancestablemodel.h" +#include "settings.h" #include "utils.h" BalancesTableModel::BalancesTableModel(QObject *parent) @@ -68,12 +69,22 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const return b; } - if (role == Qt::DisplayRole || role == Qt::ToolTipRole) { + if (role == Qt::DisplayRole) { switch (index.column()) { case 0: return std::get<0>(modeldata->at(index.row())); case 1: return QVariant(std::get<1>(modeldata->at(index.row())) % " " % Utils::getTokenName()); } } + + if(role == Qt::ToolTipRole) { + switch (index.column()) { + case 0: return std::get<0>(modeldata->at(index.row())); + case 1: { + auto bal = std::get<1>(modeldata->at(index.row())).toDouble(); + return "$ " + QString::number(bal * Settings::getInstance()->getZECPrice(), 'f', 2); // Use 'f' notation to get 2 decimal places + } + } + } return QVariant(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b22bcdf..0ee6d00 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -58,7 +58,9 @@ MainWindow::MainWindow(QWidget *parent) : setupBalancesTab(); rpc = new RPC(new QNetworkAccessManager(this), this); - rpc->refresh(); + rpc->refreshZECPrice(); + + rpc->refresh(); } void MainWindow::setupStatusBar() { diff --git a/src/rpc.cpp b/src/rpc.cpp index fa97833..132ddc4 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -39,6 +39,13 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) { }); // Start at every 10s. When an operation is pending, this will change to every second txTimer->start(Utils::updateSpeed); + + // Set up timer to refresh Price + priceTimer = new QTimer(main); + QObject::connect(timer, &QTimer::timeout, [=]() { + refreshZECPrice(); + }); + priceTimer->start(1 * 60 * 60 * 1000); // Every hour } RPC::~RPC() { @@ -515,3 +522,68 @@ void RPC::refreshTxStatus(const QString& newOpid) { } }); } + +void RPC::refreshZECPrice() { + QUrl cmcURL("https://api.coinmarketcap.com/v1/ticker/"); + + QNetworkRequest req; + req.setUrl(cmcURL); + + QNetworkReply *reply = restclient->get(req); + + QObject::connect(reply, &QNetworkReply::finished, [=] { + reply->deleteLater(); + + try { + if (reply->error() != QNetworkReply::NoError) { + auto parsed = json::parse(reply->readAll(), nullptr, false); + if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) { + qDebug() << QString::fromStdString(parsed["error"]["message"]); + } else { + qDebug() << reply->errorString(); + } + Settings::getInstance()->setZECPrice(0); + return; + } + + auto all = reply->readAll(); + + auto parsed = json::parse(all, nullptr, false); + if (parsed.is_discarded()) { + Settings::getInstance()->setZECPrice(0); + return; + } + + for (const json& item : parsed.get()) { + if (item["symbol"].get().compare("ZEC") == 0) { + QString price = QString::fromStdString(item["price_usd"].get()); + qDebug() << "ZEC Price=" << price; + Settings::getInstance()->setZECPrice(price.toDouble()); + return; + } + } + } catch (...) { + // If anything at all goes wrong, just set the price to 0 and move on. + qDebug() << QString("Caught something nasty"); + } + + // If nothing, then set the price to 0; + Settings::getInstance()->setZECPrice(0); + }); +} + +/* + .url("https://api.coinmarketcap.com/v1/ticker/") + .withHeaders("Accept" -> "application/json") + .get() + .map { + response => { + val prices = response.json.as[JsArray].value + .map(x => ((x \ "symbol").as[String], (x \ "price_usd").as[BigDecimal].setScale(2, RoundingMode.HALF_UP))) + .toMap + + coinCodes.map { coinCode => + CoinPrice(coinCode, prices.get(coinCode), Some(System.currentTimeMillis() / 1000)) + } + } + */ diff --git a/src/rpc.h b/src/rpc.h index ed80910..52754a2 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -20,6 +20,7 @@ public: void refresh(); // Refresh all transactions void refreshTxStatus(const QString& newOpid = QString()); // Refresh the status of all pending txs. void refreshAddresses(); // Refresh wallet Z-addrs + void refreshZECPrice(); void sendZTransaction (json params, const std::function& cb); @@ -38,8 +39,8 @@ private: void doSendRPC (const json& payload, const std::function& cb); void refreshBalances(); - void refreshTransactions(); - + void refreshTransactions(); + bool processUnspent (const json& reply); void updateUI (bool anyUnconfirmed); @@ -52,7 +53,6 @@ private: void getTransactions (const std::function& cb); void getZAddresses (const std::function& cb); - void handleConnectionError (const QString& error); void handleTxError (const QString& error); @@ -70,6 +70,7 @@ private: QTimer* timer; QTimer* txTimer; + QTimer* priceTimer; Ui::MainWindow* ui; MainWindow* main; diff --git a/src/scripts/mkrelease.sh b/src/scripts/mkrelease.sh index e1eece4..f9bd512 100755 --- a/src/scripts/mkrelease.sh +++ b/src/scripts/mkrelease.sh @@ -52,4 +52,5 @@ if [ -f bin/linux-zcash-qt-wallet-v$APP_VERSION.tar.gz ] ; then else echo "[ERROR]" exit 1 -fi \ No newline at end of file +fi + diff --git a/src/settings.h b/src/settings.h index 977908b..ee7eb60 100644 --- a/src/settings.h +++ b/src/settings.h @@ -31,6 +31,9 @@ public: const QString& getZcashdConfLocation() { return confLocation; } + void setZECPrice(double p) { zecPrice = p; } + double getZECPrice() { return zecPrice; } + private: // This class can only be accessed through Settings::getInstance() Settings() = default; @@ -48,6 +51,8 @@ private: bool _isTestnet = false; bool _isSyncing = false; + + double zecPrice = 0.0; }; #endif // SETTINGS_H \ No newline at end of file diff --git a/src/txtablemodel.cpp b/src/txtablemodel.cpp index c6a1f25..9f2a8b7 100644 --- a/src/txtablemodel.cpp +++ b/src/txtablemodel.cpp @@ -1,4 +1,5 @@ #include "txtablemodel.h" +#include "settings.h" #include "utils.h" TxTableModel::TxTableModel(QObject *parent) @@ -53,7 +54,13 @@ void TxTableModel::setNewData(QList* data) { case 0: return modeldata->at(index.row()).type; case 1: return modeldata->at(index.row()).address; case 2: return modeldata->at(index.row()).datetime; - case 3: return QVariant(QString::number(modeldata->at(index.row()).amount, 'g', 8) % " " % Utils::getTokenName()); + case 3: { + if (role == Qt::DisplayRole) + return QVariant(QString::number(modeldata->at(index.row()).amount, 'g', 8) % " " % Utils::getTokenName()); + else { + return "$ " + QString::number(Settings::getInstance()->getZECPrice() * modeldata->at(index.row()).amount, 'f', 2); + } + } } } diff --git a/src/utils.h b/src/utils.h index e3121b0..291b280 100644 --- a/src/utils.h +++ b/src/utils.h @@ -18,7 +18,7 @@ public: static double getTotalFee(); static const int updateSpeed = 20 * 1000; // 20 sec -private: +private: Utils() = delete; };