diff --git a/src/plugins/atomic/AtomicConfigDialog.cpp b/src/plugins/atomic/AtomicConfigDialog.cpp index c9dbfe5..b627074 100644 --- a/src/plugins/atomic/AtomicConfigDialog.cpp +++ b/src/plugins/atomic/AtomicConfigDialog.cpp @@ -58,13 +58,14 @@ void AtomicConfigDialog::downloadBinary() { tempFile = download->fileName(); QString url; auto operatingSystem = Config::instance()->get(Config::operatingSystem).toString().toStdString(); + QString firstPart = "https://github.com/comit-network/xmr-btc-swap/releases/download/" + conf()->get(Config::swapVersion).toString(); if(strcmp("WIN",operatingSystem.c_str()) == 0) { // HARD CODED DOWNload URL CHANGE IF PROBLEMS - url = QString("https://github.com/comit-network/xmr-btc-swap/releases/download/0.13.1/swap_0.13.1_Windows_x86_64.zip"); + url = QString(firstPart+"/swap_"+conf()->get(Config::swapVersion).toString()+"_Windows_x86_64.zip"); } else if (strcmp("LINUX",operatingSystem.c_str())==0){ - url = QString("https://github.com/comit-network/xmr-btc-swap/releases/download/0.13.1/swap_0.13.1_Linux_x86_64.tar"); + url = QString(firstPart+"/swap_"+conf()->get(Config::swapVersion).toString()+"_Linux_x86_64.tar"); } else { - url = QString("https://github.com/comit-network/xmr-btc-swap/releases/download/0.13.1/swap_0.13.1_Linux_x86_64.tar"); + url = QString(firstPart + "/swap_" + conf()->get(Config::swapVersion).toString() + "_Darwin_x86_64.tar"); } archive = network->get(this, url); @@ -72,7 +73,6 @@ void AtomicConfigDialog::downloadBinary() { QStringList answer; connect(archive,&QNetworkReply::readyRead, this, [this]{ QByteArray data= archive->readAll(); - qDebug() << "received data of size: " << data.size(); download->write(data.constData(), data.size()); }); connect(archive, &QNetworkReply::finished, @@ -82,7 +82,6 @@ void AtomicConfigDialog::downloadBinary() { void AtomicConfigDialog::extract() { ui->downloadLabel->setText("Download Successful, extracting binary to final destination"); - qDebug() << "extracting"; download->close(); archive->deleteLater(); diff --git a/src/plugins/atomic/AtomicRecoverDialog.cpp b/src/plugins/atomic/AtomicRecoverDialog.cpp index fa00416..e6cd086 100644 --- a/src/plugins/atomic/AtomicRecoverDialog.cpp +++ b/src/plugins/atomic/AtomicRecoverDialog.cpp @@ -9,6 +9,7 @@ #include "History.h" #include "config.h" #include "AtomicSwap.h" +#include "Utils.h" #include AtomicRecoverDialog::AtomicRecoverDialog(QWidget *parent) : @@ -57,8 +58,20 @@ AtomicRecoverDialog::AtomicRecoverDialog(QWidget *parent) : } 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(); + arguments << "--monero-daemon-address"; + 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(); + } + } + arguments << nodes.value("0").toObject()["ws"].toArray()[0].toString(); + if(conf()->get(Config::proxy).toInt() != Config::Proxy::None) { + arguments << "--tor-socks5-port"; + arguments << conf()->get(Config::socks5Port).toString(); + } swapDialog->runSwap(arguments); }); } diff --git a/src/plugins/atomic/AtomicSwap.cpp b/src/plugins/atomic/AtomicSwap.cpp index 7fa80d9..74604dc 100644 --- a/src/plugins/atomic/AtomicSwap.cpp +++ b/src/plugins/atomic/AtomicSwap.cpp @@ -6,8 +6,8 @@ #include "AtomicSwap.h" -#include #include +#include #include "ui_AtomicSwap.h" #include "AtomicWidget.h" @@ -15,7 +15,6 @@ AtomicSwap::AtomicSwap(QWidget *parent) : WindowModalDialog(parent), ui(new Ui::AtomicSwap), fundDialog( new AtomicFundDialog(this)), procList(new QList>()) { ui->setupUi(this); - //ui->debug_log->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); ui->label_status->setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse); QPixmap pixmapTarget = QPixmap(":/assets/images/hint-icon.png"); int size=20; @@ -33,7 +32,6 @@ void AtomicSwap::runSwap(QStringList arguments){ swap->setProcessChannelMode(QProcess::MergedChannels); swap->setReadChannel(QProcess::StandardOutput); connect(swap, &QProcess::readyRead,this, [this, swap] { - //Refactor and move this to a slot in atomicswap, move fund dialog to be part of atomic swap while(swap->canReadLine()){ QJsonParseError err; const QByteArray& rawline = swap->readLine(); @@ -51,14 +49,18 @@ void AtomicSwap::runSwap(QStringList arguments){ fundDialog->show(); } else if (line["fields"]["message"].toString().startsWith("Received Bitcoin")){ this->updateStatus(line["fields"]["new_balance"].toString().split(" ")[0] + " BTC received, starting swap"); - this->setSwap(line["span"]["swap_id"].toString()); + QVariant var; + var.setValue(HistoryEntry {QDateTime::currentDateTime(),line["span"]["swap_id"].toString()}); + QVariantList past = conf()->get(Config::pendingSwap).toList(); + past.append(var); + conf()->set(Config::pendingSwap,past); fundDialog->close(); qDebug() << "Spawn atomic swap progress dialog"; this->show(); } else if ( QString confs = line["fields"]["seen_confirmations"].toString(); !confs.isEmpty()){ qDebug() << "Updating xmrconfs " + confs; this->updateXMRConf(confs.toInt()); - } else if (QString message = line["fields"]["message"].toString(); !QString::compare(message, "Bitcoin transaction status changed")){ + } else if (QString message = line["fields"]["message"].toString(); QString::compare(message, "Bitcoin transaction status changed")==0){ qDebug() << "Updating btconfs " + line["fields"]["new_status"].toString().split(" ")[2]; QString status = line["fields"]["new_status"].toString(); bool ok; @@ -68,9 +70,31 @@ void AtomicSwap::runSwap(QStringList arguments){ } else { this->updateStatus("Found txid " + line["fields"]["txid"].toString() + " in mempool"); } - + } else if (QString message = line["fields"]["message"].toString(); message.startsWith("Swap completed")){ + QVariantList past = conf()->get(Config::pendingSwap).toList(); + past.removeLast(); + conf()->set(Config::pendingSwap, past); + this->updateStatus("Swap has successfully completed you can close this window now"); + } else if (QString message = line["fields"]["message"].toString(); QString::compare(message,"Advancing state")==0){ + this->updateStatus("State of swap has advanced to " + line["fields"]["state"].toString()); + } else if (QString refund = line["fields"]["kind"].toString(); QString::compare(refund,"refund")==0){ + QString txid = line["fields"]["txid"].toString(); + QString id = line["span"]["swap_id"].toString(); + QVariantList past = conf()->get(Config::pendingSwap).toList(); + for(int i=0;i().id,id)==0) { + past.remove(i); + break; + } + } + conf()->set(Config::pendingSwap, past); + QMessageBox::information(this,"Cancel and Refund","Swap refunded succesfully with txid " + txid); + } else if (QString message = line["fields"]["message"].toString(); QString::compare(message, "API call resulted in an error")==0){ + QString err = line["fields"]["err"].toString().split("\n")[0].split(":")[1]; + QMessageBox::warning(this, "Cancel and Refund", "Time lock hasn't expired yet so cancel failed. Try again in " + err + "blocks"); + } else if (QString message = line["fields"]["latest_version"].toString(); !message.isEmpty()){ + conf()->set(Config::swapVersion,message); } - //Insert line conditionals here } }); @@ -82,18 +106,8 @@ AtomicSwap::~AtomicSwap() { for (const auto& proc : *procList){ proc->kill(); } - 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"}); - (new QProcess)->start("kill", QStringList{"-f", Config::defaultConfigDir().absolutePath() + - "/testnet/monero/monero-wallet-rpc"}); - } - } void AtomicSwap::logLine(QString line){ - //ui->debug_log->setText(ui->debug_log->toPlainText().append(QTime::currentTime().toString() + ":" + line)); - this->update(); } void AtomicSwap::updateStatus(QString status){ @@ -117,9 +131,6 @@ void AtomicSwap::setTitle(QString title) { this->update(); } -void AtomicSwap::setSwap(QString swapId){ - id = std::move(swapId); -} void AtomicSwap::cancel(){ diff --git a/src/plugins/atomic/AtomicSwap.h b/src/plugins/atomic/AtomicSwap.h index 3cb7d56..f4e2f10 100644 --- a/src/plugins/atomic/AtomicSwap.h +++ b/src/plugins/atomic/AtomicSwap.h @@ -27,7 +27,6 @@ public: void updateBTCConf(int confs); void updateXMRConf(int confs); void setTitle(QString title); - void setSwap(QString swapId); public slots: void runSwap(QStringList swap); signals: diff --git a/src/plugins/atomic/AtomicWidget.cpp b/src/plugins/atomic/AtomicWidget.cpp index a31d5fc..416b296 100644 --- a/src/plugins/atomic/AtomicWidget.cpp +++ b/src/plugins/atomic/AtomicWidget.cpp @@ -61,19 +61,45 @@ AtomicWidget::AtomicWidget(QWidget *parent) connect(ui->btn_swap, &QPushButton::clicked, this, [this]{ auto rows = ui->offerBookTable->selectionModel()->selectedRows(); clean(); - // UNCOMENT after testing - //if (rows.size() < 1){ - // ui->meta_label->setText("You must select an offer to use for swap, refresh if there aren't any"); - //} else { - //QModelIndex index = rows.at(0); - //QString seller = index.sibling(index.row(), 3).data().toString(); - QString seller = "test"; + if (rows.size() < 1){ + ui->meta_label->setText("You must select an offer to use for swap, refresh if there aren't any"); + } else { + QModelIndex index = rows.at(0); + QString seller = index.sibling(index.row(), 3).data().toString(); //Add proper error checking on ui input after rest of swap is implemented QString btcChange = ui->change_address->text(); + QRegularExpression btcMain("^(bc1)[a-zA-HJ-NP-Z0-9]{39}$"); + QRegularExpression btcTest("^(tb1)[a-zA-HJ-NP-Z0-9]{39}$"); QString xmrReceive = ui->xmr_address->text(); + if(xmrReceive.isEmpty()) { + QMessageBox::warning(this, "Warning", "XMR receive address is required to start swap"); + return; + } + QRegularExpression xmrMain("^[48][0-9AB][1-9A-HJ-NP-Za-km-z]{93}"); + QRegularExpression xmrStage("^[57][0-9AB][1-9A-HJ-NP-Za-km-z]{93}"); + if (constants::networkType==NetworkType::STAGENET){ + if(!btcChange.isEmpty() && !btcTest.match(btcChange).hasMatch()){ + QMessageBox::warning(this, "Warning","BTC change address is wrong, not a bech32 segwit address, or on wrong network"); + return; + } + if(!xmrStage.match(xmrReceive).hasMatch()){ + QMessageBox::warning(this, "Warning","XMR receive address is improperly formated or on wrong network"); + return; + } + } else { + if(!btcChange.isEmpty() && !btcMain.match(btcChange).hasMatch()){ + QMessageBox::warning(this, "Warning","BTC change address is wrong, not a bech32 segwit address,or on wrong network"); + return; + } + if(!xmrMain.match(xmrReceive).hasMatch()){ + QMessageBox::warning(this, "Warning","XMR receive address is improperly formated or on wrong network"); + return; + } + } + sleep(1); runSwap(seller,btcChange, xmrReceive); - //} + } }); connect(ui->btn_addRendezvous, &QPushButton::clicked, this, [this]{ @@ -89,11 +115,6 @@ AtomicWidget::AtomicWidget(QWidget *parent) } }); - - //Remove after testing - 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(); @@ -124,18 +145,10 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons arguments << "-j"; arguments << "buy-xmr"; arguments << "--change-address"; - arguments << "tb1qzndh6u8qgl2ee4k4gl9erg947g67hyx03vvgen"; - //arguments << btcChange; + arguments << btcChange; arguments << "--receive-address"; - arguments << "78YnzFTp3UUMgtKuAJCP2STcbxRZPDPveJ5YGgfg5doiPahS9suWF1r3JhKqjM1McYBJvu8nhkXExGfXVkU6n5S6AXrg4KP"; - //arguments << xmrReceive; - arguments << "--seller"; - arguments << "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooW9yDFYojXnZRdqS9UXcfP2amgwoYdSjujwWdRw4LTSdWw"; - // Remove after testing - arguments << "--electrum-rpc"; - arguments << "tcp://127.0.0.1:50001"; - arguments << "--bitcoin-target-block"; - arguments << "1"; + arguments << xmrReceive; + auto nodes = conf()->get(Config::nodes).toJsonObject(); if (nodes.isEmpty()) { auto jsonData = conf()->get(Config::nodes).toByteArray(); @@ -144,12 +157,10 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons nodes = doc.object(); } } - qDebug() << nodes.value("0").toObject()["ws"].toArray()[0]; arguments << "--monero-daemon-address"; - //arguments << "node.monerodevs.org:38089"; arguments << nodes.value("0").toObject()["ws"].toArray()[0].toString(); - // Uncomment after testing - //arguments << seller; + arguments << "--seller"; + arguments << seller; if(conf()->get(Config::proxy).toInt() != Config::Proxy::None) { arguments << "--tor-socks5-port"; arguments << conf()->get(Config::socks5Port).toString(); @@ -176,23 +187,16 @@ void AtomicWidget::list(const QString& rendezvous) { auto *swap = new QProcess(); procList->append(QSharedPointer(swap)); swap->setReadChannel(QProcess::StandardError); - //swap->start(conf()->get(Config::swapPath).toString(), arguments); connect(swap, &QProcess::finished, this, [this, swap]{ QJsonDocument parsedLine; QJsonParseError parseError; QList> list; - qDebug() << "Subprocess has finished"; auto output = QString::fromLocal8Bit(swap->readAllStandardError()); - qDebug() << "Crashes before splitting"; auto lines = output.split(QRegularExpression("[\r\n]"),Qt::SkipEmptyParts); - qDebug() << lines.size(); - qDebug() << "parsing Output"; for(const auto& line : lines){ - qDebug() << line; if(line.contains("status")){ - qDebug() << "status contained"; parsedLine = QJsonDocument::fromJson(line.toLocal8Bit(), &parseError ); if (parsedLine["fields"]["status"].toString().contains("Online")){ bool skip = false; @@ -205,17 +209,14 @@ void AtomicWidget::list(const QString& rendezvous) { ui->meta_label->setText("Updated offer book"); offerList->append(QSharedPointer(entry)); } - qDebug() << entry; } } } - qDebug() << "exits fine"; swap->close(); o_model->updateOffers(*offerList); return list; }); swap->start(conf()->get(Config::swapPath).toString(), arguments); - //swap->waitForFinished(120000); @@ -234,13 +235,6 @@ void AtomicWidget::clean() { for (const auto& proc : *procList){ proc->kill(); } - 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"}); - (new QProcess)->start("kill", QStringList{"-f", Config::defaultConfigDir().absolutePath() + - "/testnet/monero/monero-wallet-rpc"}); - } } diff --git a/src/plugins/atomic/OfferModel.cpp b/src/plugins/atomic/OfferModel.cpp index e4092c8..013a080 100644 --- a/src/plugins/atomic/OfferModel.cpp +++ b/src/plugins/atomic/OfferModel.cpp @@ -21,7 +21,6 @@ void OfferModel::clear() { void OfferModel::updateOffers(const QList> &posts) { beginResetModel(); - qDebug() << "updating Offers"; m_offers.clear(); for (const auto& post : posts) { m_offers.push_back(post); diff --git a/src/utils/config.cpp b/src/utils/config.cpp index 47e7b99..7eef841 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -150,6 +150,7 @@ static const QHash configStrings = { {Config::swapPath, {QS("swapPath"), ""}}, {Config::operatingSystem, {QS("operatingSystem"), OS}}, {Config::pendingSwap, {QS("pendingSwap"), QVariantList{}}}, + {Config::swapVersion, {QS("swapVersion"), "0.13.4"}}, }; diff --git a/src/utils/config.h b/src/utils/config.h index 0aab639..d7c91ee 100644 --- a/src/utils/config.h +++ b/src/utils/config.h @@ -156,6 +156,7 @@ public: swapPath, operatingSystem, pendingSwap, + swapVersion, }; enum PrivacyLevel {