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
TODO:
     3. Add cancel and refund functionality to AtomicSwap when things go wrong
     4. Refactor AtomicWidget so AtomicSwap handles parsing of swap binary output.
This commit is contained in:
twiddle 2024-08-02 17:09:22 -04:00
parent 08328d96f4
commit 06c43a707e
12 changed files with 177 additions and 8 deletions

View file

@ -0,0 +1,59 @@
//
// Created by dev on 7/29/24.
//
// You may need to build the project (run Qt uic code generator) to get "ui_AtomicRecoverDialog.h" resolved
#include "AtomicRecoverDialog.h"
#include "ui_AtomicRecoverDialog.h"
#include "History.h"
#include "config.h"
#include <QStandardItemModel>
AtomicRecoverDialog::AtomicRecoverDialog(QWidget *parent) :
WindowModalDialog(parent), ui(new Ui::AtomicRecoverDialog) {
ui->setupUi(this);
auto model = new QStandardItemModel();
ui->swap_history->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->swap_history->setModel(model);
model->setHorizontalHeaderItem(0, new QStandardItem("Swap-Id"));
model->setHorizontalHeaderItem(1, new QStandardItem("Timestamp swap started"));
model->setHorizontalHeaderItem(2, new QStandardItem("Status"));
QList<QStandardItem*> rowData;
auto data = Config::instance()->get(Config::pendingSwap).value<QVariantList>();
for(int i=0; i< data.size(); i++){
auto entry = data[i].value<HistoryEntry>();
qint64 difference = entry.timestamp.secsTo(QDateTime::currentDateTime());
if (difference < 86400) {
rowData.clear();
rowData << new QStandardItem(entry.id);
rowData << new QStandardItem(entry.timestamp.toString("MM-dd-yyyy hh:mm"));
if (difference > 43200){
rowData << new QStandardItem("Refundable");
} else
rowData << new QStandardItem("Recoverable/Pending Refund Timelock");
model->appendRow(rowData);
} else {
data.remove(i);
}
}
Config::instance()->set(Config::pendingSwap,data);
}
bool AtomicRecoverDialog::historyEmpty(){
return Config::instance()->get(Config::pendingSwap).value<QVariantList>().isEmpty();
}
void AtomicRecoverDialog::appendHistory(HistoryEntry entry){
auto current = Config::instance()->get(Config::pendingSwap).value<QVariantList>();
auto var = QVariant();
var.setValue(entry);
current.append(var);
Config::instance()->set(Config::pendingSwap, current);
}
AtomicRecoverDialog::~AtomicRecoverDialog() {
delete ui;
}

View file

@ -0,0 +1,30 @@
//
// Created by dev on 7/29/24.
//
#ifndef FEATHER_ATOMICRECOVERDIALOG_H
#define FEATHER_ATOMICRECOVERDIALOG_H
#include <QDialog>
#include "components.h"
#include "History.h"
QT_BEGIN_NAMESPACE
namespace Ui { class AtomicRecoverDialog; }
QT_END_NAMESPACE
class AtomicRecoverDialog : public WindowModalDialog {
Q_OBJECT
public:
explicit AtomicRecoverDialog(QWidget *parent = nullptr);
bool historyEmpty();
void appendHistory(HistoryEntry entry);
~AtomicRecoverDialog() override;
private:
Ui::AtomicRecoverDialog *ui;
};
#endif //FEATHER_ATOMICRECOVERDIALOG_H

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AtomicRecoverDialog</class>
<widget class="QDialog" name="AtomicRecoverDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>903</width>
<height>248</height>
</rect>
</property>
<property name="windowTitle">
<string>AtomicRecoverDialog</string>
</property>
<widget class="QTableView" name="swap_history">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>881</width>
<height>179</height>
</rect>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -5,12 +5,14 @@
// You may need to build the project (run Qt uic code generator) to get "ui_AtomicSwap.h" resolved
#include "AtomicSwap.h"
#include <utility>
#include "ui_AtomicSwap.h"
#include "AtomicWidget.h"
AtomicSwap::AtomicSwap(QWidget *parent) :
WindowModalDialog(parent), ui(new Ui::AtomicSwap) {
WindowModalDialog(parent), ui(new Ui::AtomicSwap), fundDialog( new AtomicFundDialog(this)) {
ui->setupUi(this);
//ui->debug_log->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
ui->label_status->setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
@ -21,6 +23,7 @@ AtomicSwap::AtomicSwap(QWidget *parent) :
ui->btc_hint->setToolTip("Alice is expected to send monero lock after one btc confirmation,\nswap is cancelable after 72 btc confirmations,\nyou will lose your funds if you don't refund before 144 confirmations");
this->setContentsMargins(3,3,3,3);
this->adjustSize();
connect(ui->btn_cancel, &QPushButton::clicked, this, &AtomicSwap::cancel);
}
@ -44,6 +47,7 @@ void AtomicSwap::updateXMRConf(int confs) {
}
void AtomicSwap::updateBTCConf(int confs) {
btc_confs = confs;
ui->label_btc_cons->setText(QString::number(confs));
this->update();
}
@ -53,3 +57,10 @@ void AtomicSwap::setTitle(QString title) {
this->update();
}
void AtomicSwap::setSwap(QString swapId){
id = std::move(swapId);
}
void AtomicSwap::cancel(){
}

View file

@ -8,6 +8,7 @@
#include <QDialog>
#include <QTime>
#include "components.h"
#include "AtomicFundDialog.h"
QT_BEGIN_NAMESPACE
@ -25,11 +26,15 @@ public:
void updateBTCConf(int confs);
void updateXMRConf(int confs);
void setTitle(QString title);
void setSwap(QString swapId);
signals:
void cleanProcs();
private:
Ui::AtomicSwap *ui;
QString id;
AtomicFundDialog fundDialog;
int btc_confs;
void cancel();
};

View file

@ -37,7 +37,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="pushButton">
<widget class="QPushButton" name="btn_cancel">
<property name="text">
<string>Cancel </string>
</property>

View file

@ -24,6 +24,7 @@ AtomicWidget::AtomicWidget(QWidget *parent)
, swapDialog(new AtomicSwap(this))
, procList(new QList<QSharedPointer<QProcess>>())
, fundDialog(new AtomicFundDialog(this))
, recoverDialog(new AtomicRecoverDialog(this))
{
ui->setupUi(this);
@ -42,7 +43,7 @@ AtomicWidget::AtomicWidget(QWidget *parent)
ui->offerBookTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
ui->btn_configure->setEnabled(true);
if (!Config::instance()->get(Config::swapPath).toString().isEmpty())
if (!m_instance->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);
@ -82,13 +83,21 @@ AtomicWidget::AtomicWidget(QWidget *parent)
tr("p2p multi address of rendezvous point"), QLineEdit::Normal,
"", &ok);
if (ok && !text.isEmpty()) {
QStringList copy = Config::instance()->get(Config::rendezVous).toStringList();
QStringList copy = m_instance->get(Config::rendezVous).toStringList();
copy.append(text);
Config::instance()->set(Config::rendezVous,copy);
m_instance->set(Config::rendezVous,copy);
}
});
connect(swapDialog,&AtomicSwap::cleanProcs, this, [this]{clean();});
//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();
}
@ -99,7 +108,7 @@ void AtomicWidget::skinChanged() {
void AtomicWidget::showAtomicConfigureDialog() {
AtomicConfigDialog dialog{this};
dialog.show();
dialog.exec();
}
void AtomicWidget::showAtomicSwapDialog() {
@ -146,6 +155,7 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons
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();
@ -163,6 +173,7 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons
fundDialog->show();
} else if (line["fields"]["message"].toString().startsWith("Received Bitcoin")){
swapDialog->updateStatus(line["fields"]["new_balance"].toString().split(" ")[0] + " BTC received, starting swap");
swapDialog->setSwap(line["span"]["swap_id"].toString());
fundDialog->close();
qDebug() << "Spawn atomic swap progress dialog";
showAtomicSwapDialog();

View file

@ -14,6 +14,7 @@
#include "AtomicSwap.h"
#include "config.h"
#include "AtomicFundDialog.h"
#include "AtomicRecoverDialog.h"
namespace Ui {
class AtomicWidget;
@ -46,7 +47,7 @@ private:
QList<QSharedPointer<OfferEntry>> *offerList;
AtomicSwap *swapDialog;
AtomicFundDialog *fundDialog;
AtomicRecoverDialog *recoverDialog;
void showAtomicSwapDialog();
QList<QSharedPointer<QProcess>> *procList;

View file

@ -64,6 +64,9 @@
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>

View file

@ -0,0 +1,17 @@
//
// Created by dev on 7/29/24.
//
#ifndef FEATHER_HISTORY_H
#define FEATHER_HISTORY_H
#include <QString>
#include <QDateTime>
struct HistoryEntry {
QDateTime timestamp;
QString id;
};
Q_DECLARE_METATYPE(HistoryEntry);
#endif //FEATHER_HISTORY_H

View file

@ -149,6 +149,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
"/dns4/swap.sethforprivacy.com/tcp/8888/p2p/12D3KooWCULyZKuV9YEkb6BX8FuwajdvktSzmMg4U5ZX2uYZjHeu"}}},
{Config::swapPath, {QS("swapPath"), ""}},
{Config::operatingSystem, {QS("operatingSystem"), OS}},
{Config::pendingSwap, {QS("pendingSwap"), QVariantList{}}},
};

View file

@ -12,6 +12,7 @@
#include <QDir>
class Config : public QObject
{
Q_OBJECT
@ -154,6 +155,7 @@ public:
rendezVous,
swapPath,
operatingSystem,
pendingSwap,
};
enum PrivacyLevel {