From 41f78b5f892b061a33e6686d417ddb03411ae377 Mon Sep 17 00:00:00 2001 From: twiddle Date: Thu, 8 Aug 2024 23:49:37 -0400 Subject: [PATCH] Minor Refactoring and addition of behind the scene changes to swap settings based on feather configuration. Atomic will no longer appear if feather is launched in testnet mode. DONE: 1. Connect signals to make status of swap reflected in AtomicSwap dialog 2. Add informational tabs to AtomicSwap dialog 4. Add recovery to atomic widget 5. Refactor AtomicWidget so AtomicSwap handles parsing of swap binary output. TODO: 3. Add cancel and refund functionality to AtomicSwap when things go wrong --- src/MainWindow.cpp | 1 + src/plugins/PluginRegistry.h | 3 +- src/plugins/atomic/AtomicConfigDialog.cpp | 6 +- src/plugins/atomic/AtomicPlugin.cpp | 11 +++- src/plugins/atomic/AtomicRecoverDialog.cpp | 46 ++++++++++++-- src/plugins/atomic/AtomicRecoverDialog.h | 5 ++ src/plugins/atomic/AtomicRecoverDialog.ui | 61 +++++++++++++++++-- src/plugins/atomic/AtomicSwap.cpp | 14 ++++- src/plugins/atomic/AtomicWidget.cpp | 70 ++++++++++++---------- src/plugins/atomic/AtomicWidget.h | 4 -- 10 files changed, 165 insertions(+), 56 deletions(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 9c8814d..62c880b 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -69,6 +69,7 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa this->restoreGeo(); this->initStatusBar(); + this->initPlugins(); this->initWidgets(); this->initMenu(); diff --git a/src/plugins/PluginRegistry.h b/src/plugins/PluginRegistry.h index 020d2b2..e63aef4 100644 --- a/src/plugins/PluginRegistry.h +++ b/src/plugins/PluginRegistry.h @@ -6,6 +6,7 @@ #include "Plugin.h" #include "utils/config.h" +#include "constants.h" class PluginRegistry { public: @@ -35,7 +36,7 @@ public: } bool isPluginEnabled(const QString &id) { - if (!pluginMap.contains(id)) { + if (!pluginMap.contains(id) or (QString::compare(id,"atomic")==0 && constants::networkType==NetworkType::TESTNET)) { return false; } diff --git a/src/plugins/atomic/AtomicConfigDialog.cpp b/src/plugins/atomic/AtomicConfigDialog.cpp index c4fc412..c9dbfe5 100644 --- a/src/plugins/atomic/AtomicConfigDialog.cpp +++ b/src/plugins/atomic/AtomicConfigDialog.cpp @@ -90,7 +90,7 @@ void AtomicConfigDialog::extract() { swapPath.append("/swapTool"); QFile binaryFile(swapPath); binaryFile.open(QIODevice::WriteOnly); - auto operatingSystem = Config::instance()->get(Config::operatingSystem).toString().toStdString(); + auto operatingSystem = conf()->get(Config::operatingSystem).toString().toStdString(); if(strcmp("WIN",operatingSystem.c_str()) == 0) { // UNZIP zip *z = zip_open(tempFile.toStdString().c_str(), 0, 0); @@ -114,7 +114,7 @@ void AtomicConfigDialog::extract() { zip_fclose(f); //And close the archive zip_close(z); - Config::instance()->set(Config::swapPath,swapPath); + conf()->set(Config::swapPath,swapPath); } else { struct archive *a; @@ -145,7 +145,7 @@ void AtomicConfigDialog::extract() { archive_write_close(ext); archive_write_free(ext); - Config::instance()->set(Config::swapPath, QString(savePath.c_str())); + conf()->set(Config::swapPath, QString(savePath.c_str())); } qDebug() << "Finished"; binaryFile.close(); diff --git a/src/plugins/atomic/AtomicPlugin.cpp b/src/plugins/atomic/AtomicPlugin.cpp index ddaf240..45fea3c 100644 --- a/src/plugins/atomic/AtomicPlugin.cpp +++ b/src/plugins/atomic/AtomicPlugin.cpp @@ -5,6 +5,7 @@ #include "AtomicConfigDialog.h" #include "plugins/PluginRegistry.h" +#include "constants.h" AtomicPlugin::AtomicPlugin() { @@ -64,7 +65,11 @@ void AtomicPlugin::skinChanged() { } const bool AtomicPlugin::registered = [] { - PluginRegistry::registerPlugin(AtomicPlugin::create()); - PluginRegistry::getInstance().registerPluginCreator(&AtomicPlugin::create); - return true; + if(constants::networkType!=NetworkType::TESTNET) { + PluginRegistry::registerPlugin(AtomicPlugin::create()); + PluginRegistry::getInstance().registerPluginCreator(&AtomicPlugin::create); + return true; + } + + return false; }(); diff --git a/src/plugins/atomic/AtomicRecoverDialog.cpp b/src/plugins/atomic/AtomicRecoverDialog.cpp index 118e00a..fa00416 100644 --- a/src/plugins/atomic/AtomicRecoverDialog.cpp +++ b/src/plugins/atomic/AtomicRecoverDialog.cpp @@ -8,20 +8,27 @@ #include "ui_AtomicRecoverDialog.h" #include "History.h" #include "config.h" +#include "AtomicSwap.h" #include AtomicRecoverDialog::AtomicRecoverDialog(QWidget *parent) : - WindowModalDialog(parent), ui(new Ui::AtomicRecoverDialog) { + WindowModalDialog(parent), ui(new Ui::AtomicRecoverDialog), swapDialog(new AtomicSwap(this)) { ui->setupUi(this); auto model = new QStandardItemModel(); ui->swap_history->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->swap_history->setModel(model); + ui->btn_refund_resume->setVisible(false); + ui->swap_history->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->swap_history->verticalHeader()->setVisible(false); + // Makes it easy to see if button is in refund or resume mode + ui->btn_refund_resume->setProperty("Refund",0); + this->setWindowFlag(Qt::WindowStaysOnTopHint); model->setHorizontalHeaderItem(0, new QStandardItem("Swap-Id")); model->setHorizontalHeaderItem(1, new QStandardItem("Timestamp swap started")); model->setHorizontalHeaderItem(2, new QStandardItem("Status")); QList rowData; - auto data = Config::instance()->get(Config::pendingSwap).value(); + auto data = conf()->get(Config::pendingSwap).value(); for(int i=0; i< data.size(); i++){ auto entry = data[i].value(); qint64 difference = entry.timestamp.secsTo(QDateTime::currentDateTime()); @@ -39,20 +46,47 @@ AtomicRecoverDialog::AtomicRecoverDialog(QWidget *parent) : data.remove(i); } } - Config::instance()->set(Config::pendingSwap,data); + conf()->set(Config::pendingSwap,data); + connect(ui->swap_history, &QAbstractItemView::clicked, this, &AtomicRecoverDialog::updateBtn); + connect(ui->btn_refund_resume, &QPushButton::clicked, this, [this]{ + QStringList arguments; + if (ui->btn_refund_resume->property("Refund").toBool()){ + arguments << "cancel-and-refund"; + } else { + arguments << "resume"; + } + arguments << "--swap-id"; + arguments << ui->swap_history->selectionModel()->selectedRows().at(0).sibling(0,1).data().toString(); + arguments << "--tor-socks5-port"; + arguments << conf()->get(Config::socks5Port).toString(); + swapDialog->runSwap(arguments); + }); +} + +void AtomicRecoverDialog::updateBtn(const QModelIndex &index){ + auto row = index.sibling(index.row(),2).data().toString(); + if (row.startsWith("Ref")){ + ui->btn_refund_resume->setText("Cancel And Refund"); + ui->btn_refund_resume->setProperty("Refund",1); + } else { + ui->btn_refund_resume->setText("Attempt to Resume"); + ui->btn_refund_resume->setProperty("Refund",0); + } + ui->btn_refund_resume->setVisible(true); + } bool AtomicRecoverDialog::historyEmpty(){ - return Config::instance()->get(Config::pendingSwap).value().isEmpty(); + return conf()->get(Config::pendingSwap).value().isEmpty(); } void AtomicRecoverDialog::appendHistory(HistoryEntry entry){ - auto current = Config::instance()->get(Config::pendingSwap).value(); + auto current = conf()->get(Config::pendingSwap).value(); auto var = QVariant(); var.setValue(entry); current.append(var); - Config::instance()->set(Config::pendingSwap, current); + conf()->set(Config::pendingSwap, current); } AtomicRecoverDialog::~AtomicRecoverDialog() { delete ui; diff --git a/src/plugins/atomic/AtomicRecoverDialog.h b/src/plugins/atomic/AtomicRecoverDialog.h index 8e5099e..0558a2f 100644 --- a/src/plugins/atomic/AtomicRecoverDialog.h +++ b/src/plugins/atomic/AtomicRecoverDialog.h @@ -8,6 +8,7 @@ #include #include "components.h" #include "History.h" +#include "AtomicSwap.h" QT_BEGIN_NAMESPACE namespace Ui { class AtomicRecoverDialog; } @@ -22,8 +23,12 @@ public: void appendHistory(HistoryEntry entry); ~AtomicRecoverDialog() override; +private slots: + void updateBtn(const QModelIndex &index); private: Ui::AtomicRecoverDialog *ui; + AtomicSwap *swapDialog; + }; diff --git a/src/plugins/atomic/AtomicRecoverDialog.ui b/src/plugins/atomic/AtomicRecoverDialog.ui index 30d56ff..092a9bb 100644 --- a/src/plugins/atomic/AtomicRecoverDialog.ui +++ b/src/plugins/atomic/AtomicRecoverDialog.ui @@ -6,22 +6,71 @@ 0 0 - 903 - 248 + 936 + 256 AtomicRecoverDialog - + 10 - 20 - 881 - 179 + 10 + 911 + 211 + + + + + There are one or more Atomic Swaps still pending, take action to prevent losing funds! + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + Resume + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + diff --git a/src/plugins/atomic/AtomicSwap.cpp b/src/plugins/atomic/AtomicSwap.cpp index 73092dd..7fa80d9 100644 --- a/src/plugins/atomic/AtomicSwap.cpp +++ b/src/plugins/atomic/AtomicSwap.cpp @@ -60,13 +60,21 @@ void AtomicSwap::runSwap(QStringList arguments){ this->updateXMRConf(confs.toInt()); } else if (QString message = line["fields"]["message"].toString(); !QString::compare(message, "Bitcoin transaction status changed")){ qDebug() << "Updating btconfs " + line["fields"]["new_status"].toString().split(" ")[2]; - this->updateBTCConf(line["fields"]["new_status"].toString().split(" ")[2].toInt()); + QString status = line["fields"]["new_status"].toString(); + bool ok; + auto confirmations = status.split(" ")[2].toInt(&ok, 10); + if(ok) { + this->updateBTCConf(confirmations); + } else { + this->updateStatus("Found txid " + line["fields"]["txid"].toString() + " in mempool"); + } + } //Insert line conditionals here } }); - swap->start(Config::instance()->get(Config::swapPath).toString(),arguments); + swap->start(conf()->get(Config::swapPath).toString(),arguments); qDebug() << "process started"; } AtomicSwap::~AtomicSwap() { @@ -74,7 +82,7 @@ AtomicSwap::~AtomicSwap() { for (const auto& proc : *procList){ proc->kill(); } - if(QString::compare("WINDOWS",Config::instance()->get(Config::operatingSystem).toString()) != 0) { + if(QString::compare("WINDOWS",conf()->get(Config::operatingSystem).toString()) != 0) { qDebug() << "Closing monero-wallet-rpc"; (new QProcess)->start("kill", QStringList{"-f", Config::defaultConfigDir().absolutePath() + "/mainnet/monero/monero-wallet-rpc"}); diff --git a/src/plugins/atomic/AtomicWidget.cpp b/src/plugins/atomic/AtomicWidget.cpp index 5c32e06..a31d5fc 100644 --- a/src/plugins/atomic/AtomicWidget.cpp +++ b/src/plugins/atomic/AtomicWidget.cpp @@ -11,6 +11,7 @@ #include "AtomicConfigDialog.h" #include "OfferModel.h" #include "utils/AppData.h" +#include "utils/nodes.h" #include "utils/ColorScheme.h" #include "utils/WebsocketNotifier.h" #include "AtomicFundDialog.h" @@ -18,7 +19,6 @@ AtomicWidget::AtomicWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::AtomicWidget) - , m_instance(Config::instance()) , o_model(new OfferModel(this)) , offerList(new QList>()) , swapDialog(new AtomicSwap(this)) @@ -43,7 +43,7 @@ AtomicWidget::AtomicWidget(QWidget *parent) ui->offerBookTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); ui->btn_configure->setEnabled(true); - if (!m_instance->get(Config::swapPath).toString().isEmpty()) + if (!conf()->get(Config::swapPath).toString().isEmpty()) ui->meta_label->setText("Refresh offer book before swapping to prevent errors"); connect(ui->btn_configure, &QPushButton::clicked, this, &AtomicWidget::showAtomicConfigureDialog); @@ -53,7 +53,7 @@ AtomicWidget::AtomicWidget(QWidget *parent) ui->meta_label->setText("Updating offer book this may take a bit, if no offers appear after a while try refreshing again"); - QStringList pointList = m_instance->get(Config::rendezVous).toStringList(); + QStringList pointList = conf()->get(Config::rendezVous).toStringList(); for(const QString& point :pointList) AtomicWidget::list(point); }); @@ -83,22 +83,21 @@ AtomicWidget::AtomicWidget(QWidget *parent) tr("p2p multi address of rendezvous point"), QLineEdit::Normal, "", &ok); if (ok && !text.isEmpty()) { - QStringList copy = m_instance->get(Config::rendezVous).toStringList(); + QStringList copy = conf()->get(Config::rendezVous).toStringList(); copy.append(text); - m_instance->set(Config::rendezVous,copy); + conf()->set(Config::rendezVous,copy); } }); //Remove after testing - //QVariant var; - //var.setValue(HistoryEntry {QDateTime::currentDateTime(),"test-id"}); - //m_instance->set(Config::pendingSwap, QVariantList{var}); - //auto recd = new AtomicRecoverDialog(); - //if (!recd->historyEmpty()){ - // recd->show(); - //} - this->updateStatus(); + QVariant var; + var.setValue(HistoryEntry {QDateTime::currentDateTime(),"test-id"}); + conf()->set(Config::pendingSwap, QVariantList{var}); + auto recd = new AtomicRecoverDialog(this); + if (!recd->historyEmpty()){ + recd->show(); + } } @@ -111,13 +110,6 @@ void AtomicWidget::showAtomicConfigureDialog() { dialog.exec(); } -void AtomicWidget::showAtomicSwapDialog() { - swapDialog->show(); -} - -void AtomicWidget::updateStatus() { - -} void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, const QString& xmrReceive) { qDebug() << "starting swap"; @@ -125,7 +117,9 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons arguments << "--data-base-dir"; arguments << Config::defaultConfigDir().absolutePath(); // Remove after testing - arguments << "--testnet"; + if (constants::networkType==NetworkType::STAGENET){ + arguments << "--testnet"; + } arguments << "--debug"; arguments << "-j"; arguments << "buy-xmr"; @@ -142,12 +136,24 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons arguments << "tcp://127.0.0.1:50001"; arguments << "--bitcoin-target-block"; arguments << "1"; + auto nodes = conf()->get(Config::nodes).toJsonObject(); + if (nodes.isEmpty()) { + auto jsonData = conf()->get(Config::nodes).toByteArray(); + if (Utils::validateJSON(jsonData)) { + auto doc = QJsonDocument::fromJson(jsonData); + nodes = doc.object(); + } + } + qDebug() << nodes.value("0").toObject()["ws"].toArray()[0]; arguments << "--monero-daemon-address"; - arguments << "node.monerodevs.org:38089"; + //arguments << "node.monerodevs.org:38089"; + arguments << nodes.value("0").toObject()["ws"].toArray()[0].toString(); // Uncomment after testing //arguments << seller; - arguments << "--tor-socks5-port"; - arguments << m_instance->get(Config::socks5Port).toString(); + if(conf()->get(Config::proxy).toInt() != Config::Proxy::None) { + arguments << "--tor-socks5-port"; + arguments << conf()->get(Config::socks5Port).toString(); + } swapDialog->runSwap(arguments); } @@ -156,16 +162,21 @@ void AtomicWidget::list(const QString& rendezvous) { QStringList arguments; arguments << "--data-base-dir"; arguments << Config::defaultConfigDir().absolutePath(); + if (constants::networkType==NetworkType::STAGENET){ + arguments << "--testnet"; + } arguments << "-j"; arguments << "list-sellers"; - arguments << "--tor-socks5-port"; - arguments << m_instance->get(Config::socks5Port).toString(); + if(conf()->get(Config::proxy).toInt() != Config::Proxy::None) { + arguments << "--tor-socks5-port"; + arguments << conf()->get(Config::socks5Port).toString(); + } arguments << "--rendezvous-point"; arguments << rendezvous; auto *swap = new QProcess(); procList->append(QSharedPointer(swap)); swap->setReadChannel(QProcess::StandardError); - //swap->start(m_instance->get(Config::swapPath).toString(), arguments); + //swap->start(conf()->get(Config::swapPath).toString(), arguments); connect(swap, &QProcess::finished, this, [this, swap]{ QJsonDocument parsedLine; QJsonParseError parseError; @@ -203,7 +214,7 @@ void AtomicWidget::list(const QString& rendezvous) { o_model->updateOffers(*offerList); return list; }); - swap->start(m_instance->get(Config::swapPath).toString(), arguments); + swap->start(conf()->get(Config::swapPath).toString(), arguments); //swap->waitForFinished(120000); @@ -216,7 +227,6 @@ AtomicWidget::~AtomicWidget() { delete o_model; delete offerList; clean(); - delete m_instance; delete procList; } @@ -224,7 +234,7 @@ void AtomicWidget::clean() { for (const auto& proc : *procList){ proc->kill(); } - if(QString::compare("WINDOWS",m_instance->get(Config::operatingSystem).toString()) != 0) { + if(QString::compare("WINDOWS",conf()->get(Config::operatingSystem).toString()) != 0) { qDebug() << "Closing monero-wallet-rpc"; (new QProcess)->start("kill", QStringList{"-f", Config::defaultConfigDir().absolutePath() + "/mainnet/monero/monero-wallet-rpc"}); diff --git a/src/plugins/atomic/AtomicWidget.h b/src/plugins/atomic/AtomicWidget.h index 015ea94..c465ced 100644 --- a/src/plugins/atomic/AtomicWidget.h +++ b/src/plugins/atomic/AtomicWidget.h @@ -38,8 +38,6 @@ private slots: void runSwap(const QString& seller, const QString& btcChange, const QString& xmrReceive); private: - void updateStatus(); - QScopedPointer ui; bool m_comboBoxInit = false; QTimer m_statusTimer; @@ -48,10 +46,8 @@ private: AtomicSwap *swapDialog; AtomicFundDialog *fundDialog; AtomicRecoverDialog *recoverDialog; - void showAtomicSwapDialog(); QList> *procList; - Config *m_instance; }; #endif // FEATHER_ATOMICWIDGET_H