From 9e96f4183ae4a9f6095abf93e170423a99ad619b Mon Sep 17 00:00:00 2001 From: tobtoht Date: Mon, 1 Feb 2021 17:53:08 +0100 Subject: [PATCH] Exchanges: Remove XMR.to --- CMakeLists.txt | 1 - HACKING.md | 1 - Makefile | 1 - src/CMakeLists.txt | 4 - src/appcontext.cpp | 19 -- src/appcontext.h | 3 - src/assets.qrc | 3 +- src/assets/images/exchange_white.png | Bin 0 -> 1000 bytes src/dialog/xmrtoinfodialog.cpp | 35 --- src/dialog/xmrtoinfodialog.h | 28 --- src/dialog/xmrtoinfodialog.ui | 256 --------------------- src/mainwindow.cpp | 27 +-- src/mainwindow.ui | 39 ---- src/model/XmrToModel.cpp | 107 --------- src/model/XmrToModel.h | 38 ---- src/utils/xmrto.cpp | 110 --------- src/utils/xmrto.h | 63 ------ src/utils/xmrtoapi.cpp | 76 ------- src/utils/xmrtoapi.h | 87 ------- src/utils/xmrtoorder.cpp | 274 ---------------------- src/utils/xmrtoorder.h | 106 --------- src/xmrtowidget.cpp | 193 ---------------- src/xmrtowidget.h | 67 ------ src/xmrtowidget.ui | 327 --------------------------- 24 files changed, 2 insertions(+), 1863 deletions(-) create mode 100644 src/assets/images/exchange_white.png delete mode 100644 src/dialog/xmrtoinfodialog.cpp delete mode 100644 src/dialog/xmrtoinfodialog.h delete mode 100644 src/dialog/xmrtoinfodialog.ui delete mode 100644 src/model/XmrToModel.cpp delete mode 100644 src/model/XmrToModel.h delete mode 100644 src/utils/xmrto.cpp delete mode 100644 src/utils/xmrto.h delete mode 100644 src/utils/xmrtoapi.cpp delete mode 100644 src/utils/xmrtoapi.h delete mode 100644 src/utils/xmrtoorder.cpp delete mode 100644 src/utils/xmrtoorder.h delete mode 100644 src/xmrtowidget.cpp delete mode 100644 src/xmrtowidget.h delete mode 100644 src/xmrtowidget.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index e8b509f..9d81a31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,6 @@ set(VERSION_REVISION "0") set(VERSION "beta-3") option(FETCH_DEPS "Download dependencies if they are not found" ON) -option(XMRTO "Include Xmr.To module" ON) option(XMRIG "Include XMRig module" ON) option(TOR_BIN "Path to Tor binary to embed inside Feather" OFF) diff --git a/HACKING.md b/HACKING.md index fd27af9..01e8155 100644 --- a/HACKING.md +++ b/HACKING.md @@ -41,7 +41,6 @@ via the `CMAKE_PREFIX_PATH` definition. For me this is: There are some Monero/Feather related options/definitions that you may pass: -- `-DXMRTO=OFF` - disable Xmr.To feature - `-DXMRIG=OFF` - disable XMRig feature - `-DTOR_BIN=/path/to/tor` - Embed a Tor executable inside Feather - `-DDONATE_BEG=OFF` - disable the dreaded donate requests diff --git a/Makefile b/Makefile index 7ef1c5e..6e929cc 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,6 @@ CMAKEFLAGS = \ -DARCH=x86_64 \ -DBUILD_64=On \ -DBUILD_TESTS=Off \ - -DXMRTO=On \ -DXMRIG=On \ -DTOR_BIN=Off \ -DCMAKE_CXX_STANDARD=11 \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d7d297e..55acfaa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -122,10 +122,6 @@ if(DONATE_BEG) target_compile_definitions(feather PRIVATE DONATE_BEG=1) endif() -if(XMRTO) - target_compile_definitions(feather PRIVATE HAS_XMRTO=1) -endif() - if(TOR_BIN) target_compile_definitions(feather PRIVATE HAS_TOR_BIN=1) endif() diff --git a/src/appcontext.cpp b/src/appcontext.cpp index e0fa022..4cdbf97 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -132,11 +132,6 @@ AppContext::AppContext(QCommandLineParser *cmdargs) { // fiat/crypto lookup AppContext::prices = new Prices(); - // xmr.to -#ifdef HAS_XMRTO - this->XMRTo = new XmrTo(this); -#endif - // XMRig #ifdef HAS_XMRIG this->XMRig = new XmRig(this->configDirectory, this); @@ -171,7 +166,6 @@ void AppContext::initTor() { if (m_wsUrl.host().endsWith(".onion")) this->ws->webSocket.setProxy(*networkProxy); } - } void AppContext::initWS() { @@ -199,13 +193,6 @@ void AppContext::onSweepOutput(const QString &keyImage, QString address, bool ch this->currentWallet->createTransactionSingleAsync(keyImage, address, outputs, this->tx_priority); } -void AppContext::onCreateTransaction(XmrToOrder *order) { - // tx creation via xmr.to - const QString description = QString("XmrTo order %1").arg(order->uuid); - quint64 amount = WalletManager::amountFromDouble(order->incoming_amount_total); - this->onCreateTransaction(order->receiving_subaddress, amount, description, false); -} - void AppContext::onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all) { // tx creation this->tmpTxDescription = description; @@ -434,12 +421,6 @@ void AppContext::onWSMessage(const QJsonObject &msg) { QJsonObject fiat_rates = msg.value("data").toObject(); AppContext::prices->fiatPricesReceived(fiat_rates); } -#if defined(HAS_XMRTO) - else if(cmd == "xmrto_rates") { - auto xmr_rates = msg.value("data").toObject(); - this->XMRTo->onRatesReceived(xmr_rates); - } -#endif else if(cmd == "reddit") { QJsonArray reddit_data = msg.value("data").toArray(); this->onWSReddit(reddit_data); diff --git a/src/appcontext.h b/src/appcontext.h index f971129..dd6369a 100644 --- a/src/appcontext.h +++ b/src/appcontext.h @@ -14,7 +14,6 @@ #include "utils/prices.h" #include "utils/networking.h" #include "utils/tor.h" -#include "utils/xmrto.h" #include "utils/xmrig.h" #include "utils/wsclient.h" #include "utils/txfiathistory.h" @@ -81,7 +80,6 @@ public: Tor *tor{}; WSClient *ws; - XmrTo *XMRTo; XmRig *XMRig; Nodes *nodes; static Prices *prices; @@ -114,7 +112,6 @@ public: public slots: void onOpenWallet(const QString& path, const QString &password); void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all); - void onCreateTransaction(XmrToOrder *order); void onCreateTransactionMultiDest(const QVector &addresses, const QVector &amounts, const QString &description); void onCancelTransaction(PendingTransaction *tx, const QVector &address); void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) const; diff --git a/src/assets.qrc b/src/assets.qrc index 347779c..5a341e7 100644 --- a/src/assets.qrc +++ b/src/assets.qrc @@ -34,6 +34,7 @@ assets/images/cutexmrfox.png assets/images/edit.png assets/images/exchange.png + assets/images/exchange_white.png assets/images/expired.png assets/images/expired_icon.png assets/images/eye1.png @@ -97,8 +98,6 @@ assets/images/unpaid.png assets/images/update.png assets/images/warning.png - assets/images/xmrto_big.png - assets/images/xmrto.png assets/images/xmrig.ico assets/images/xmrig.svg assets/images/zoom.png diff --git a/src/assets/images/exchange_white.png b/src/assets/images/exchange_white.png new file mode 100644 index 0000000000000000000000000000000000000000..9fe42b48efcb69c168aeb09aa730832339bb1fff GIT binary patch literal 1000 zcmV>P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 zVoOIv0RM-N%)bBt17%4>K~#9!?VLYPQ&AYkpZ8Sb;KB#cffx-Rfx(T%#6ctxmH#M- zi4HP5x#%Zga6npUjg$gWHx?5U7e9evGR}MeqHTE{3ia0BKj+rc7tZ_sCTP;|JinfM zdhR_Z0ES^0hG7_nVHk#C80Qv#%KN;>W70XK>JM|1nVB0rEuBS1z%xD}mjWjpyl-4= z|5U)bzk+ZCM9HBbOaVC*get&WLAU}u6@)CnOF`HIJQRd3AX7p30x}e65Rj@shkz6X zS_C92&?6v00r54w#sn@%ryCGW%+tG00aZ*&r;=1aTvzky$0{IZ={&LuG);nkiA;w& z1w<5R70_0oa}GG6iQBpb0H5_<0xhm+7w|^+B~ZkY<`GcD5*_IkP{a})>0JkuTJ^OG zDB*FdKH%_8I*nv~z~Lnhq!SI4^=N&70KSBqk0)ek}qvuo!>s>kyDwUx$Ela(xW~%2-JI;tO3sM*YwQRI=)aEuez=>{VZG z0X)RR(#`r;KX3U0ukax^xgy;zCR^uHxXk?@+g#vE`wxst7fuyWIgR=*QlEKQx^P#% z(MbKmY1A)w46!pO0N@HY`H)uzQU6Q|0C<>(^1jF8a0EN7V@A515A-Addom}B^HaY! zG6b+gDdhSY0@$I1S?P#k0yNZ55x@?`@arcEV22{+q{E2`&{IEF06VN{sUIVN9o8@} z9cys>vl8^KKf<@9qyIN`e5GI1Q~gjlz+B|ci5=czK|0ewxs2=W5umU>0DyGYKmHbA zhgF^RTL&Z@RGb`g>!B#^;sF}cu>=JGw4+Hu?8XS~;Gq@;30q^dtwllN<|u7r zN`r!w?QyDUP>^~+f@+vXQ#zuc0D!haSCDx~imG8N@HkRRRm_B|!0SvcZHBAB^H4Eu zVm3?#-lwYRJ?0_`wB0th;3;k#|M%{z(pjVwjPV|S=LP8;hG7_nVHk#C7=~dOz4HfF WK(Ze+2ZpNv0000setupUi(this); - - ui->status->setText(XmrTo::stateMap[(OrderState) oInfo->state]); - ui->xmrto_id->setText(!oInfo->uuid.isEmpty() ? oInfo->uuid : ""); - - ui->error_code->setText(!oInfo->errorCode.isEmpty() ? oInfo->errorCode : ""); - ui->error_msg->setText(!oInfo->errorMsg.isEmpty() ? oInfo->errorMsg : ""); - - ui->xmr_amount->setText(QString::number(oInfo->incoming_amount_total)); - ui->btc_amount->setText(QString::number(oInfo->btc_amount)); - ui->rate->setText(oInfo->incoming_price_btc > 0 ? QString::number(oInfo->incoming_price_btc) : ""); - - ui->xmr_txid->setText(oInfo->xmr_txid); - ui->xmr_address->setText(oInfo->receiving_subaddress); - - ui->btc_txid->setText(oInfo->btc_txid); - ui->btc_address->setText(oInfo->btc_dest_address); - - this->adjustSize(); -} - -XmrToInfoDialog::~XmrToInfoDialog() { - delete ui; -} diff --git a/src/dialog/xmrtoinfodialog.h b/src/dialog/xmrtoinfodialog.h deleted file mode 100644 index 910498e..0000000 --- a/src/dialog/xmrtoinfodialog.h +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#ifndef FEATHER_XMRTOINFODIALOG_H -#define FEATHER_XMRTOINFODIALOG_H - -#include -#include "utils/xmrto.h" - -namespace Ui { - class XmrToInfoDialog; -} - -class XmrToInfoDialog : public QDialog -{ -Q_OBJECT - -public: - explicit XmrToInfoDialog(XmrToOrder *oInfo, QWidget *parent = nullptr); - ~XmrToInfoDialog() override; - -private: - Ui::XmrToInfoDialog *ui; - - XmrToOrder *m_oInfo; -}; - -#endif //FEATHER_XMRTOINFODIALOG_H diff --git a/src/dialog/xmrtoinfodialog.ui b/src/dialog/xmrtoinfodialog.ui deleted file mode 100644 index cb38077..0000000 --- a/src/dialog/xmrtoinfodialog.ui +++ /dev/null @@ -1,256 +0,0 @@ - - - XmrToInfoDialog - - - - 0 - 0 - 689 - 581 - - - - Xmr.to Order - - - - - - - - - - Status: - - - - - - - XMR.to ID: - - - - - - - Error code: - - - - - - - true - - - - - - - true - - - - - - - true - - - - - - - - - Qt::Vertical - - - - - - - - - XMR amount: - - - - - - - BTC amount: - - - - - - - Rate: - - - - - - - true - - - - - - - true - - - - - - - true - - - - - - - - - - - - - Message: - - - - - - - true - - - - - - - Qt::Horizontal - - - - - - - XMR.to address: - - - - - - - true - - - - - - - XMR txid: - - - - - - - true - - - - - - - Qt::Horizontal - - - - - - - BTC address: - - - - - - - true - - - - - - - BTC txid: - - - - - - - true - - - - - - - - - Qt::Horizontal - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Copy support template - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 0124f79..4191ef6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -97,22 +97,6 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : connect(ui->actionShow_debug_info, &QAction::triggered, this, &MainWindow::showDebugInfo); connect(ui->actionOfficialWebsite, &QAction::triggered, [=] { Utils::externalLinkWarning(this, "https://featherwallet.org"); }); -#if defined(HAS_XMRTO) - // xmr.to connects/widget - connect(ui->xmrToWidget, &XMRToWidget::viewOrder, m_ctx->XMRTo, &XmrTo::onViewOrder); - connect(ui->xmrToWidget, &XMRToWidget::getRates, m_ctx->XMRTo, &XmrTo::onGetRates); - connect(ui->xmrToWidget, &XMRToWidget::createOrder, m_ctx->XMRTo, &XmrTo::createOrder); - connect(m_ctx->XMRTo, &XmrTo::ratesUpdated, ui->xmrToWidget, &XMRToWidget::onRatesUpdated); - connect(m_ctx->XMRTo, &XmrTo::connectionError, ui->xmrToWidget, &XMRToWidget::onConnectionError); - connect(m_ctx->XMRTo, &XmrTo::connectionSuccess, ui->xmrToWidget, &XMRToWidget::onConnectionSuccess); - connect(m_ctx, &AppContext::balanceUpdated, ui->xmrToWidget, &XMRToWidget::onBalanceUpdated); - connect(m_ctx->XMRTo, &XmrTo::openURL, this, [=](const QString &url){ Utils::externalLinkWarning(this, url); }); - connect(m_ctx, &AppContext::walletClosed, ui->xmrToWidget, &XMRToWidget::onWalletClosed); - ui->xmrToWidget->setHistoryModel(m_ctx->XMRTo->tableModel); -#else - ui->tabExchanges->setTabVisible(0, false); -#endif - #if defined(Q_OS_LINUX) // system tray m_trayIcon = new QSystemTrayIcon(QIcon(":/assets/images/appicons/64x64.png")); @@ -225,10 +209,6 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : connect(m_ctx, &AppContext::initiateTransaction, ui->sendWidget, &SendWidget::onInitiateTransaction); connect(m_ctx, &AppContext::endTransaction, ui->sendWidget, &SendWidget::onEndTransaction); - // XMR.to - connect(m_ctx, &AppContext::initiateTransaction, ui->xmrToWidget, &XMRToWidget::onInitiateTransaction); - connect(m_ctx, &AppContext::endTransaction, ui->xmrToWidget, &XMRToWidget::onEndTransaction); - connect(m_ctx, &AppContext::initiateTransaction, [this]{ m_statusDots = 0; m_constructingTransaction = true; @@ -421,13 +401,8 @@ void MainWindow::initMenu() { m_tabShowHideMapper["Calc"] = new ToggleTab(ui->tabCalc, "Calc", "Calc", ui->actionShow_calc, Config::showTabCalc); m_tabShowHideSignalMapper->setMapping(ui->actionShow_calc, "Calc"); -#if defined(HAS_XMRTO) - connect(ui->actionShow_Exchange, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); - m_tabShowHideMapper["Exchange"] = new ToggleTab(ui->tabExchange, "Exchange", "Exchange", ui->actionShow_Exchange, Config::showTabExchange); - m_tabShowHideSignalMapper->setMapping(ui->actionShow_Exchange, "Exchange"); -#else ui->actionShow_Exchange->setVisible(false); -#endif + ui->tabWidget->setTabVisible(Tabs::EXCHANGES, false); #if defined(HAS_XMRIG) connect(ui->actionShow_XMRig, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index bb51edb..8a6efc2 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -293,39 +293,6 @@ 0 - - - - 0 - - - - - :/assets/images/xmrto.png:/assets/images/xmrto.png - - - XMR.to - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - @@ -764,12 +731,6 @@ QWidget
historywidget.h
- - XMRToWidget - QWidget -
xmrtowidget.h
- 1 -
CalcWidget QWidget diff --git a/src/model/XmrToModel.cpp b/src/model/XmrToModel.cpp deleted file mode 100644 index f6f4a2d..0000000 --- a/src/model/XmrToModel.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#include "XmrToModel.h" -#include "model/ModelUtils.h" -#include "utils/xmrto.h" -#include "utils/ColorScheme.h" - -XmrToModel::XmrToModel(QList *orders, QObject *parent) - : QAbstractTableModel(parent), - orders(orders) -{ -} - -void XmrToModel::update() { - beginResetModel(); - endResetModel(); -} - -int XmrToModel::rowCount(const QModelIndex &) const { - return this->orders->count(); -} - -int XmrToModel::columnCount(const QModelIndex &) const { - return COUNT; -} - -QVariant XmrToModel::data(const QModelIndex &index, int role) const { - const int _row = index.row(); - const int _col = index.column(); - const auto order = this->orders->at(_row); - - if (role == Qt::DisplayRole){ - switch(index.column()){ - case Status: - { - QString status = XmrTo::stateMap[(OrderState) order->state]; - - if (order->state == OrderState::Status_OrderUnpaid) - return QString("%1 (%2)").arg(status, QString::number(order->countdown)); - - return status; - } - case ID: - return !order->uuid.isEmpty() ? order->uuid.split("-")[1] : "-"; - case Destination: - return ModelUtils::displayAddress(order->btc_dest_address, 1); - case Conversion: - if(order->state <= OrderState::Status_OrderToBeCreated) - return ""; - - return QString("%1 XMR ⟶ %2 BTC").arg(QString::number(order->incoming_amount_total), QString::number(order->btc_amount)); - case Rate: - return order->incoming_price_btc ? QString::number(order->incoming_price_btc, 'f', 6) : ""; - case ErrorMsg: - if(order->errorMsg.isEmpty()) return ""; - return order->errorMsg; - default: return {}; - } - } - - else if(role == Qt::BackgroundRole) { - if (_col == 0) { - if (order->state == OrderState::Status_OrderPaid || order->state == OrderState::Status_OrderPaidUnconfirmed) - return QBrush(ColorScheme::GREEN.asColor(true)); - else if (order->state == OrderState::Status_OrderCreating || order->state == OrderState::Status_OrderToBeCreated) - return QBrush(ColorScheme::YELLOW.asColor(true)); - else if (order->state == OrderState::Status_OrderUnpaid) - return QBrush(ColorScheme::YELLOW.asColor(true)); - else if (order->state == OrderState::Status_OrderBTCSent) - return QBrush(ColorScheme::GREEN.asColor(true)); - else if (order->state == OrderState::Status_OrderFailed || order->state == OrderState::Status_OrderTimedOut) - return QBrush(ColorScheme::RED.asColor(true)); - } - } - else if (role == Qt::FontRole) { - switch(index.column()) { - case ID: - case Destination: - return ModelUtils::getMonospaceFont(); - } - } - - return QVariant(); -} - -QVariant XmrToModel::headerData(int section, Qt::Orientation orientation, int role) const { - if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { - switch (section) { - case Status: - return QString("Status"); - case ID: - return QString("ID"); - case Destination: - return QString("Address"); - case Conversion: - return QString("Conversion"); - case Rate: - return QString("Rate"); - case ErrorMsg: - return QString("Message"); - default: - return QVariant(); - } - } - return QVariant(); -} \ No newline at end of file diff --git a/src/model/XmrToModel.h b/src/model/XmrToModel.h deleted file mode 100644 index d3fbc3e..0000000 --- a/src/model/XmrToModel.h +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#ifndef FEATHER_XMRTOMODEL_H -#define FEATHER_XMRTOMODEL_H - -#include - -class XmrToOrder; -class XmrToModel : public QAbstractTableModel -{ - Q_OBJECT - -public: - enum ModelColumn - { - Status = 0, - ID, - Conversion, - Rate, - Destination, - ErrorMsg, - COUNT - }; - - XmrToModel(QList *orders, QObject *parent = nullptr); - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - QList *orders; - -public slots: - void update(); -}; - - -#endif //FEATHER_XMRTOMODEL_H diff --git a/src/utils/xmrto.cpp b/src/utils/xmrto.cpp deleted file mode 100644 index 10f2d2d..0000000 --- a/src/utils/xmrto.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#include "xmrto.h" - -#include "appcontext.h" - -QMap XmrTo::stateMap; - -XmrTo::XmrTo(AppContext *ctx, QObject *parent) : - QObject(parent), - m_ctx(ctx) { - - m_baseUrl = m_ctx->networkType == NetworkType::Type::MAINNET ? "https://xmr.to" : "https://test.xmr.to"; - - m_netTor = new UtilsNetworking(this->m_ctx->network); - m_netClear = new UtilsNetworking(this->m_ctx->networkClearnet); - - m_apiTor = new XmrToApi(this, m_netTor, m_baseUrl); - m_apiClear = new XmrToApi(this, m_netClear, m_baseUrl); - - connect(m_apiTor, &XmrToApi::ApiResponse, this, &XmrTo::onApiResponse); - connect(m_apiClear, &XmrToApi::ApiResponse, this, &XmrTo::onApiResponse); - - connect(this, &XmrTo::orderPaymentRequired, this->m_ctx, QOverload::of(&AppContext::onCreateTransaction)); - - XmrTo::stateMap[OrderState::Status_Idle] = "IDLE"; - XmrTo::stateMap[OrderState::Status_OrderCreating] = "CREATING"; - XmrTo::stateMap[OrderState::Status_OrderUnpaid] = "UNPAID"; - XmrTo::stateMap[OrderState::Status_OrderToBeCreated] = "TO_BE_CREATED"; - XmrTo::stateMap[OrderState::Status_OrderUnderPaid] = "UNDERPAID"; - XmrTo::stateMap[OrderState::Status_OrderPaidUnconfirmed] = "PAID_UNCONFIRMED"; - XmrTo::stateMap[OrderState::Status_OrderPaid] = "PAID"; - XmrTo::stateMap[OrderState::Status_OrderBTCSent] = "BTC_SENT"; - XmrTo::stateMap[OrderState::Status_OrderTimedOut] = "TIMED_OUT"; - XmrTo::stateMap[OrderState::Status_OrderFailed] = "FAILED"; - XmrTo::stateMap[OrderState::Status_OrderXMRSent] = "XMR_SENT"; - - this->tableModel = new XmrToModel(&this->orders, this); -} - -void XmrTo::createOrder(double amount, const QString ¤cy, const QString &btcAddress) { - // ^[13][a-km-zA-HJ-NP-Z0-9]{26,33}$ - - XmrToOrder *order; - order = new XmrToOrder(this->m_ctx, m_netTor, m_baseUrl, false, &this->rates, this); - - connect(order, &XmrToOrder::orderFailed, this, &XmrTo::orderFailed); - connect(order, &XmrToOrder::orderPaid, this, &XmrTo::orderPaid); - connect(order, &XmrToOrder::orderPaidUnconfirmed, this, &XmrTo::orderPaidUnconfirmed); - connect(order, &XmrToOrder::orderPaymentRequired, this, &XmrTo::orderPaymentRequired); - connect(order, &XmrToOrder::orderChanged, this->tableModel, &XmrToModel::update); - - order->create(amount, currency, btcAddress); - this->orders.append(order); - tableModel->update(); -} - - -void XmrTo::onApiResponse(const XmrToResponse &resp) { - if (!resp.ok) { - this->onApiFailure(resp); - return; - } - - emit connectionSuccess(); - if (resp.endpoint == Endpoint::RATES) { - onRatesReceived(resp.obj); - } -} - -void XmrTo::onApiFailure(const XmrToResponse &resp) { - emit connectionError(resp.message); -} - -void XmrTo::onGetRates() { - m_apiTor->getRates(); -} - -void XmrTo::onRatesReceived(const QJsonObject &doc) { - this->rates.price = doc.value("price").toString().toDouble(); - this->rates.ln_lower_limit = doc.value("ln_lower_limit").toString().toDouble(); - this->rates.ln_upper_limit = doc.value("ln_upper_limit").toString().toDouble(); - this->rates.lower_limit = doc.value("lower_limit").toString().toDouble(); - this->rates.upper_limit = doc.value("upper_limit").toString().toDouble(); - this->rates.zero_conf_enabled = doc.value("zero_conf_enabled").toBool(); - this->rates.zero_conf_max_amount = doc.value("zero_conf_enabled").toString().toDouble(); - emit ratesUpdated(rates); -} - -void XmrTo::onNetworkChanged(bool clearnet) { - m_api = clearnet ? m_apiClear : m_apiTor; -} - -void XmrTo::onWalletClosed() { - // @TODO: cleanup - for(const auto &order: this->orders) - order->deleteLater(); - - this->tableModel->update(); -} - -void XmrTo::onWalletOpened() { - // @TODO: read past XMR.To orders, start pending ones -} - -void XmrTo::onViewOrder(const QString &orderId) { - QString url = QString("%1/nojs/status/%2").arg(this->m_baseUrl).arg(orderId); - emit openURL(url); -} diff --git a/src/utils/xmrto.h b/src/utils/xmrto.h deleted file mode 100644 index 00b0498..0000000 --- a/src/utils/xmrto.h +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#ifndef FEATHER_XMRTOCONVERT_H -#define FEATHER_XMRTOCONVERT_H - -#include - -#include "model/XmrToModel.h" -#include "utils/xmrtoorder.h" -#include "utils/xmrtoapi.h" - -class AppContext; -class XmrTo: public QObject { - Q_OBJECT - -public: - explicit XmrTo(AppContext *ctx, QObject *parent = nullptr); - Q_ENUM(OrderState); - - XmrToModel *tableModel; - static QMap stateMap; - XmrToRates rates; - QList orders; - -public slots: - void createOrder(double amount, const QString ¤cy, const QString &btcAddress); - void onGetRates(); - void onRatesReceived(const QJsonObject &doc); - void onViewOrder(const QString &orderId); - void onNetworkChanged(bool clearnet); - void onWalletOpened(); - void onWalletClosed(); - -private slots: - void onApiResponse(const XmrToResponse &doc); - -signals: - void orderPaymentRequired(XmrToOrder *order); - void orderPaidUnconfirmed(XmrToOrder *order); - void orderPaid(XmrToOrder *order); - void orderFailed(XmrToOrder *order); - void ratesUpdated(XmrToRates rates); - void openURL(const QString &url); - void connectionError(const QString &err); - void connectionSuccess(); - -private: - void onApiFailure(const XmrToResponse &doc); - - QString m_baseUrl; - AppContext *m_ctx; - int m_orderTimeout = 900; // https://xmrto-api.readthedocs.io/en/latest/introduction.html#various-parameters - - UtilsNetworking *m_netTor; - UtilsNetworking *m_netClear; - - XmrToApi *m_api; - XmrToApi *m_apiTor; - XmrToApi *m_apiClear; -}; - -#endif //FEATHER_XMRTOCONVERT_H diff --git a/src/utils/xmrtoapi.cpp b/src/utils/xmrtoapi.cpp deleted file mode 100644 index 628bec7..0000000 --- a/src/utils/xmrtoapi.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#include "xmrtoapi.h" - -XmrToApi::XmrToApi(QObject *parent, UtilsNetworking *network, QString baseUrl) - : QObject(parent) - , m_network(network) - , m_baseUrl(std::move(baseUrl)) -{ -} - -void XmrToApi::getRates() { - QString url = QString("%1/api/v3/xmr2btc/order_parameter_query/").arg(this->m_baseUrl); - QNetworkReply *reply = m_network->getJson(url); - connect(reply, &QNetworkReply::finished, std::bind(&XmrToApi::onResponse, this, reply, Endpoint::RATES)); -} - -void XmrToApi::createOrder(double amount, const QString &amount_currency, const QString &dest_address) { - QJsonObject order; - order["amount"] = amount; - order["amount_currency"] = amount_currency; - order["btc_dest_address"] = dest_address; - - QString url = QString("%1/api/v3/xmr2btc/order_create/").arg(m_baseUrl); - QNetworkReply *reply = m_network->postJson(url, order); - connect(reply, &QNetworkReply::finished, std::bind(&XmrToApi::onResponse, this, reply, Endpoint::ORDER_CREATE)); -} - -void XmrToApi::getOrderStatus(const QString &uuid) { - QJsonObject order; - order["uuid"] = uuid; - - QString url = QString("%1/api/v3/xmr2btc/order_status_query/").arg(m_baseUrl); - QNetworkReply *reply = m_network->postJson(url, order); - connect(reply, &QNetworkReply::finished, std::bind(&XmrToApi::onResponse, this, reply, Endpoint::ORDER_STATUS)); -} - -void XmrToApi::onResponse(QNetworkReply *reply, Endpoint endpoint) { - const auto ok = reply->error() == QNetworkReply::NoError; - const auto err = reply->errorString(); - - QByteArray data = reply->readAll(); - QJsonObject obj; - if (!data.isEmpty() && Utils::validateJSON(data)) { - auto doc = QJsonDocument::fromJson(data); - obj = doc.object(); - } - else if (!ok) { - emit ApiResponse(XmrToResponse(false, endpoint, err)); - return; - } - else { - emit ApiResponse(XmrToResponse(false, endpoint, "Invalid response from XMR.to")); - return; - } - - XmrToError xmrto_err = XmrToApi::getApiError(obj); - if (!xmrto_err.code.isEmpty()) { - emit ApiResponse(XmrToResponse(false, endpoint, m_errorMap.contains(xmrto_err.code) ? m_errorMap[xmrto_err.code] : "", xmrto_err)); - return; - } - - reply->deleteLater(); - emit ApiResponse(XmrToResponse(true, endpoint, "", obj)); -} - -XmrToError XmrToApi::getApiError(const QJsonObject &obj) { - if (!obj.contains("error")) - return XmrToError(); - - QString code = obj.value("error").toString(); - QString msg = obj.value("error_msg").toString(); - - return XmrToError(code, msg); -} diff --git a/src/utils/xmrtoapi.h b/src/utils/xmrtoapi.h deleted file mode 100644 index 896f739..0000000 --- a/src/utils/xmrtoapi.h +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#ifndef FEATHER_XMRTOAPI_H -#define FEATHER_XMRTOAPI_H - -#include -#include - -#include "utils/networking.h" - -enum Endpoint { - RATES = 0, - ORDER_CREATE, - ORDER_STATUS -}; - -struct XmrToError { - explicit XmrToError(QString code = "", QString msg = "") - : code(std::move(code)), msg(std::move(msg)) {}; - - QString code; - QString msg; -}; - -struct XmrToResponse { - explicit XmrToResponse(bool ok, Endpoint endpoint, QString message, XmrToError error = XmrToError(), QJsonObject obj = {}) - : ok(ok), endpoint(endpoint), message(std::move(message)), error(std::move(error)), obj(std::move(obj)) {}; - - explicit XmrToResponse(bool ok, Endpoint endpoint, QString message, QJsonObject obj) - : ok(ok), endpoint(endpoint), message(std::move(message)), obj(std::move(obj)) {}; - - bool ok; - Endpoint endpoint; - QString message; - XmrToError error = XmrToError(); - QJsonObject obj; -}; - -class XmrToApi : public QObject { - Q_OBJECT - -public: - explicit XmrToApi(QObject *parent, UtilsNetworking *network, QString baseUrl = "https://xmr.to"); - - void getRates(); - void createOrder(double amount, const QString &amount_currency, const QString &dest_address); - void getOrderStatus(const QString &uuid); - -signals: - void ApiResponse(XmrToResponse resp); - -private slots: - void onResponse(QNetworkReply *reply, Endpoint endpoint); - -private: - static XmrToError getApiError(const QJsonObject &obj); - - QString m_baseUrl; - UtilsNetworking *m_network; - - // https://xmrto-api.readthedocs.io/en/latest/introduction.html#list-of-all-error-codes - const QMap m_errorMap = { - {"XMRTO-ERROR-001", "internal services not available, try again later."}, - {"XMRTO-ERROR-002", "malformed bitcoin address, check address validity."}, - {"XMRTO-ERROR-003", "invalid bitcoin amount, check amount data type."}, - {"XMRTO-ERROR-004", "bitcoin amount out of bounds, check min and max amount."}, - {"XMRTO-ERROR-005", "unexpected validation error, contact support."}, - {"XMRTO-ERROR-006", "requested order not found, check order UUID."}, - {"XMRTO-ERROR-007", "third party service not available, try again later."}, - {"XMRTO-ERROR-008", "insufficient funds available, try again later."}, - {"XMRTO-ERROR-009", "invalid request, check request parameters."}, - {"XMRTO-ERROR-010", "payment protocol failed, invalid or outdated data served by URL."}, - {"XMRTO-ERROR-011", "malformed payment protocol url, URL is malformed or cannot be contacted."}, - {"XMRTO-ERROR-012", "too many requests, try less often."}, - {"XMRTO-ERROR-013", "access forbidden."}, - {"XMRTO-ERROR-014", "service is not available in your region."}, - {"XMRTO-ERROR-015", "invalid monero amount, check amount data type."}, - {"XMRTO-ERROR-016", "invalid currency, check available currency options."}, - {"XMRTO-ERROR-017", "malformed lightning network invoice, provide a correct invoice for the main network."}, - {"XMRTO-ERROR-018", "lightning payment unlikely to succeed, check first if xmr.to has routes available."}, - {"XMRTO-ERROR-019", "lightning invoice preimage already known, don’t use the same invoice more than once."} - }; -}; - - -#endif //FEATHER_XMRTOAPI_H diff --git a/src/utils/xmrtoorder.cpp b/src/utils/xmrtoorder.cpp deleted file mode 100644 index 36011dd..0000000 --- a/src/utils/xmrtoorder.cpp +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#include "xmrtoorder.h" - -#include "libwalletqt/Wallet.h" -#include "appcontext.h" -#include "globals.h" - -XmrToOrder::XmrToOrder(AppContext *ctx, UtilsNetworking *network, QString baseUrl, bool clearnet, XmrToRates *rates, QObject *parent) : - QObject(parent), - m_ctx(ctx), - m_network(network), - m_baseUrl(std::move(baseUrl)), - m_rates(rates), - m_clearnet(clearnet) { - this->state = OrderState::Status_Idle; - - m_baseUrl = m_ctx->networkType == NetworkType::Type::MAINNET ? "https://xmr.to" : "https://test.xmr.to"; - m_api = new XmrToApi(this, network, m_baseUrl); - - connect(m_api, &XmrToApi::ApiResponse, this, &XmrToOrder::onApiResponse); - connect(m_ctx, &AppContext::transactionCommitted, this, &XmrToOrder::onTransactionCommitted); - connect(m_ctx, &AppContext::createTransactionCancelled, this, &XmrToOrder::onTransactionCancelled); -} - -void XmrToOrder::onTransactionCancelled(const QVector &address, double amount) { - // listener for all cancelled transactions - will try to match the exact amount to this order. - if(this->incoming_amount_total != amount || this->receiving_subaddress != address[0]) return; - - this->errorMsg = "TX cancelled by user"; - this->changeState(OrderState::Status_OrderFailed); - this->stop(); -} - -void XmrToOrder::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid) { - // listener for all outgoing transactions - will try to match the exact amount to this order. - if(this->state == OrderState::Status_OrderUnpaid){ - if(tx->amount() / globals::cdiv == this->incoming_amount_total) { - if(!status) { - this->errorMsg = "TX failed to commit"; - this->changeState(OrderState::Status_OrderFailed); - this->stop(); - return; - } - - this->xmr_txid = txid.at(0); - this->m_paymentSent = true; - this->changeState(OrderState::Status_OrderXMRSent); - } - } -} - -void XmrToOrder::onApiFailure(const XmrToResponse &resp) { - this->errorCode = resp.error.code; - this->errorMsg = resp.message; - - switch (resp.endpoint) { - case ORDER_CREATE: - this->onCreatedError(); - break; - case ORDER_STATUS: - this->onCheckedError(resp.error); - break; - default: - return; - } -} - -void XmrToOrder::onApiResponse(const XmrToResponse& resp) { - if (!resp.ok) { - this->onApiFailure(resp); - return; - } - - switch (resp.endpoint) { - case ORDER_CREATE: - this->onCreated(resp.obj); - break; - case ORDER_STATUS: - this->onChecked(resp.obj); - break; - default: - return; - } -} - -void XmrToOrder::create(double amount, const QString ¤cy, const QString &btcAddress) { - if(this->m_ctx->currentWallet == nullptr) { - this->errorMsg = "No wallet opened"; - this->changeState(OrderState::Status_OrderFailed); - return; - } - - m_api->createOrder(amount, currency, btcAddress); - this->changeState(OrderState::Status_OrderCreating); -} - -void XmrToOrder::onCreatedError() { - this->changeState(OrderState::Status_OrderFailed); -} - -void XmrToOrder::onCreated(const QJsonObject &object) { - if(!object.contains("state")) - this->errorMsg = "Could not parse 'state' from JSON response"; - if(object.value("state").toString() != "TO_BE_CREATED") - this->errorMsg = "unknown state from response, should be \"TO_BE_CREATED\""; - - if(!this->errorMsg.isEmpty()) { - this->changeState(OrderState::Status_OrderFailed); - return; - } - - if(m_created) return; - m_created = true; - this->btc_amount = object.value("btc_amount").toDouble(); - this->btc_dest_address = object.value("btc_dest_address").toString(); - this->uses_lightning = object.value("uses_lightning").toBool(); - this->uuid = object.value("uuid").toString(); - m_checkTimer.start(1000*5); - m_countdownTimer.start(1000); - connect(&m_checkTimer, &QTimer::timeout, this, &XmrToOrder::check); - connect(&m_countdownTimer, &QTimer::timeout, this, &XmrToOrder::onCountdown); - - this->changeState(OrderState::Status_OrderToBeCreated); - this->check(); -} - -void XmrToOrder::check() { - if(this->m_ctx->currentWallet == nullptr) - return; - - m_api->getOrderStatus(this->uuid); -} - -void XmrToOrder::onCheckedError(const XmrToError& err) { - if (!err.code.isEmpty()) - this->changeState(OrderState::Status_OrderFailed); - - m_checkFailures += 1; - if(m_checkFailures > 15){ - this->errorMsg = "Too many failed attempts"; - this->changeState(OrderState::Status_OrderFailed); - } -} - -void XmrToOrder::onChecked(const QJsonObject &object) { - if(object.contains("btc_amount")) - this->btc_amount = object.value("btc_amount").toString().toDouble(); - if(object.contains("btc_dest_address")) - this->btc_dest_address = object.value("btc_dest_address").toString(); - if(object.contains("seconds_till_timeout")) { - this->seconds_till_timeout = object.value("seconds_till_timeout").toInt(); - this->countdown = this->seconds_till_timeout; - } - if(object.contains("created_at")) - this->created_at = object.value("created_at").toString(); - if(object.contains("expires_at")) - this->expires_at = object.value("expires_at").toString(); - if(object.contains("incoming_amount_total")) - this->incoming_amount_total = object.value("incoming_amount_total").toString().toDouble(); - if(object.contains("remaining_amount_incoming")) - this->remaining_amount_incoming = object.value("remaining_amount_incoming").toString().toDouble(); - if(object.contains("incoming_price_btc")) - { - qDebug() << object.value("incoming_price_btc").toString(); - this->incoming_price_btc = object.value("incoming_price_btc").toString().toDouble(); - } - if(object.contains("receiving_subaddress")) - this->receiving_subaddress = object.value("receiving_subaddress").toString(); - - if(object.contains("payments")) { - // detect btc txid, xmr.to api can output several - we'll just grab the first #yolo - auto payments = object.value("payments").toArray(); - for(const auto &payment: payments){ - auto obj = payment.toObject(); - if(obj.contains("tx_id")) { - this->btc_txid = obj.value("tx_id").toString(); - break; - } - } - } - - this->changeState(object.value("state").toString()); -} - -void XmrToOrder::changeState(const QString &_state) { - for(const auto &key: XmrTo::stateMap.keys()) { - const auto &val = XmrTo::stateMap[key]; - if(_state == val){ - this->changeState(key); - return; - } - } -} - -void XmrToOrder::changeState(OrderState _state) { - if(this->m_ctx->currentWallet == nullptr) - return; - - if(_state == OrderState::Status_OrderUnderPaid && m_paymentSent) { - this->state = OrderState::Status_OrderXMRSent; - emit orderChanged(); - return; - } - - if(_state == this->state) return; - switch(_state){ - case OrderState::Status_Idle: - break; - case OrderState::Status_OrderCreating: - break; - case OrderState::Status_OrderToBeCreated: - break; - case OrderState::Status_OrderUnderPaid: - emit orderFailed(this); - this->stop(); - break; - case OrderState::Status_OrderUnpaid: - // need to send Monero - if(!m_paymentRequested) { - auto unlocked_balance = m_ctx->currentWallet->unlockedBalance() / globals::cdiv; - if (this->incoming_amount_total >= unlocked_balance) { - this->state = OrderState::Status_OrderFailed; - emit orderFailed(this); - this->stop(); - break; - } - m_paymentRequested = true; - emit orderPaymentRequired(this); - } - break; - case OrderState::Status_OrderFailed: - emit orderFailed(this); - this->stop(); - break; - case OrderState::Status_OrderPaidUnconfirmed: - emit orderPaidUnconfirmed(this); - break; - case OrderState::Status_OrderPaid: - emit orderPaid(this); - break; - case OrderState::Status_OrderTimedOut: - emit orderFailed(this); - this->stop(); - break; - case OrderState::Status_OrderBTCSent: - emit orderPaid(this); - this->stop(); - break; - default: - break; - } - - this->state = _state; - emit orderChanged(); -} - -void XmrToOrder::onCountdown() { - if(this->countdown <= 0) return; - this->countdown -= 1; - emit orderChanged(); -} - -void XmrToOrder::stop(){ - this->m_checkTimer.stop(); - this->m_countdownTimer.stop(); -} - -XmrToOrder::~XmrToOrder(){ - this->stop(); - this->disconnect(); - this->m_network->deleteLater(); -} \ No newline at end of file diff --git a/src/utils/xmrtoorder.h b/src/utils/xmrtoorder.h deleted file mode 100644 index ae585d3..0000000 --- a/src/utils/xmrtoorder.h +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#ifndef FEATHER_XMRTOORDER_H -#define FEATHER_XMRTOORDER_H - -#include - -#include "utils/networking.h" -#include "PendingTransaction.h" -#include "utils/xmrtoapi.h" - -enum OrderState { - Status_Idle, - Status_OrderCreating, - Status_OrderToBeCreated, - Status_OrderUnpaid, - Status_OrderXMRSent, - Status_OrderUnderPaid, - Status_OrderPaidUnconfirmed, - Status_OrderPaid, - Status_OrderBTCSent, - Status_OrderTimedOut, - Status_OrderFailed -}; - -struct XmrToRates { - double price; - double upper_limit; - double lower_limit; - double ln_upper_limit; - double ln_lower_limit; - double zero_conf_max_amount; - bool zero_conf_enabled; -}; - -class XmrToOrder : public QObject { - Q_OBJECT - -public: - explicit XmrToOrder(AppContext *ctx, UtilsNetworking *network, QString baseUrl, bool clearnet, XmrToRates *rates, QObject *parent = nullptr); - void create(double btcAmount, const QString ¤cy, const QString &btcAddress); - void changeState(OrderState state); - void changeState(const QString &state); - void stop(); - - int state; - int countdown = -1; // seconds remaining calculated from `seconds_till_timeout` - QString uuid; - QString errorMsg; - QString errorCode; - - double btc_amount = 0; - QString btc_dest_address; - QString btc_txid; - QString xmr_txid; - bool uses_lightning = false; - - QString receiving_subaddress; - QString created_at; - QString expires_at; - int seconds_till_timeout = -1; - double incoming_amount_total = 0; // amount_in_incoming_currency_for_this_order_as_string - double remaining_amount_incoming; // amount_in_incoming_currency_that_the_user_must_still_send_as_string - double incoming_price_btc = 0; // price_of_1_incoming_in_btc_currency_as_offered_by_service - -public slots: - void onCountdown(); - void onTransactionCancelled(const QVector &address, double amount); - void onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid); - - void onCreatedError(); - void onChecked(const QJsonObject &object); - void onCheckedError(const XmrToError& err); - void check(); - -private: - bool m_created = false; - QString m_baseUrl; - QTimer m_checkTimer; - QTimer m_countdownTimer; - int m_checkFailures = 0; - bool m_clearnet; - bool m_paymentSent = false; - bool m_paymentRequested = false; - UtilsNetworking *m_network; - AppContext *m_ctx; - XmrToRates *m_rates; - XmrToApi *m_api; - - ~XmrToOrder(); - -signals: - void orderChanged(); - void orderPaymentRequired(XmrToOrder *order); - void orderPaid(XmrToOrder *order); - void orderPaidUnconfirmed(XmrToOrder *order); - void orderFailed(XmrToOrder *order); - -private slots: - void onCreated(const QJsonObject &object); - void onApiFailure(const XmrToResponse &resp); - void onApiResponse(const XmrToResponse &resp); -}; - -#endif //FEATHER_XMRTOORDER_H diff --git a/src/xmrtowidget.cpp b/src/xmrtowidget.cpp deleted file mode 100644 index 71e7752..0000000 --- a/src/xmrtowidget.cpp +++ /dev/null @@ -1,193 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#include "xmrtowidget.h" -#include "ui_xmrtowidget.h" -#include "dialog/xmrtoinfodialog.h" -#include "mainwindow.h" -#include "globals.h" - -#include - -XMRToWidget::XMRToWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::XMRToWidget) -{ - ui->setupUi(this); - m_ctx = MainWindow::getContext(); - - QString amount_rx = R"(^\d*\.\d*$)"; - QRegExp rx; - rx.setPattern(amount_rx); - QValidator *validator = new QRegExpValidator(rx, this); - ui->lineAmount->setValidator(validator); - - // xmrto logo (c) binaryFate et. al. :-D - QPixmap p(":assets/images/xmrto_big.png"); - ui->logo->setPixmap(p.scaled(112, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - - ui->ratesLayout->hide(); - - // context menu - m_contextMenu = new QMenu(); - m_showDetailsAction = m_contextMenu->addAction("Details"); - m_viewOnXmrToAction = m_contextMenu->addAction("View order on XMR.to"); - m_viewOnXmrToAction->setIcon(QIcon(":/assets/images/xmrto.png")); - connect(m_showDetailsAction, &QAction::triggered, this, &XMRToWidget::showInfoDialog); - connect(m_viewOnXmrToAction, &QAction::triggered, [&](){ - QModelIndex index = ui->historyTable->currentIndex(); - XmrToOrder *order = this->tableModel->orders->at(index.row()); - emit viewOrder(order->uuid); - }); - - // connects - connect(ui->btnGetRates, &QPushButton::pressed, this, &XMRToWidget::onGetRates); - connect(ui->lineAmount, &QLineEdit::textChanged, this, &XMRToWidget::updateConversionLabel); - connect(ui->comboBox_currency, &QComboBox::currentTextChanged, this, &XMRToWidget::updateConversionLabel); - connect(ui->torCheckBox, &QCheckBox::stateChanged, this, &XMRToWidget::onTorCheckBoxToggled); - connect(ui->btnCreate, &QPushButton::clicked, this, &XMRToWidget::onCreateOrder); - - ui->historyTable->header()->setStretchLastSection(true); - ui->historyTable->header()->setSectionResizeMode(QHeaderView::ResizeToContents); - ui->historyTable->setSelectionBehavior(QAbstractItemView::SelectRows); - ui->historyTable->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->historyTable, &QTreeView::customContextMenuRequested, [&](const QPoint & point){ - QModelIndex index = ui->historyTable->indexAt(point); - if (index.isValid()) { - m_contextMenu->popup(ui->historyTable->viewport()->mapToGlobal(point)); - } - }); - - if (m_ctx->isTails || m_ctx->isWhonix) { - ui->torCheckBox->setDisabled(true); - } - - connect(ui->historyTable, &QTreeView::doubleClicked, this, &XMRToWidget::showInfoDialog); -} - -void XMRToWidget::setHistoryModel(XmrToModel *model) { - this->tableModel = model; - this->ui->historyTable->setModel(model); -} - -void XMRToWidget::onBalanceUpdated(quint64 balance, quint64 spendable) { - this->m_unlockedBalance = spendable / globals::cdiv; -} - -void XMRToWidget::onWalletClosed() { - ui->lineAddress->clear(); - ui->lineAmount->clear(); - ui->xmrLabelEstimate->setText("0.00 XMR"); -} - -void XMRToWidget::onCreateOrder() { - // @TODO: regex verify - - auto amount = ui->lineAmount->text(); - if(amount.isEmpty()) { - QMessageBox::warning(this, "Cannot create XMR.To order", "Invalid amount"); - return; - } - - double amount_num = amount.toDouble(); - QString amount_cur = (ui->comboBox_currency->currentIndex() == curr::BTC) ? "BTC" : "XMR"; - double amount_xmr = amount_num; - if (ui->comboBox_currency->currentIndex() == curr::BTC) { - amount_xmr = AppContext::prices->convert("BTC", "XMR", amount_num); - } - - auto available = m_unlockedBalance; - if(amount_xmr > available){ - QMessageBox::warning(this, "Cannot create XMR.To order", "Not enough Monero to create order."); - return; - } - - ui->btnGetRates->setEnabled(false); - ui->btnCreate->setEnabled(false); - - auto btc_address = ui->lineAddress->text(); - emit createOrder(amount_num, amount_cur, btc_address); - - QTimer::singleShot(2000, [=] { - ui->lineAmount->clear(); - ui->lineAddress->clear(); - ui->btnGetRates->setEnabled(true); - }); -} - -void XMRToWidget::onTorCheckBoxToggled(int state) { - ui->btnGetRates->setEnabled(true); - ui->btnCreate->setEnabled(false); - emit networkChanged(!state); -} - -void XMRToWidget::updateConversionLabel() { - QString amount = ui->lineAmount->text(); - - int curIndex = ui->comboBox_currency->currentIndex(); - QString symbolFrom = (curIndex == curr::XMR) ? "XMR" : "BTC"; - QString symbolTo = (curIndex == curr::XMR) ? "BTC" : "XMR"; - - if(amount.isEmpty()) { - ui->xmrLabelEstimate->setText(QString("0.00 %1").arg(symbolTo)); - return; - } - auto amount_num = amount.toDouble(); - auto amount_converted = AppContext::prices->convert(symbolFrom, symbolTo, amount_num); - auto amount_converted_str = QString::number(amount_converted, 'f', 2); - - auto fiat_cur = config()->get(Config::preferredFiatCurrency).toString(); - auto amount_fiat = AppContext::prices->convert(symbolFrom, fiat_cur, amount_num); - auto amount_fiat_str = QString::number(amount_fiat, 'f', 2); - - ui->xmrLabelEstimate->setText(QString("%1 %2, %3 %4").arg(amount_converted_str, symbolTo, amount_fiat_str, fiat_cur)); -} - -void XMRToWidget::onGetRates() { - ui->btnGetRates->setEnabled(false); - ui->btnCreate->setEnabled(false); - emit getRates(); -} - -void XMRToWidget::onConnectionError(QString msg) { - ui->btnGetRates->setEnabled(true); - ui->btnCreate->setEnabled(false); - msg = QString("%1\n\n%2").arg(msg).arg(m_regionBlockMessage); - QMessageBox::warning(this, "XMR.To Connection Error", msg); -} - -void XMRToWidget::onConnectionSuccess() { - ui->btnGetRates->setEnabled(true); - ui->btnCreate->setEnabled(true); -} - -void XMRToWidget::onRatesUpdated(XmrToRates rates) { - ui->label_rate->setText(QString("%1 BTC").arg(QString::number(rates.price))); - ui->label_minimum->setText(QString("%1 BTC").arg(QString::number(rates.lower_limit))); - ui->label_maximum->setText(QString("%1 BTC").arg(QString::number(rates.upper_limit))); - - if(!m_ratesDisplayed) { - ui->ratesLayout->setVisible(true); - m_ratesDisplayed = true; - } -} - -void XMRToWidget::onInitiateTransaction() { - ui->btnCreate->setEnabled(false); -} - -void XMRToWidget::onEndTransaction() { - ui->btnCreate->setEnabled(true); -} - -void XMRToWidget::showInfoDialog() { - QModelIndex index = ui->historyTable->currentIndex(); - XmrToOrder *order = this->tableModel->orders->at(index.row()); - auto *dialog = new XmrToInfoDialog(order, this); - dialog->exec(); - dialog->deleteLater(); -} - -XMRToWidget::~XMRToWidget() { - delete ui; -} diff --git a/src/xmrtowidget.h b/src/xmrtowidget.h deleted file mode 100644 index 59f6870..0000000 --- a/src/xmrtowidget.h +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020-2021, The Monero Project. - -#ifndef XMRTOWIDGET_H -#define XMRTOWIDGET_H - -#include -#include "widgets/tickerwidget.h" -#include "utils/xmrto.h" -#include "appcontext.h" - -namespace Ui { - class XMRToWidget; -} - -class XMRToWidget : public QWidget -{ -Q_OBJECT - -public: - explicit XMRToWidget(QWidget *parent = nullptr); - void setHistoryModel(XmrToModel *model); - ~XMRToWidget() override; - -public slots: - void onWalletClosed(); - void onGetRates(); - void onConnectionError(QString msg); - void onConnectionSuccess(); - void onRatesUpdated(XmrToRates rates); - void onTorCheckBoxToggled(int state); - void onCreateOrder(); - void onBalanceUpdated(quint64 balance, quint64 spendable); - void updateConversionLabel(); - - void onInitiateTransaction(); - void onEndTransaction(); - -signals: - void getRates(); - void networkChanged(bool clearnet); - void createOrder(double btnAmount, QString currency, QString btnAddress); - void viewOrder(const QString &orderId); - -private: - void showInfoDialog(); - - QMap m_tickerWidgets; - QMenu *m_contextMenu; - QAction *m_viewOnXmrToAction; - QAction *m_showDetailsAction; - - Ui::XMRToWidget *ui; - AppContext *m_ctx; - bool m_ratesDisplayed = false; - const QString m_regionBlockMessage = "Beware that XMR.To region blocks certain IPs, which can be problematic in combination with Tor. " - "Wait a few minutes for the circuit to switch, or disable the option to relay over Tor if the problem persists."; - double m_unlockedBalance = 0; - XmrToModel *tableModel; - - enum curr { - BTC = 0, - XMR - }; -}; - -#endif diff --git a/src/xmrtowidget.ui b/src/xmrtowidget.ui deleted file mode 100644 index 8726ea7..0000000 --- a/src/xmrtowidget.ui +++ /dev/null @@ -1,327 +0,0 @@ - - - XMRToWidget - - - - 0 - 0 - 896 - 472 - - - - Form - - - - - - - - - - Relay over Tor - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Get Rates - - - - - - - false - - - Create Order - - - - - - - - - Amount - - - - - - - - - 0 - - - - - - 0 - 0 - - - - - - - - - - - - - - - BTC - - - - - XMR - - - - - - - - - - 0.00 XMR - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - - - - - - - BTC address - - - - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - - 169 - 48 - - - - - - - - - - - - - - Pay to - - - - - - - - - QFrame::Sunken - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 0 - - - 1 - - - 0 - - - 6 - - - - - Rate (1 XMR) - - - - 6 - - - 6 - - - 6 - - - 4 - - - - - Rate - - - - - - - - - - Minimum - - - - 6 - - - 6 - - - 6 - - - 4 - - - - - Minimum - - - - - - - - - - Maximum - - - - 6 - - - 6 - - - 6 - - - 4 - - - - - Maximum - - - - - - - - - - - - - false - - - - - - - -