Coins: Sweep selected

This commit is contained in:
tobtoht 2021-06-28 18:05:21 +02:00
parent cfa96e8126
commit 04b2f5f9a0
No known key found for this signature in database
GPG key ID: 1CADD27F41F45C3C
9 changed files with 88 additions and 7 deletions

View file

@ -121,6 +121,17 @@ void AppContext::onSweepOutput(const QString &keyImage, QString address, bool ch
emit initiateTransaction(); emit initiateTransaction();
} }
void AppContext::onSweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs) {
if (churn) {
address = this->wallet->address(0, 0);
}
qInfo() << "Creating transaction";
this->wallet->createTransactionSelectedAsync(keyImages, address, outputs, this->tx_priority);
emit initiateTransaction();
}
void AppContext::onCreateTransactionError(const QString &msg) { void AppContext::onCreateTransactionError(const QString &msg) {
this->tmpTxDescription = ""; this->tmpTxDescription = "";
emit endTransaction(); emit endTransaction();

View file

@ -51,6 +51,7 @@ public slots:
void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description); void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address); void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address);
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs); void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs);
void onSweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs);
void onCreateTransactionError(const QString &msg); void onCreateTransactionError(const QString &msg);
void onOpenAliasResolve(const QString &openAlias); void onOpenAliasResolve(const QString &openAlias);
void onSetRestoreHeight(quint64 height); void onSetRestoreHeight(quint64 height);

View file

@ -47,10 +47,12 @@ CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
m_viewOutputAction = new QAction(icons()->icon("info2.svg"), "Details", this); m_viewOutputAction = new QAction(icons()->icon("info2.svg"), "Details", this);
m_sweepOutputAction = new QAction("Sweep output", this); m_sweepOutputAction = new QAction("Sweep output", this);
m_sweepOutputsAction = new QAction("Sweep selected outputs", this);
connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput); connect(m_freezeOutputAction, &QAction::triggered, this, &CoinsWidget::freezeOutput);
connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput); connect(m_thawOutputAction, &QAction::triggered, this, &CoinsWidget::thawOutput);
connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput); connect(m_viewOutputAction, &QAction::triggered, this, &CoinsWidget::viewOutput);
connect(m_sweepOutputAction, &QAction::triggered, this, &CoinsWidget::onSweepOutput); connect(m_sweepOutputAction, &QAction::triggered, this, &CoinsWidget::onSweepOutput);
connect(m_sweepOutputsAction, &QAction::triggered, this, &CoinsWidget::onSweepMulti);
connect(m_freezeAllSelectedAction, &QAction::triggered, this, &CoinsWidget::freezeAllSelected); connect(m_freezeAllSelectedAction, &QAction::triggered, this, &CoinsWidget::freezeAllSelected);
connect(m_thawAllSelectedAction, &QAction::triggered, this, &CoinsWidget::thawAllSelected); connect(m_thawAllSelectedAction, &QAction::triggered, this, &CoinsWidget::thawAllSelected);
@ -88,6 +90,7 @@ void CoinsWidget::showContextMenu(const QPoint &point) {
if (list.size() > 1) { if (list.size() > 1) {
menu->addAction(m_freezeAllSelectedAction); menu->addAction(m_freezeAllSelectedAction);
menu->addAction(m_thawAllSelectedAction); menu->addAction(m_thawAllSelectedAction);
menu->addAction(m_sweepOutputsAction);
} }
else { else {
CoinsInfo* c = this->currentEntry(); CoinsInfo* c = this->currentEntry();
@ -178,7 +181,7 @@ void CoinsWidget::onSweepOutput() {
return; return;
} }
auto *dialog = new OutputSweepDialog(this, c); auto *dialog = new OutputSweepDialog(this, c->amount());
int ret = dialog->exec(); int ret = dialog->exec();
if (!ret) return; if (!ret) return;
@ -186,6 +189,30 @@ void CoinsWidget::onSweepOutput() {
dialog->deleteLater(); dialog->deleteLater();
} }
void CoinsWidget::onSweepMulti() {
QVector<CoinsInfo*> selectedCoins = this->currentEntries();
QVector<QString> keyImages;
quint64 totalAmount = 0;
for (const auto coin : selectedCoins) {
if (!coin) return;
QString keyImage = coin->keyImage();
if (!coin->keyImageKnown()) {
QMessageBox::warning(this, "Unable to sweep output", "Unable to sweep output: key image unknown");
return;
}
keyImages.push_back(keyImage);
totalAmount += coin->amount();
}
OutputSweepDialog dialog{this, totalAmount};
int ret = dialog.exec();
if (!ret) return;
m_ctx->onSweepOutputs(keyImages, dialog.address(), dialog.churn(), dialog.outputs());
}
void CoinsWidget::copy(copyField field) { void CoinsWidget::copy(copyField field) {
CoinsInfo* c = this->currentEntry(); CoinsInfo* c = this->currentEntry();
if (!c) return; if (!c) return;
@ -227,6 +254,15 @@ CoinsInfo* CoinsWidget::currentEntry() {
} }
} }
QVector<CoinsInfo*> CoinsWidget::currentEntries() {
QModelIndexList list = ui->coins->selectionModel()->selectedRows();
QVector<CoinsInfo*> selectedCoins;
for (const auto index : list) {
selectedCoins.push_back(m_model->entryFromIndex(m_proxyModel->mapToSource(index)));
}
return selectedCoins;
}
void CoinsWidget::freezeCoins(const QVector<int>& indexes) { void CoinsWidget::freezeCoins(const QVector<int>& indexes) {
for (int i : indexes) { for (int i : indexes) {
m_ctx->wallet->coins()->freeze(i); m_ctx->wallet->coins()->freeze(i);

View file

@ -35,6 +35,7 @@ private slots:
void thawAllSelected(); void thawAllSelected();
void viewOutput(); void viewOutput();
void onSweepOutput(); void onSweepOutput();
void onSweepMulti();
private: private:
void freezeCoins(const QVector<int>& indexes); void freezeCoins(const QVector<int>& indexes);
@ -63,6 +64,7 @@ private:
QAction *m_thawAllSelectedAction; QAction *m_thawAllSelectedAction;
QAction *m_viewOutputAction; QAction *m_viewOutputAction;
QAction *m_sweepOutputAction; QAction *m_sweepOutputAction;
QAction *m_sweepOutputsAction;
Coins *m_coins; Coins *m_coins;
CoinsModel * m_model; CoinsModel * m_model;
CoinsProxyModel * m_proxyModel; CoinsProxyModel * m_proxyModel;
@ -70,6 +72,7 @@ private:
void showContextMenu(const QPoint & point); void showContextMenu(const QPoint & point);
void copy(copyField field); void copy(copyField field);
CoinsInfo* currentEntry(); CoinsInfo* currentEntry();
QVector<CoinsInfo*> currentEntries();
}; };

View file

@ -6,14 +6,13 @@
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
OutputSweepDialog::OutputSweepDialog(QWidget *parent, CoinsInfo *coin) OutputSweepDialog::OutputSweepDialog(QWidget *parent, quint64 amount)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::OutputSweepDialog) , ui(new Ui::OutputSweepDialog)
, m_amount(amount)
{ {
ui->setupUi(this); ui->setupUi(this);
m_amount = coin->amount();
connect(ui->checkBox_churn, &QCheckBox::toggled, [&](bool toggled){ connect(ui->checkBox_churn, &QCheckBox::toggled, [&](bool toggled){
ui->lineEdit_address->setEnabled(!toggled); ui->lineEdit_address->setEnabled(!toggled);
ui->lineEdit_address->setText(toggled ? "Primary address" : ""); ui->lineEdit_address->setText(toggled ? "Primary address" : "");

View file

@ -17,7 +17,7 @@ class OutputSweepDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit OutputSweepDialog(QWidget *parent, CoinsInfo *coin); explicit OutputSweepDialog(QWidget *parent, quint64 amount);
~OutputSweepDialog() override; ~OutputSweepDialog() override;
QString address(); QString address();

View file

@ -723,6 +723,29 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
}); });
} }
PendingTransaction *Wallet::createTransactionSelected(const QVector<QString> &key_images, const QString &dst_addr,
size_t outputs, PendingTransaction::Priority priority)
{
std::vector<std::string> kis;
for (const auto &key_image : key_images) {
kis.push_back(key_image.toStdString());
}
Monero::PendingTransaction *ptImpl = m_walletImpl->createTransactionSelected(kis, dst_addr.toStdString(), outputs, static_cast<Monero::PendingTransaction::Priority>(priority));
PendingTransaction *result = new PendingTransaction(ptImpl, this);
return result;
}
void Wallet::createTransactionSelectedAsync(const QVector<QString> &key_images, const QString &dst_addr,
size_t outputs, PendingTransaction::Priority priority)
{
m_scheduler.run([this, key_images, dst_addr, outputs, priority] {
PendingTransaction *tx = createTransactionSelected(key_images, dst_addr, outputs, priority);
QVector<QString> address {dst_addr};
emit transactionCreated(tx, address);
});
}
PendingTransaction *Wallet::createSweepUnmixableTransaction() PendingTransaction *Wallet::createSweepUnmixableTransaction()
{ {
// pauseRefresh(); // pauseRefresh();

View file

@ -298,6 +298,14 @@ public:
void createTransactionSingleAsync(const QString &key_image, const QString &dst_addr, void createTransactionSingleAsync(const QString &key_image, const QString &dst_addr,
size_t outputs, PendingTransaction::Priority priority); size_t outputs, PendingTransaction::Priority priority);
//! creates transaction with selected inputs
PendingTransaction * createTransactionSelected(const QVector<QString> &key_images, const QString &dst_addr,
size_t outputs, PendingTransaction::Priority priority);
//! creates async transaction with selected inputs
void createTransactionSelectedAsync(const QVector<QString> &key_images, const QString &dst_addr,
size_t outputs, PendingTransaction::Priority priority);
//! creates sweep unmixable transaction //! creates sweep unmixable transaction
PendingTransaction * createSweepUnmixableTransaction(); PendingTransaction * createSweepUnmixableTransaction();

View file

@ -809,13 +809,13 @@
<customwidget> <customwidget>
<class>CCSWidget</class> <class>CCSWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>widgets/ccswidget.h</header> <header>widgets/CCSWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>RedditWidget</class> <class>RedditWidget</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>widgets/redditwidget.h</header> <header>widgets/RedditWidget.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
</customwidgets> </customwidgets>