mirror of
https://github.com/feather-wallet/feather.git
synced 2025-03-12 09:37:47 +00:00
DONE:
1. Connect signals to make status of swap reflected in AtomicSwap dialog 2. Add informational tabs to AtomicSwap dialog TODO: 3. Add cancel and refund functionality to AtomicSwap when things go wrong, possibly add automatic cancel functionality 4. Add History and recovery to atomic window
This commit is contained in:
parent
8744138b42
commit
08328d96f4
9 changed files with 180 additions and 154 deletions
|
@ -41,6 +41,7 @@
|
|||
<file>assets/images/file_manager_32px.png</file>
|
||||
<file>assets/images/gnome-calc.png</file>
|
||||
<file>assets/images/atomic-icon.png</file>
|
||||
<file>assets/images/hint-icon.png</file>
|
||||
<file>assets/images/hd_32px.png</file>
|
||||
<file>assets/images/history.png</file>
|
||||
<file>assets/images/i2p.png</file>
|
||||
|
|
BIN
src/assets/images/hint-icon.png
Normal file
BIN
src/assets/images/hint-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
|
@ -8,20 +8,21 @@
|
|||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
AtomicFundDialog::AtomicFundDialog(QWidget *parent, QrCode *qrCode, const QString &title, const QString &btc_address)
|
||||
AtomicFundDialog::AtomicFundDialog(QWidget *parent, const QString &title, const QString &btc_address)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::AtomicFundDialog)
|
||||
, address(btc_address)
|
||||
, qrCode(address, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->setWindowTitle(title);
|
||||
ui->qrWidget->setQrCode(qrCode);
|
||||
m_pixmap = qrCode->toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
|
||||
|
||||
ui->qrWidget->setQrCode(&qrCode);
|
||||
m_pixmap = qrCode.toPixmap(1).scaled(500, 500, Qt::KeepAspectRatio);
|
||||
connect(ui->btn_CopyAddress, &QPushButton::clicked, this, &AtomicFundDialog::copyAddress);
|
||||
connect(ui->btn_CopyImage, &QPushButton::clicked, this, &AtomicFundDialog::copyImage);
|
||||
connect(ui->btn_Save, &QPushButton::clicked, this, &AtomicFundDialog::saveImage);
|
||||
connect(ui->btn_Close, &QPushButton::clicked, [this](){
|
||||
emit cleanProcs();
|
||||
accept();
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class AtomicFundDialog : public WindowModalDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AtomicFundDialog(QWidget *parent, QrCode *qrCode, const QString &title = "Qr Code", const QString &btc_address = "Error Restart swap");
|
||||
explicit AtomicFundDialog(QWidget *parent, const QString &title = "Qr Code", const QString &btc_address = "Error Restart swap");
|
||||
~AtomicFundDialog() override;
|
||||
signals:
|
||||
void cleanProcs();
|
||||
|
@ -31,6 +31,7 @@ private:
|
|||
QScopedPointer<Ui::AtomicFundDialog> ui;
|
||||
QPixmap m_pixmap;
|
||||
QString address;
|
||||
QrCode qrCode;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,111 +1,111 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AtomicFundDialog</class>
|
||||
<widget class="QDialog" name="AtomicFundDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>520</width>
|
||||
<height>446</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QrCodeWidget" name="qrWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_CopyAddress">
|
||||
<property name="text">
|
||||
<string>Copy Address</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_CopyImage">
|
||||
<property name="text">
|
||||
<string>Copy Image</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_Save">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_Close">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<class>AtomicFundDialog</class>
|
||||
<widget class="QDialog" name="AtomicFundDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>520</width>
|
||||
<height>446</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QrCodeWidget" name="qrWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QrCodeWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/QrCodeWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_CopyAddress">
|
||||
<property name="text">
|
||||
<string>Copy Address</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_CopyImage">
|
||||
<property name="text">
|
||||
<string>Copy Image</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_Save">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_Close">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QrCodeWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/QrCodeWidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -14,6 +14,11 @@ AtomicSwap::AtomicSwap(QWidget *parent) :
|
|||
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;
|
||||
pixmapTarget = pixmapTarget.scaled(size-5, size-5, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
ui->btc_hint->setPixmap(pixmapTarget);
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -95,6 +95,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="btc_hint">
|
||||
<property name="pixmap">
|
||||
<pixmap>hint-icon.png</pixmap>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::TextFormat::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_xmr">
|
||||
<property name="text">
|
||||
|
|
|
@ -23,6 +23,7 @@ AtomicWidget::AtomicWidget(QWidget *parent)
|
|||
, offerList(new QList<QSharedPointer<OfferEntry>>())
|
||||
, swapDialog(new AtomicSwap(this))
|
||||
, procList(new QList<QSharedPointer<QProcess>>())
|
||||
, fundDialog(new AtomicFundDialog(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -58,16 +59,20 @@ AtomicWidget::AtomicWidget(QWidget *parent)
|
|||
|
||||
connect(ui->btn_swap, &QPushButton::clicked, this, [this]{
|
||||
auto rows = ui->offerBookTable->selectionModel()->selectedRows();
|
||||
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();
|
||||
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";
|
||||
//Add proper error checking on ui input after rest of swap is implemented
|
||||
QString btcChange = ui->change_address->text();
|
||||
QString xmrReceive = ui->xmr_address->text();
|
||||
sleep(1);
|
||||
runSwap(seller,btcChange, xmrReceive);
|
||||
}
|
||||
//}
|
||||
});
|
||||
|
||||
connect(ui->btn_addRendezvous, &QPushButton::clicked, this, [this]{
|
||||
|
@ -84,7 +89,6 @@ AtomicWidget::AtomicWidget(QWidget *parent)
|
|||
});
|
||||
connect(swapDialog,&AtomicSwap::cleanProcs, this, [this]{clean();});
|
||||
|
||||
|
||||
this->updateStatus();
|
||||
}
|
||||
|
||||
|
@ -95,10 +99,7 @@ void AtomicWidget::skinChanged() {
|
|||
|
||||
void AtomicWidget::showAtomicConfigureDialog() {
|
||||
AtomicConfigDialog dialog{this};
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
|
||||
}
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
void AtomicWidget::showAtomicSwapDialog() {
|
||||
|
@ -115,57 +116,62 @@ void AtomicWidget::runSwap(const QString& seller, const QString& btcChange, cons
|
|||
arguments << "--data-base-dir";
|
||||
arguments << Config::defaultConfigDir().absolutePath();
|
||||
// Remove after testing
|
||||
//arguments << "--testnet";
|
||||
arguments << "--testnet";
|
||||
arguments << "--debug";
|
||||
arguments << "-j";
|
||||
arguments << "buy-xmr";
|
||||
arguments << "--change-address";
|
||||
//arguments << "tb1qzndh6u8qgl2ee4k4gl9erg947g67hyx03vvgen";
|
||||
arguments << btcChange;
|
||||
arguments << "tb1qzndh6u8qgl2ee4k4gl9erg947g67hyx03vvgen";
|
||||
//arguments << btcChange;
|
||||
arguments << "--receive-address";
|
||||
//arguments << "78YnzFTp3UUMgtKuAJCP2STcbxRZPDPveJ5YGgfg5doiPahS9suWF1r3JhKqjM1McYBJvu8nhkXExGfXVkU6n5S6AXrg4KP";
|
||||
arguments << xmrReceive;
|
||||
arguments << "78YnzFTp3UUMgtKuAJCP2STcbxRZPDPveJ5YGgfg5doiPahS9suWF1r3JhKqjM1McYBJvu8nhkXExGfXVkU6n5S6AXrg4KP";
|
||||
//arguments << xmrReceive;
|
||||
arguments << "--seller";
|
||||
//arguments << "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWQA4fXDYLNXgxPsVZmnR8kh2wwHUQnkH9e1Wjc8KyJ7p8";
|
||||
arguments << "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWQA4fXDYLNXgxPsVZmnR8kh2wwHUQnkH9e1Wjc8KyJ7p8";
|
||||
// Remove after testing
|
||||
//arguments << "--electrum-rpc";
|
||||
//arguments << "tcp://127.0.0.1:50001";
|
||||
//arguments << "--bitcoin-target-block";
|
||||
//arguments << "8";
|
||||
//arguments << "--monero-daemon-address";
|
||||
//arguments << "http://127.0.0.1:38083";
|
||||
arguments << "--electrum-rpc";
|
||||
arguments << "tcp://127.0.0.1:50001";
|
||||
arguments << "--bitcoin-target-block";
|
||||
arguments << "1";
|
||||
arguments << "--monero-daemon-address";
|
||||
arguments << "node.monerodevs.org:38089";
|
||||
// Uncomment after testing
|
||||
arguments << seller;
|
||||
//arguments << seller;
|
||||
arguments << "--tor-socks5-port";
|
||||
arguments << m_instance->get(Config::socks5Port).toString();
|
||||
|
||||
|
||||
auto *swap = new QProcess();
|
||||
procList->append(QSharedPointer<QProcess>(swap));
|
||||
|
||||
swap->setReadChannel(QProcess::StandardError);
|
||||
connect(swap, &QProcess::readyReadStandardError,this, [this, swap] {
|
||||
swap->setProcessChannelMode(QProcess::MergedChannels);
|
||||
swap->setReadChannel(QProcess::StandardOutput);
|
||||
connect(swap, &QProcess::readyRead,this, [this, swap] {
|
||||
while(swap->canReadLine()){
|
||||
QJsonParseError err;
|
||||
const QByteArray& rawline = swap->readLine();
|
||||
QJsonDocument line = QJsonDocument::fromJson(rawline, &err);
|
||||
qDebug() << rawline;
|
||||
bool check;
|
||||
if (line["fields"]["message"].toString().contains("Connected to Alice")){
|
||||
qDebug() << "Successfully connected";
|
||||
swapDialog->logLine(line["fields"].toString());
|
||||
} else if (!line["fields"]["deposit_address"].toString().isEmpty()){
|
||||
qDebug() << "Deposit to btc to segwit address";
|
||||
QString address = line["fields"]["deposit_address"].toString();
|
||||
QrCode qrc(address, QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
|
||||
AtomicFundDialog dialog(qobject_cast<QWidget*>(parent()), &qrc, "Deposit BTC to this address", address);
|
||||
connect(&dialog,&AtomicFundDialog::cleanProcs, this, [this]{clean();});
|
||||
connect(this, &AtomicWidget::receivedBTC,&dialog, [ &dialog]{
|
||||
disconnect(&dialog, SIGNAL(cleanProcs()), nullptr, nullptr);
|
||||
dialog.close();});
|
||||
dialog.exec();
|
||||
fundDialog = new AtomicFundDialog(this, "Deposit BTC to this address", address);
|
||||
//dialog->setModal(true);
|
||||
fundDialog->show();
|
||||
} else if (line["fields"]["message"].toString().startsWith("Received Bitcoin")){
|
||||
emit receivedBTC(line["fields"]["new_balance"].toString().split(" ")[0].toFloat());
|
||||
swapDialog->updateStatus(line["fields"]["new_balance"].toString().split(" ")[0] + " BTC received, starting swap");
|
||||
fundDialog->close();
|
||||
qDebug() << "Spawn atomic swap progress dialog";
|
||||
showAtomicSwapDialog();
|
||||
} else if ( QString confs = line["fields"]["seen_confirmations"].toString(); !confs.isEmpty()){
|
||||
qDebug() << "Updating xmrconfs " + confs;
|
||||
swapDialog->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];
|
||||
swapDialog->updateBTCConf(line["fields"]["new_status"].toString().split(" ")[2].toInt());
|
||||
}
|
||||
//Insert line conditionals here
|
||||
}
|
||||
|
@ -245,15 +251,16 @@ AtomicWidget::~AtomicWidget() {
|
|||
|
||||
void AtomicWidget::clean() {
|
||||
for (const auto& proc : *procList){
|
||||
if(!proc->atEnd())
|
||||
proc->terminate();
|
||||
proc->kill();
|
||||
}
|
||||
if(QString::compare("WINDOWS",m_instance->get(Config::operatingSystem).toString()) != 0) {
|
||||
qDebug() << "Closing monero-wallet-rpc";
|
||||
(new QProcess)->start("pkill", QStringList{"-f", Config::defaultConfigDir().absolutePath() +
|
||||
(new QProcess)->start("kill", QStringList{"-f", Config::defaultConfigDir().absolutePath() +
|
||||
"/mainnet/monero/monero-wallet-rpc"});
|
||||
(new QProcess)->start("pkill", QStringList{"-f", Config::defaultConfigDir().absolutePath() +
|
||||
(new QProcess)->start("kill", QStringList{"-f", Config::defaultConfigDir().absolutePath() +
|
||||
"/testnet/monero/monero-wallet-rpc"});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "OfferModel.h"
|
||||
#include "AtomicSwap.h"
|
||||
#include "config.h"
|
||||
#include "AtomicFundDialog.h"
|
||||
|
||||
namespace Ui {
|
||||
class AtomicWidget;
|
||||
|
@ -34,8 +35,7 @@ public slots:
|
|||
private slots:
|
||||
void showAtomicConfigureDialog();
|
||||
void runSwap(const QString& seller, const QString& btcChange, const QString& xmrReceive);
|
||||
signals:
|
||||
void receivedBTC(float new_amount);
|
||||
|
||||
private:
|
||||
void updateStatus();
|
||||
|
||||
|
@ -45,6 +45,7 @@ private:
|
|||
OfferModel *o_model;
|
||||
QList<QSharedPointer<OfferEntry>> *offerList;
|
||||
AtomicSwap *swapDialog;
|
||||
AtomicFundDialog *fundDialog;
|
||||
|
||||
void showAtomicSwapDialog();
|
||||
|
||||
|
|
Loading…
Reference in a new issue