diff --git a/CMakeLists.txt b/CMakeLists.txt index 6da3e49..ba7c968 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,6 @@ set(VERSION "beta-2") option(FETCH_DEPS "Download dependencies if they are not found" ON) option(XMRTO "Include Xmr.To module" ON) -option(MORPHTOKEN "Include MorphToken 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 6679d4d..fd27af9 100644 --- a/HACKING.md +++ b/HACKING.md @@ -42,7 +42,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 -- `-DMORPHTOKEN=OFF` - disable MorphToken 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 837a0fc..fe1a511 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,6 @@ CMAKEFLAGS = \ -DBUILD_64=On \ -DBUILD_TESTS=Off \ -DXMRTO=On \ - -DMORPHTOKEN=On \ -DXMRIG=On \ -DTOR_BIN=Off \ -DCMAKE_CXX_STANDARD=11 \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1be194c..99c870a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -124,10 +124,6 @@ if(XMRTO) target_compile_definitions(feather PRIVATE HAS_XMRTO=1) endif() -if(MORPHTOKEN) - target_compile_definitions(feather PRIVATE HAS_MORPHTOKEN=1) -endif() - if(TOR_BIN) target_compile_definitions(feather PRIVATE HAS_TOR_BIN=1) endif() diff --git a/src/MorphTokenWidget.cpp b/src/MorphTokenWidget.cpp deleted file mode 100644 index b1fbc55..0000000 --- a/src/MorphTokenWidget.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020, The Monero Project. - -#include "MorphTokenWidget.h" -#include "ui_MorphTokenWidget.h" -#include "mainwindow.h" -#include "qrcode/QrCode.h" -#include "dialog/qrcodedialog.h" - -#include - -MorphTokenWidget::MorphTokenWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::MorphTokenWidget) -{ - ui->setupUi(this); - m_ctx = MainWindow::getContext(); - - m_network = new UtilsNetworking(this->m_ctx->network); - m_api = new MorphTokenApi(this, m_network); - - connect(ui->btnCreateTrade, &QPushButton::clicked, this, &MorphTokenWidget::createTrade); - connect(ui->btn_lookupTrade, &QPushButton::clicked, this, &MorphTokenWidget::lookupTrade); - connect(ui->btn_getRates, &QPushButton::clicked, this, &MorphTokenWidget::getRates); - - connect(m_api, &MorphTokenApi::ApiResponse, this, &MorphTokenWidget::onApiResponse); - - connect(ui->combo_From, QOverload::of(&QComboBox::currentIndexChanged), [this](int index){ - this->displayRate(); - ui->label_refundAddress->setText(QString("Refund address (%1):").arg(ui->combo_From->currentText())); - }); - connect(ui->combo_To, QOverload::of(&QComboBox::currentIndexChanged), [this](int index){ - this->displayRate(); - ui->label_destinationAddress->setText(QString("Destination address (%1):").arg(ui->combo_To->currentText())); - }); - - connect(ui->check_autorefresh, &QCheckBox::toggled, [this](bool toggled){ - m_countdown = 30; - toggled ? m_countdownTimer.start(1000) : m_countdownTimer.stop(); - ui->check_autorefresh->setText("Autorefresh"); - }); - connect(&m_countdownTimer, &QTimer::timeout, this, &MorphTokenWidget::onCountdown); - - connect(ui->line_Id, &QLineEdit::textChanged, [this](const QString &text){ - ui->btn_lookupTrade->setEnabled(!text.isEmpty()); - ui->check_autorefresh->setEnabled(!text.isEmpty()); - }); - - // Default to BTC -> XMR - ui->combo_From->setCurrentIndex(1); - ui->combo_To->setCurrentIndex(0); - - ui->label_rate->setVisible(false); - m_ratesTimer.setSingleShot(true); - connect(&m_ratesTimer, &QTimer::timeout, [this]{ - ui->label_rate->setVisible(false); - }); - - ui->qrCode->setVisible(false); - ui->label_depositAddress->setVisible(false); - connect(ui->qrCode, &ClickableLabel::clicked, this, &MorphTokenWidget::showQrCodeDialog); - - ui->tabWidget->setTabVisible(2, false); -} - -void MorphTokenWidget::createTrade() { - QString inputAsset = ui->combo_From->currentText(); - QString outputAsset = ui->combo_To->currentText(); - QString refundAddress = ui->line_refundAddress->text(); - QString destinationAddress = ui->line_destinationAddress->text(); - - m_api->createTrade(inputAsset, outputAsset, refundAddress, destinationAddress); -} - -void MorphTokenWidget::lookupTrade() { - QString morphId = ui->line_Id->text(); - - if (!morphId.isEmpty()) - m_api->getTrade(morphId); -} - -void MorphTokenWidget::getRates() { - m_api->getRates(); -} - -void MorphTokenWidget::onApiResponse(const MorphTokenApi::MorphTokenResponse &resp) { - if (!resp.ok) { - ui->check_autorefresh->setChecked(false); - QMessageBox::warning(this, "MorphToken error", QString("Request failed:\n\n%1").arg(resp.message)); - return; - } - - ui->debugInfo->setPlainText(QJsonDocument(resp.obj).toJson(QJsonDocument::Indented)); - - bool shouldShowQr = (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE || resp.endpoint == MorphTokenApi::Endpoint::GET_TRADE); - ui->qrCode->setVisible(shouldShowQr); - ui->label_depositAddress->setVisible(shouldShowQr); - - if (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE || resp.endpoint == MorphTokenApi::Endpoint::GET_TRADE) { - ui->tabWidget->setCurrentIndex(1); - ui->line_Id->setText(resp.obj.value("id").toString()); - - auto obj = resp.obj; - auto input = obj["input"].toObject(); - auto output = obj["output"].toArray()[0].toObject(); - QString state = obj.value("state").toString(); - QString statusText; - - ui->trade->setTitle(QString("Trade (%1)").arg(state)); - - statusText += QString("Morph ID: %1\n\n").arg(obj["id"].toString()); - - if (state == "PENDING") { - statusText += QString("Waiting for a deposit, send %1 to %2\n").arg(input["asset"].toString(), - input["deposit_address"].toString()); - statusText += QString("Rate: 1 %1 -> %2 %3\n\n").arg(input["asset"].toString(), - output["seen_rate"].toString(), - output["asset"].toString()); - statusText += "Limits:\n"; - statusText += QString(" Minimum amount accepted: %1 %2\n").arg(formatAmount(input["asset"].toString(), input["limits"].toObject()["min"].toDouble()), - input["asset"].toString()); - statusText += QString(" Maximum amount accepted: %1 %2\n").arg(formatAmount(input["asset"].toString(), input["limits"].toObject()["max"].toDouble()), - input["asset"].toString()); - statusText += QString("\nSend a single deposit. If the amount is outside the limits, a refund will happen."); - - m_depositAddress = input["deposit_address"].toString(); - - const QrCode qrc(m_depositAddress, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::MEDIUM); - int width = ui->qrCode->width(); - if (qrc.isValid()) { - ui->qrCode->setPixmap(qrc.toPixmap(1).scaled(width, width, Qt::KeepAspectRatio)); - } - } else if (state == "PROCESSING" || state == "TRADING" || state == "CONFIRMING") { - if (state == "CONFIRMING") { - statusText += QString("Waiting for confirmations\n"); - } else if (state == "TRADING") { - statusText += QString("Your transaction has been received and is confirmed. MorphToken is now executing your trade.\n" - "Usually this step takes no longer than a minute, " - "but in rare cases it can take a couple hours.\n" - "Wait a bit before contacting support.\n"); - } - statusText += QString("Converting %1 to %2\n").arg(input["asset"].toString(), output["asset"].toString()); - statusText += QString("Sending to %1\n").arg(output["address"].toString()); - statusText += QString("Stuck? Contact support at contact@morphtoken.com"); - } else if (state == "COMPLETE") { - if (output["txid"].toString().isEmpty()) { - statusText += QString("MorphToken is sending your transaction.\n"); - statusText += QString("MorphToken will send %1 %2 to %2").arg(this->formatAmount(output["asset"].toString(), output["converted_amount"].toDouble() - output["network_fee"].toObject()["fee"].toDouble()), - output["asset"].toString(), - output["address"].toString()); - } else { - statusText += QString("Sent %1 %2 to %3\ntxid: {}").arg(this->formatAmount(output["asset"].toString(), output["converted_amount"].toDouble() - output["network_fee"].toObject()["fee"].toDouble()), - output["asset"].toString(), - output["address"].toString(), - output["txid"].toString()); - } - } else if (state == "PROCESSING_REFUND" || state == "COMPLETE_WITH_REFUND") { - statusText += QString("MorphToken will refund %1 %2\nReason: %3\n").arg(obj["final_amount"].toString(), - obj["asset"].toString(), - obj["reason"].toString()); - - if (obj.contains("txid")) { - statusText += QString("txid: %1").arg(obj["txid"].toString()); - } - } else if (state == "COMPLETE_WITHOUT_REFUND") { - statusText += "Deposit amount below network fee, too small to refund."; - } else if (state == "PROCESSING_DELAY") { - statusText += "Please enter in contact with support.\n\ncontact@morphtoken.com"; - } else if (state == "CANCELLED") { - statusText += "The trade was cancelled. If this is unexpected, please contact support at contact@morphtoken.com"; - } - - ui->label_status->setText(statusText); - } else if (resp.endpoint == MorphTokenApi::Endpoint::GET_RATES) { - m_rates = resp.obj.value("data").toObject(); - this->displayRate(); - ui->label_rate->setVisible(true); - m_ratesTimer.start(120 * 1000); - } - - if (resp.endpoint == MorphTokenApi::Endpoint::CREATE_TRADE) { - QMessageBox::information(this, "MorphToken", "Trade created!\n\nMake sure to save your Morph ID. You may need it in case something goes wrong."); - } -} - -void MorphTokenWidget::onCountdown() { - if (m_countdown > 0) { - m_countdown -= 1; - } else { - this->lookupTrade(); - m_countdown = 30; - } - ui->check_autorefresh->setText(QString("Autorefresh (%1)").arg(m_countdown)); -} - -void MorphTokenWidget::displayRate() { - QString inputAsset = ui->combo_From->currentText(); - QString outputAsset = ui->combo_To->currentText(); - QString outputRate = m_rates.value(inputAsset).toObject().value(outputAsset).toString("1"); - - QString rateStr = QString("1 %1 -> %2 %3").arg(inputAsset, outputRate, outputAsset); - ui->label_rate->setText(rateStr); -} - -void MorphTokenWidget::showQrCodeDialog() { - QrCode qr(m_depositAddress, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH); - auto *dialog = new QrCodeDialog(this, qr, "Deposit address"); - dialog->exec(); - dialog->deleteLater(); -} - -QString MorphTokenWidget::formatAmount(const QString &asset, double amount) { - double displayAmount; - double div; - - if (asset == "ETH") - div = 1e18; - else if (asset == "XMR") - div = 1e12; - else - div = 1e8; - - displayAmount = amount / div; - - return QString::number(displayAmount, 'f', 8); -} - -MorphTokenWidget::~MorphTokenWidget() { - delete ui; -} diff --git a/src/MorphTokenWidget.h b/src/MorphTokenWidget.h deleted file mode 100644 index 0f0961f..0000000 --- a/src/MorphTokenWidget.h +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020, The Monero Project. - -#ifndef FEATHER_MORPHTOKENWIDGET_H -#define FEATHER_MORPHTOKENWIDGET_H - -#include -#include "appcontext.h" -#include "utils/MorphTokenApi.h" - -namespace Ui { - class MorphTokenWidget; -} - -class MorphTokenWidget : public QWidget -{ -Q_OBJECT - -public: - explicit MorphTokenWidget(QWidget *parent = nullptr); - ~MorphTokenWidget() override; - -private: - void createTrade(); - void lookupTrade(); - void getRates(); - void onApiResponse(const MorphTokenApi::MorphTokenResponse &resp); - - void onCountdown(); - void displayRate(); - void showQrCodeDialog(); - - QString formatAmount(const QString &asset, double amount); - - Ui::MorphTokenWidget *ui; - - AppContext *m_ctx; - MorphTokenApi *m_api; - UtilsNetworking *m_network; - QTimer m_countdownTimer; - int m_countdown = 30; - QJsonObject m_rates; - QTimer m_ratesTimer; - QString m_depositAddress; -}; - -#endif //FEATHER_MORPHTOKENWIDGET_H diff --git a/src/MorphTokenWidget.ui b/src/MorphTokenWidget.ui deleted file mode 100644 index 85414db..0000000 --- a/src/MorphTokenWidget.ui +++ /dev/null @@ -1,423 +0,0 @@ - - - MorphTokenWidget - - - - 0 - 0 - 1036 - 614 - - - - Form - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - - - - Create trade - - - - - - - - - 0 - 0 - - - - From: - - - - - - - - XMR - - - - - BTC - - - - - ETH - - - - - BCH - - - - - LTC - - - - - DASH - - - - - - - - - 0 - 0 - - - - To: - - - - - - - - XMR - - - - - BTC - - - - - ETH - - - - - BCH - - - - - LTC - - - - - DASH - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - rate - - - - - - - - - - - Refund address (XMR): - - - - - - - - - - Destination address (XMR): - - - - - - - - - - - - - - false - - - Powered by MorphToken.com - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Get Rates - - - - - - - Create Trade - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Lookup trade - - - - - - Morph ID or MorphToken deposit address: - - - - - - - - - - - - false - - - Autorefresh - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Lookup trade - - - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - Trade - - - - - - - - No trade loaded. - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - - - 0 - 0 - - - - qrcode - - - - - - - Deposit address - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - Debug - - - - - - - 0 - 0 - - - - true - - - - - - - - - - - - ClickableLabel - QLabel -
components.h
-
-
- - -
diff --git a/src/assets.qrc b/src/assets.qrc index 50cc4f6..5ad38bb 100644 --- a/src/assets.qrc +++ b/src/assets.qrc @@ -48,7 +48,6 @@ assets/images/lock.svg assets/images/microphone.png assets/images/mining.png - assets/images/morphtoken.png assets/images/network.png assets/images/offline_tx.png assets/images/person.svg diff --git a/src/assets/images/morphtoken.png b/src/assets/images/morphtoken.png deleted file mode 100644 index 3d5db60..0000000 Binary files a/src/assets/images/morphtoken.png and /dev/null differ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d7c2a00..4b54fa8 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -121,10 +121,6 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : ui->tabExchanges->setTabVisible(0, false); #endif -#ifndef HAS_MORPHTOKEN - ui->tabExchanges->setTabVisible(1, false); -#endif - #if defined(Q_OS_LINUX) // system tray m_trayIcon = new QSystemTrayIcon(QIcon(":/assets/images/appicons/64x64.png")); @@ -400,14 +396,6 @@ 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) || defined(HAS_MORPHTOKEN) - 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_Exchanges->setVisible(false); -#endif - #if defined(HAS_XMRIG) connect(ui->actionShow_XMRig, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map)); m_tabShowHideMapper["Mining"] = new ToggleTab(ui->tabXmrRig, "Mining", "Mining", ui->actionShow_XMRig, Config::showTabXMRig); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 334d5f2..460f1f2 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -324,32 +324,6 @@ - - - - :/assets/images/morphtoken.png:/assets/images/morphtoken.png - - - MorphToken - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - @@ -784,12 +758,6 @@
calcwidget.h
1 - - MorphTokenWidget - QWidget -
MorphTokenWidget.h
- 1 -
CCSWidget QWidget diff --git a/src/utils/MorphTokenApi.cpp b/src/utils/MorphTokenApi.cpp deleted file mode 100644 index eae1380..0000000 --- a/src/utils/MorphTokenApi.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020, The Monero Project. - -#include "MorphTokenApi.h" - -MorphTokenApi::MorphTokenApi(QObject *parent, UtilsNetworking *network, QString baseUrl) - : QObject(parent) - , m_network(network) - , m_baseUrl(std::move(baseUrl)) -{ -} - -void MorphTokenApi::createTrade(const QString &inputAsset, const QString &outputAsset, const QString &refundAddress, const QString &outputAddress) { - QJsonObject trade; - - QJsonObject input; - input["asset"] = inputAsset; - input["refund"] = refundAddress; - - QJsonArray output; - QJsonObject outputObj; - outputObj["asset"] = outputAsset; - outputObj["weight"] = 10000; - outputObj["address"] = outputAddress; - output.append(outputObj); - - trade["input"] = input; - trade["output"] = output; - - QString url = QString("%1/morph").arg(m_baseUrl); - QNetworkReply *reply = m_network->postJson(url, trade); - connect(reply, &QNetworkReply::finished, std::bind(&MorphTokenApi::onResponse, this, reply, Endpoint::CREATE_TRADE)); -} - -void MorphTokenApi::getTrade(const QString &morphId) { - QString url = QString("%1/morph/%2").arg(m_baseUrl, morphId); - QNetworkReply *reply = m_network->getJson(url); - connect(reply, &QNetworkReply::finished, std::bind(&MorphTokenApi::onResponse, this, reply, Endpoint::GET_TRADE)); -} - -void MorphTokenApi::getRates() { - QString url = QString("%1/rates").arg(m_baseUrl); - QNetworkReply *reply = m_network->getJson(url); - connect(reply, &QNetworkReply::finished, std::bind(&MorphTokenApi::onResponse, this, reply, Endpoint::GET_RATES)); -} - -void MorphTokenApi::getLimits(const QString &inputAsset, const QString &outputAsset) { - QJsonObject limits; - - QJsonObject input; - input["asset"] = inputAsset; - - QJsonArray output; - QJsonObject outputObj; - outputObj["asset"] = outputAsset; - outputObj["weight"] = 10000; - output.append(outputObj); - - limits["input"] = input; - limits["output"] = output; - - QString url = QString("%1/limits").arg(m_baseUrl); - QNetworkReply *reply = m_network->postJson(url, limits); - connect(reply, &QNetworkReply::finished, std::bind(&MorphTokenApi::onResponse, this, reply, Endpoint::GET_LIMITS)); -} - -void MorphTokenApi::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(MorphTokenResponse(false, endpoint, err, {})); - return; - } - else { - emit ApiResponse(MorphTokenResponse(false, endpoint, "Invalid response from MorphToken", {})); - return; - } - - if (obj.contains("success")) { - emit ApiResponse(MorphTokenResponse(false, endpoint, obj.value("description").toString(), obj)); - return; - } - - reply->deleteLater(); - emit ApiResponse(MorphTokenResponse(true, endpoint, "", obj)); -} \ No newline at end of file diff --git a/src/utils/MorphTokenApi.h b/src/utils/MorphTokenApi.h deleted file mode 100644 index b96a96c..0000000 --- a/src/utils/MorphTokenApi.h +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2020, The Monero Project. - -#ifndef FEATHER_MORPHTOKENAPI_H -#define FEATHER_MORPHTOKENAPI_H - -#include -#include -#include "utils/networking.h" - -class MorphTokenApi : public QObject { - Q_OBJECT - -public: - enum Endpoint { - CREATE_TRADE = 0, - GET_TRADE, - GET_RATES, - GET_LIMITS - }; - - struct MorphTokenResponse { - explicit MorphTokenResponse(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; - QJsonObject obj; - }; - - explicit MorphTokenApi(QObject *parent, UtilsNetworking *network, QString baseUrl = "https://api.morphtoken.com"); - - void createTrade(const QString &inputAsset, const QString &outputAsset, const QString &refundAddress, const QString &outputAddress); - void getTrade(const QString &morphId); - void getRates(); - void getLimits(const QString &inputAsset, const QString &outputAsset); - -signals: - void ApiResponse(MorphTokenResponse resp); - -private slots: - void onResponse(QNetworkReply *reply, Endpoint endpoint); - -private: - QString m_baseUrl; - UtilsNetworking *m_network; -}; - - -#endif //FEATHER_MORPHTOKENAPI_H