mirror of
https://github.com/feather-wallet/feather.git
synced 2024-11-17 09:47:36 +00:00
Multi destination transactions
This commit is contained in:
parent
9fc77f3bc9
commit
045d9ec2d2
18 changed files with 411 additions and 45 deletions
|
@ -178,7 +178,7 @@ void AppContext::initWS() {
|
||||||
this->ws->start();
|
this->ws->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppContext::onCancelTransaction(PendingTransaction *tx, const QString &address) {
|
void AppContext::onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address) {
|
||||||
// tx cancelled by user
|
// tx cancelled by user
|
||||||
double amount = tx->amount() / globals::cdiv;
|
double amount = tx->amount() / globals::cdiv;
|
||||||
emit createTransactionCancelled(address, amount);
|
emit createTransactionCancelled(address, amount);
|
||||||
|
@ -239,6 +239,30 @@ void AppContext::onCreateTransaction(const QString &address, quint64 amount, con
|
||||||
emit initiateTransaction();
|
emit initiateTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppContext::onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description) {
|
||||||
|
this->tmpTxDescription = description;
|
||||||
|
|
||||||
|
if (this->currentWallet == nullptr) {
|
||||||
|
emit createTransactionError("Cannot create transaction; no wallet loaded");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 total_amount = 0;
|
||||||
|
for (auto &amount : amounts) {
|
||||||
|
total_amount += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto unlocked_balance = this->currentWallet->unlockedBalance();
|
||||||
|
if (total_amount > unlocked_balance) {
|
||||||
|
emit createTransactionError("Not enough money to spend");
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Creating tx";
|
||||||
|
this->currentWallet->createTransactionMultiDestAsync(addresses, amounts, 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();
|
||||||
|
@ -750,15 +774,18 @@ void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppContext::onTransactionCreated(PendingTransaction *tx, const QString &address, const QString &paymentId, quint32 mixin) {
|
void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address) {
|
||||||
if(address == this->donationAddress)
|
for (auto &addr : address) {
|
||||||
this->donationSending = true;
|
if (addr == this->donationAddress) {
|
||||||
|
this->donationSending = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Let UI know that the transaction was constructed
|
// Let UI know that the transaction was constructed
|
||||||
emit endTransaction();
|
emit endTransaction();
|
||||||
|
|
||||||
// tx created, but not sent yet. ask user to verify first.
|
// tx created, but not sent yet. ask user to verify first.
|
||||||
emit createTransactionSuccess(tx, address, mixin);
|
emit createTransactionSuccess(tx, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
|
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
|
||||||
|
|
|
@ -115,7 +115,8 @@ public slots:
|
||||||
void onOpenWallet(const QString& path, const QString &password);
|
void onOpenWallet(const QString& path, const QString &password);
|
||||||
void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all);
|
void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all);
|
||||||
void onCreateTransaction(XmrToOrder *order);
|
void onCreateTransaction(XmrToOrder *order);
|
||||||
void onCancelTransaction(PendingTransaction *tx, const QString &address);
|
void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
|
||||||
|
void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address);
|
||||||
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) const;
|
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) const;
|
||||||
void onCreateTransactionError(const QString &msg);
|
void onCreateTransactionError(const QString &msg);
|
||||||
void onOpenAliasResolve(const QString &openAlias);
|
void onOpenAliasResolve(const QString &openAlias);
|
||||||
|
@ -136,7 +137,7 @@ private slots:
|
||||||
void onWalletOpened(Wallet *wallet);
|
void onWalletOpened(Wallet *wallet);
|
||||||
void onWalletNewBlock(quint64 blockheight, quint64 targetHeight);
|
void onWalletNewBlock(quint64 blockheight, quint64 targetHeight);
|
||||||
void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight);
|
void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight);
|
||||||
void onTransactionCreated(PendingTransaction *tx, const QString &address, const QString &paymentId, quint32 mixin);
|
void onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address);
|
||||||
void onTransactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
|
void onTransactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -159,8 +160,8 @@ signals:
|
||||||
void walletOpenPasswordNeeded(bool invalidPassword, QString path);
|
void walletOpenPasswordNeeded(bool invalidPassword, QString path);
|
||||||
void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
|
void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
|
||||||
void createTransactionError(QString message);
|
void createTransactionError(QString message);
|
||||||
void createTransactionCancelled(QString address, double amount);
|
void createTransactionCancelled(const QVector<QString> &address, double amount);
|
||||||
void createTransactionSuccess(PendingTransaction *tx, const QString &address, const quint32 &mixin);
|
void createTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address);
|
||||||
void redditUpdated(QList<QSharedPointer<RedditPost>> &posts);
|
void redditUpdated(QList<QSharedPointer<RedditPost>> &posts);
|
||||||
void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes);
|
void nodesUpdated(QList<QSharedPointer<FeatherNode>> &nodes);
|
||||||
void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries);
|
void ccsUpdated(QList<QSharedPointer<CCSEntry>> &entries);
|
||||||
|
|
|
@ -185,17 +185,11 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTextEdit" name="outputs">
|
<widget class="QTextEdit" name="outputs">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>100</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -9,14 +9,13 @@
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent)
|
TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
, ui(new Ui::TxConfDialog)
|
, ui(new Ui::TxConfDialog)
|
||||||
, m_ctx(ctx)
|
, m_ctx(ctx)
|
||||||
, m_tx(tx)
|
, m_tx(tx)
|
||||||
, m_address(address)
|
, m_address(address)
|
||||||
, m_description(description)
|
, m_description(description)
|
||||||
, m_mixin(mixin)
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ class TxConfDialog : public QDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, int mixin, QWidget *parent = nullptr);
|
explicit TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QString &address, const QString &description, QWidget *parent = nullptr);
|
||||||
~TxConfDialog() override;
|
~TxConfDialog() override;
|
||||||
|
|
||||||
bool showAdvanced = false;
|
bool showAdvanced = false;
|
||||||
|
@ -31,7 +31,6 @@ private:
|
||||||
PendingTransaction *m_tx;
|
PendingTransaction *m_tx;
|
||||||
QString m_address;
|
QString m_address;
|
||||||
QString m_description;
|
QString m_description;
|
||||||
int m_mixin;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FEATHER_TXCONFDIALOG_H
|
#endif //FEATHER_TXCONFDIALOG_H
|
||||||
|
|
|
@ -591,7 +591,40 @@ void Wallet::createTransactionAsync(const QString &dst_addr, const QString &paym
|
||||||
{
|
{
|
||||||
m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
|
m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
|
||||||
PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
|
PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
|
||||||
emit transactionCreated(tx, dst_addr, payment_id, mixin_count);
|
QVector<QString> address {dst_addr};
|
||||||
|
emit transactionCreated(tx, address);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
PendingTransaction* Wallet::createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||||
|
PendingTransaction::Priority priority)
|
||||||
|
{
|
||||||
|
std::vector<std::string> dests;
|
||||||
|
for (auto &addr : dst_addr) {
|
||||||
|
dests.push_back(addr.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint64_t> amounts;
|
||||||
|
for (auto &a : amount) {
|
||||||
|
amounts.push_back(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: remove mixin count
|
||||||
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionMultDest(dests, "", amounts, 11, static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||||
|
PendingTransaction * result = new PendingTransaction(ptImpl);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wallet::createTransactionMultiDestAsync(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||||
|
PendingTransaction::Priority priority)
|
||||||
|
{
|
||||||
|
m_scheduler.run([this, dst_addr, amount, priority] {
|
||||||
|
PendingTransaction *tx = createTransactionMultiDest(dst_addr, amount, priority);
|
||||||
|
QVector<QString> addresses;
|
||||||
|
for (auto &addr : dst_addr) {
|
||||||
|
addresses.push_back(addr);
|
||||||
|
}
|
||||||
|
emit transactionCreated(tx, addresses);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,7 +645,8 @@ void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &p
|
||||||
{
|
{
|
||||||
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
|
m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
|
||||||
PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority);
|
PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority);
|
||||||
emit transactionCreated(tx, dst_addr, payment_id, mixin_count);
|
QVector<QString> address {dst_addr};
|
||||||
|
emit transactionCreated(tx, address);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,7 +664,8 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
|
||||||
{
|
{
|
||||||
m_scheduler.run([this, key_image, dst_addr, outputs, priority] {
|
m_scheduler.run([this, key_image, dst_addr, outputs, priority] {
|
||||||
PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority);
|
PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority);
|
||||||
emit transactionCreated(tx, dst_addr, "", 10); // todo: return true mixincount
|
QVector<QString> address {dst_addr};
|
||||||
|
emit transactionCreated(tx, address);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,7 +680,8 @@ void Wallet::createSweepUnmixableTransactionAsync()
|
||||||
{
|
{
|
||||||
m_scheduler.run([this] {
|
m_scheduler.run([this] {
|
||||||
PendingTransaction *tx = createSweepUnmixableTransaction();
|
PendingTransaction *tx = createSweepUnmixableTransaction();
|
||||||
emit transactionCreated(tx, "", "", 0);
|
QVector<QString> address {""};
|
||||||
|
emit transactionCreated(tx, address);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,15 @@ public:
|
||||||
quint64 amount, quint32 mixin_count,
|
quint64 amount, quint32 mixin_count,
|
||||||
PendingTransaction::Priority priority);
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
|
//! creates multi-destination transaction
|
||||||
|
Q_INVOKABLE PendingTransaction * createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||||
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
|
//! creates async multi-destination transaction
|
||||||
|
Q_INVOKABLE void createTransactionMultiDestAsync(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||||
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
|
|
||||||
//! creates transaction with all outputs
|
//! creates transaction with all outputs
|
||||||
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||||
quint32 mixin_count, PendingTransaction::Priority priority);
|
quint32 mixin_count, PendingTransaction::Priority priority);
|
||||||
|
@ -449,7 +458,7 @@ signals:
|
||||||
void deviceShowAddressShowed();
|
void deviceShowAddressShowed();
|
||||||
|
|
||||||
// emitted when transaction is created async
|
// emitted when transaction is created async
|
||||||
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
|
void transactionCreated(PendingTransaction * transaction, QVector<QString> address);
|
||||||
|
|
||||||
void connectionStatusChanged(int status) const;
|
void connectionStatusChanged(int status) const;
|
||||||
void currentSubaddressAccountChanged() const;
|
void currentSubaddressAccountChanged() const;
|
||||||
|
|
|
@ -161,6 +161,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qInstallMessageHandler(Utils::applicationLogHandler);
|
qInstallMessageHandler(Utils::applicationLogHandler);
|
||||||
|
qRegisterMetaType<QVector<QString>>();
|
||||||
|
|
||||||
auto *mainWindow = new MainWindow(ctx);
|
auto *mainWindow = new MainWindow(ctx);
|
||||||
return QApplication::exec();
|
return QApplication::exec();
|
||||||
|
|
|
@ -74,6 +74,7 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
|
||||||
connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::menuQuitClicked);
|
connect(ui->actionQuit, &QAction::triggered, this, &MainWindow::menuQuitClicked);
|
||||||
connect(ui->actionSettings, &QAction::triggered, this, &MainWindow::menuSettingsClicked);
|
connect(ui->actionSettings, &QAction::triggered, this, &MainWindow::menuSettingsClicked);
|
||||||
connect(ui->actionCalculator, &QAction::triggered, this, &MainWindow::showCalcWindow);
|
connect(ui->actionCalculator, &QAction::triggered, this, &MainWindow::showCalcWindow);
|
||||||
|
connect(ui->actionPay_to_many, &QAction::triggered, this, &MainWindow::payToMany);
|
||||||
connect(ui->actionWallet_cache_debug, &QAction::triggered, this, &MainWindow::showWalletCacheDebugDialog);
|
connect(ui->actionWallet_cache_debug, &QAction::triggered, this, &MainWindow::showWalletCacheDebugDialog);
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
|
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
|
||||||
|
@ -153,6 +154,7 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
|
||||||
|
|
||||||
// Send widget
|
// Send widget
|
||||||
connect(ui->sendWidget, &SendWidget::createTransaction, m_ctx, QOverload<const QString &, quint64, const QString &, bool>::of(&AppContext::onCreateTransaction));
|
connect(ui->sendWidget, &SendWidget::createTransaction, m_ctx, QOverload<const QString &, quint64, const QString &, bool>::of(&AppContext::onCreateTransaction));
|
||||||
|
connect(ui->sendWidget, &SendWidget::createTransactionMultiDest, m_ctx, &AppContext::onCreateTransactionMultiDest);
|
||||||
|
|
||||||
// Nodes
|
// Nodes
|
||||||
connect(m_ctx->nodes, &Nodes::nodeExhausted, this, &MainWindow::showNodeExhaustedMessage);
|
connect(m_ctx->nodes, &Nodes::nodeExhausted, this, &MainWindow::showNodeExhaustedMessage);
|
||||||
|
@ -737,7 +739,7 @@ void MainWindow::onConnectionStatusChanged(int status)
|
||||||
m_statusBtnConnectionStatusIndicator->setIcon(QIcon(statusIcon));
|
m_statusBtnConnectionStatusIndicator->setIcon(QIcon(statusIcon));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QString &address, const quint32 &mixin) {
|
void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address) {
|
||||||
auto tx_status = tx->status();
|
auto tx_status = tx->status();
|
||||||
auto err = QString("Can't create transaction: ");
|
auto err = QString("Can't create transaction: ");
|
||||||
|
|
||||||
|
@ -761,7 +763,16 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QStrin
|
||||||
} else {
|
} else {
|
||||||
const auto &description = m_ctx->tmpTxDescription;
|
const auto &description = m_ctx->tmpTxDescription;
|
||||||
|
|
||||||
auto *dialog = new TxConfDialog(m_ctx, tx, address, description, mixin, this);
|
// Show advanced dialog on multi-destination transactions
|
||||||
|
if (address.size() > 1) {
|
||||||
|
auto *dialog_adv = new TxConfAdvDialog(m_ctx, description, this);
|
||||||
|
dialog_adv->setTransaction(tx);
|
||||||
|
dialog_adv->exec();
|
||||||
|
dialog_adv->deleteLater();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *dialog = new TxConfDialog(m_ctx, tx, address[0], description, this);
|
||||||
switch (dialog->exec()) {
|
switch (dialog->exec()) {
|
||||||
case QDialog::Rejected:
|
case QDialog::Rejected:
|
||||||
{
|
{
|
||||||
|
@ -1061,6 +1072,15 @@ void MainWindow::showCalcWindow() {
|
||||||
m_windowCalc->show();
|
m_windowCalc->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::payToMany() {
|
||||||
|
ui->tabWidget->setCurrentIndex(Tabs::SEND);
|
||||||
|
ui->sendWidget->payToMany();
|
||||||
|
QMessageBox::information(this, "Pay to many", "Enter a list of outputs in the 'Pay to' field.\n"
|
||||||
|
"One output per line.\n"
|
||||||
|
"Format: address, amount\n"
|
||||||
|
"A maximum of 16 addresses may be specified.");
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::showSendScreen(const CCSEntry &entry) {
|
void MainWindow::showSendScreen(const CCSEntry &entry) {
|
||||||
ui->sendWidget->fill(entry);
|
ui->sendWidget->fill(entry);
|
||||||
ui->tabWidget->setCurrentIndex(Tabs::SEND);
|
ui->tabWidget->setCurrentIndex(Tabs::SEND);
|
||||||
|
|
|
@ -104,6 +104,7 @@ public slots:
|
||||||
void showViewOnlyDialog();
|
void showViewOnlyDialog();
|
||||||
void donateButtonClicked();
|
void donateButtonClicked();
|
||||||
void showCalcWindow();
|
void showCalcWindow();
|
||||||
|
void payToMany();
|
||||||
void showWalletCacheDebugDialog();
|
void showWalletCacheDebugDialog();
|
||||||
void showSendTab();
|
void showSendTab();
|
||||||
void showHistoryTab();
|
void showHistoryTab();
|
||||||
|
@ -141,7 +142,7 @@ public slots:
|
||||||
void onWalletClosed(WalletWizard::Page page = WalletWizard::Page_Menu);
|
void onWalletClosed(WalletWizard::Page page = WalletWizard::Page_Menu);
|
||||||
void onConnectionStatusChanged(int status);
|
void onConnectionStatusChanged(int status);
|
||||||
void onCreateTransactionError(const QString &message);
|
void onCreateTransactionError(const QString &message);
|
||||||
void onCreateTransactionSuccess(PendingTransaction *tx, const QString &address, const quint32 &mixin);
|
void onCreateTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address);
|
||||||
void onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
|
void onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -190,7 +190,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="SendWidget" name="sendWidget" native="true">
|
<widget class="SendWidget" name="sendWidget" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
@ -446,6 +446,7 @@
|
||||||
<addaction name="menuLoad_signed_transaction"/>
|
<addaction name="menuLoad_signed_transaction"/>
|
||||||
<addaction name="actionImport_transaction"/>
|
<addaction name="actionImport_transaction"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionPay_to_many"/>
|
||||||
<addaction name="actionCalculator"/>
|
<addaction name="actionCalculator"/>
|
||||||
<addaction name="actionCreateDesktopEntry"/>
|
<addaction name="actionCreateDesktopEntry"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -726,6 +727,11 @@
|
||||||
<string>Wallet cache debug</string>
|
<string>Wallet cache debug</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionPay_to_many">
|
||||||
|
<property name="text">
|
||||||
|
<string>Pay to many</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
|
|
@ -24,8 +24,8 @@ SendWidget::SendWidget(QWidget *parent) :
|
||||||
connect(ui->btnClear, &QPushButton::clicked, this, &SendWidget::clearClicked);
|
connect(ui->btnClear, &QPushButton::clicked, this, &SendWidget::clearClicked);
|
||||||
connect(ui->btnMax, &QPushButton::clicked, this, &SendWidget::btnMaxClicked);
|
connect(ui->btnMax, &QPushButton::clicked, this, &SendWidget::btnMaxClicked);
|
||||||
connect(ui->comboCurrencySelection, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SendWidget::currencyComboChanged);
|
connect(ui->comboCurrencySelection, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SendWidget::currencyComboChanged);
|
||||||
connect(ui->lineAmount, &QLineEdit::textEdited, this, &SendWidget::amountEdited);
|
connect(ui->lineAmount, &QLineEdit::textChanged, this, &SendWidget::amountEdited);
|
||||||
connect(ui->lineAddress, &QLineEdit::textEdited, this, &SendWidget::addressEdited);
|
connect(ui->lineAddress, &QPlainTextEdit::textChanged, this, &SendWidget::addressEdited);
|
||||||
connect(ui->btn_openAlias, &QPushButton::clicked, this, &SendWidget::aliasClicked);
|
connect(ui->btn_openAlias, &QPushButton::clicked, this, &SendWidget::aliasClicked);
|
||||||
ui->label_conversionAmount->setText("");
|
ui->label_conversionAmount->setText("");
|
||||||
ui->label_conversionAmount->hide();
|
ui->label_conversionAmount->hide();
|
||||||
|
@ -41,6 +41,7 @@ SendWidget::SendWidget(QWidget *parent) :
|
||||||
"You will be able to review the transaction fee before the transaction is broadcast.\n\n"
|
"You will be able to review the transaction fee before the transaction is broadcast.\n\n"
|
||||||
"To send all your balance, click the Max button to the right.");
|
"To send all your balance, click the Max button to the right.");
|
||||||
|
|
||||||
|
ui->lineAddress->setNetType(m_ctx->networkType);
|
||||||
this->setupComboBox();
|
this->setupComboBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,8 +51,22 @@ void SendWidget::currencyComboChanged(int index) {
|
||||||
this->amountEdited(amount);
|
this->amountEdited(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendWidget::addressEdited(const QString &text) {
|
void SendWidget::addressEdited() {
|
||||||
text.contains(".") ? ui->btn_openAlias->show() : ui->btn_openAlias->hide();
|
QVector<PartialTxOutput> outputs = ui->lineAddress->getOutputs();
|
||||||
|
|
||||||
|
bool freezeAmounts = outputs.size() > 0;
|
||||||
|
|
||||||
|
ui->lineAmount->setReadOnly(freezeAmounts);
|
||||||
|
ui->lineAmount->setFrame(!freezeAmounts);
|
||||||
|
ui->btnMax->setDisabled(freezeAmounts);
|
||||||
|
|
||||||
|
if (outputs.size() > 0) {
|
||||||
|
ui->lineAmount->setText(WalletManager::displayAmount(ui->lineAddress->getTotal()));
|
||||||
|
} else {
|
||||||
|
ui->lineAmount->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->btn_openAlias->setVisible(ui->lineAddress->isOpenAlias());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendWidget::amountEdited(const QString &text) {
|
void SendWidget::amountEdited(const QString &text) {
|
||||||
|
@ -69,7 +84,9 @@ void SendWidget::fill(double amount) {
|
||||||
void SendWidget::fill(const QString &address, const QString &description, double amount) {
|
void SendWidget::fill(const QString &address, const QString &description, double amount) {
|
||||||
ui->lineDescription->setText(description);
|
ui->lineDescription->setText(description);
|
||||||
ui->lineAddress->setText(address);
|
ui->lineAddress->setText(address);
|
||||||
ui->lineAddress->setCursorPosition(0);
|
|
||||||
|
ui->lineAddress->moveCursor(QTextCursor::Start);
|
||||||
|
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
ui->lineAmount->setText(QString::number(amount));
|
ui->lineAmount->setText(QString::number(amount));
|
||||||
this->updateConversionLabel();
|
this->updateConversionLabel();
|
||||||
|
@ -77,7 +94,7 @@ void SendWidget::fill(const QString &address, const QString &description, double
|
||||||
|
|
||||||
void SendWidget::fillAddress(const QString &address) {
|
void SendWidget::fillAddress(const QString &address) {
|
||||||
ui->lineAddress->setText(address);
|
ui->lineAddress->setText(address);
|
||||||
ui->lineAddress->setCursorPosition(0);
|
ui->lineAddress->moveCursor(QTextCursor::Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendWidget::sendClicked() {
|
void SendWidget::sendClicked() {
|
||||||
|
@ -96,6 +113,35 @@ void SendWidget::sendClicked() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<PartialTxOutput> outputs = ui->lineAddress->getOutputs();
|
||||||
|
QVector<PayToLineError> errors = ui->lineAddress->getErrors();
|
||||||
|
if (errors.size() > 0 && ui->lineAddress->isMultiline()) {
|
||||||
|
QString errorText;
|
||||||
|
for (auto &error: errors) {
|
||||||
|
errorText += QString("Line #%1:\n%2\n").arg(QString::number(error.idx + 1), error.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::warning(this, "Warning", QString("Invalid lines found:\n\n%1").arg(errorText));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputs.size() > 0) { // multi destination transaction
|
||||||
|
if (outputs.size() > 16) {
|
||||||
|
QMessageBox::warning(this, "Warning", "Maximum number of outputs (16) exceeded.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<QString> addresses;
|
||||||
|
QVector<quint64> amounts;
|
||||||
|
for (auto &output : outputs) {
|
||||||
|
addresses.push_back(output.address);
|
||||||
|
amounts.push_back(output.amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit createTransactionMultiDest(addresses, amounts, description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
quint64 amount;
|
quint64 amount;
|
||||||
if (currency == "XMR") {
|
if (currency == "XMR") {
|
||||||
amount = this->amount();
|
amount = this->amount();
|
||||||
|
@ -193,6 +239,10 @@ void SendWidget::clearFields() {
|
||||||
ui->label_conversionAmount->clear();
|
ui->label_conversionAmount->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendWidget::payToMany() {
|
||||||
|
ui->lineAddress->payToMany();
|
||||||
|
}
|
||||||
|
|
||||||
void SendWidget::onWalletClosed() {
|
void SendWidget::onWalletClosed() {
|
||||||
this->clearFields();
|
this->clearFields();
|
||||||
ui->btnSend->setEnabled(true);
|
ui->btnSend->setEnabled(true);
|
||||||
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
void fill(const QString &address, const QString& description, double amount = 0);
|
void fill(const QString &address, const QString& description, double amount = 0);
|
||||||
void fill(double amount);
|
void fill(double amount);
|
||||||
void clearFields();
|
void clearFields();
|
||||||
|
void payToMany();
|
||||||
~SendWidget() override;
|
~SendWidget() override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -30,7 +31,7 @@ public slots:
|
||||||
void aliasClicked();
|
void aliasClicked();
|
||||||
void btnMaxClicked();
|
void btnMaxClicked();
|
||||||
void amountEdited(const QString &text);
|
void amountEdited(const QString &text);
|
||||||
void addressEdited(const QString &text);
|
void addressEdited();
|
||||||
void currencyComboChanged(int index);
|
void currencyComboChanged(int index);
|
||||||
void fillAddress(const QString &address);
|
void fillAddress(const QString &address);
|
||||||
void updateConversionLabel();
|
void updateConversionLabel();
|
||||||
|
@ -45,6 +46,7 @@ public slots:
|
||||||
signals:
|
signals:
|
||||||
void resolveOpenAlias(const QString &address);
|
void resolveOpenAlias(const QString &address);
|
||||||
void createTransaction(const QString &address, quint64 amount, const QString &description, bool all);
|
void createTransaction(const QString &address, quint64 amount, const QString &description, bool all);
|
||||||
|
void createTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupComboBox();
|
void setupComboBox();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>647</width>
|
<width>647</width>
|
||||||
<height>175</height>
|
<height>231</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -46,11 +46,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QLineEdit" name="lineAddress">
|
<widget class="PayToEdit" name="lineAddress"/>
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="HelpLabel" name="label_Description">
|
<widget class="HelpLabel" name="label_Description">
|
||||||
|
@ -190,6 +186,11 @@
|
||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
<header>components.h</header>
|
<header>components.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>PayToEdit</class>
|
||||||
|
<extends>QPlainTextEdit</extends>
|
||||||
|
<header>widgets/PayToEdit.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
@ -24,9 +24,9 @@ XmrToOrder::XmrToOrder(AppContext *ctx, UtilsNetworking *network, QString baseUr
|
||||||
connect(m_ctx, &AppContext::createTransactionCancelled, this, &XmrToOrder::onTransactionCancelled);
|
connect(m_ctx, &AppContext::createTransactionCancelled, this, &XmrToOrder::onTransactionCancelled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XmrToOrder::onTransactionCancelled(const QString &address, double amount) {
|
void XmrToOrder::onTransactionCancelled(const QVector<QString> &address, double amount) {
|
||||||
// listener for all cancelled transactions - will try to match the exact amount to this order.
|
// listener for all cancelled transactions - will try to match the exact amount to this order.
|
||||||
if(this->incoming_amount_total != amount || this->receiving_subaddress != address) return;
|
if(this->incoming_amount_total != amount || this->receiving_subaddress != address[0]) return;
|
||||||
|
|
||||||
this->errorMsg = "TX cancelled by user";
|
this->errorMsg = "TX cancelled by user";
|
||||||
this->changeState(OrderState::Status_OrderFailed);
|
this->changeState(OrderState::Status_OrderFailed);
|
||||||
|
|
|
@ -66,7 +66,7 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onCountdown();
|
void onCountdown();
|
||||||
void onTransactionCancelled(const QString &address, double amount);
|
void onTransactionCancelled(const QVector<QString> &address, double amount);
|
||||||
void onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
|
void onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
|
||||||
|
|
||||||
void onCreatedError();
|
void onCreatedError();
|
||||||
|
|
150
src/widgets/PayToEdit.cpp
Normal file
150
src/widgets/PayToEdit.cpp
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020-2021, The Monero Project.
|
||||||
|
// Copyright (c) 2012 thomasv@gitorious
|
||||||
|
|
||||||
|
#include "PayToEdit.h"
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
#include "utils/utils.h"
|
||||||
|
#include "model/ModelUtils.h"
|
||||||
|
|
||||||
|
#include "libwalletqt/WalletManager.h"
|
||||||
|
|
||||||
|
PayToEdit::PayToEdit(QWidget *parent) : QPlainTextEdit(parent)
|
||||||
|
{
|
||||||
|
this->setFont(ModelUtils::getMonospaceFont());
|
||||||
|
|
||||||
|
connect(this->document(), &QTextDocument::contentsChanged, this, &PayToEdit::updateSize);
|
||||||
|
connect(this, &QPlainTextEdit::textChanged, this, &PayToEdit::checkText);
|
||||||
|
|
||||||
|
this->updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayToEdit::setNetType(NetworkType::Type netType) {
|
||||||
|
m_netType = netType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayToEdit::setText(const QString &text) {
|
||||||
|
this->setPlainText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PayToEdit::text() {
|
||||||
|
return this->toPlainText();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<PayToLineError> PayToEdit::getErrors() {
|
||||||
|
return m_errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<PartialTxOutput> PayToEdit::getOutputs() {
|
||||||
|
return m_outputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 PayToEdit::getTotal() {
|
||||||
|
return m_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList PayToEdit::lines() {
|
||||||
|
return this->toPlainText().split("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PayToEdit::isMultiline() {
|
||||||
|
return this->lines().size() > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayToEdit::payToMany() {
|
||||||
|
this->setPlainText("\n\n\n");
|
||||||
|
this->updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PayToEdit::isOpenAlias() {
|
||||||
|
if (this->isMultiline()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto text = this->toPlainText().trimmed();
|
||||||
|
if (!(text.contains('.') and (!text.contains(' ')))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto parts = text.split(',');
|
||||||
|
if (parts.size() > 0 and WalletManager::addressValid(parts[0], m_netType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayToEdit::checkText() {
|
||||||
|
m_errors.clear();
|
||||||
|
m_outputs.clear();
|
||||||
|
|
||||||
|
// filter out empty lines
|
||||||
|
QStringList lines;
|
||||||
|
for (auto &l : this->lines()) {
|
||||||
|
if (!l.isEmpty()) {
|
||||||
|
lines.push_back(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->parseAsMultiline(lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayToEdit::updateSize() {
|
||||||
|
qreal lineHeight = QFontMetrics(this->document()->defaultFont()).height();
|
||||||
|
qreal docHeight = this->document()->size().height();
|
||||||
|
int h = int(docHeight * lineHeight + 11);
|
||||||
|
h = qMin(qMax(h, m_heightMin), m_heightMax);
|
||||||
|
this->setMinimumHeight(h);
|
||||||
|
this->setMaximumHeight(h);
|
||||||
|
this->verticalScrollBar()->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
PartialTxOutput PayToEdit::parseAddressAndAmount(const QString &line) {
|
||||||
|
QStringList x = line.split(",");
|
||||||
|
if (x.size() != 2) {
|
||||||
|
return PartialTxOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString address = this->parseAddress(x[0]);
|
||||||
|
quint64 amount = this->parseAmount(x[1]);
|
||||||
|
|
||||||
|
return PartialTxOutput(address, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 PayToEdit::parseAmount(QString amount) {
|
||||||
|
amount.replace(',', '.');
|
||||||
|
if (amount.isEmpty()) return 0;
|
||||||
|
|
||||||
|
return WalletManager::amountFromString(amount.trimmed());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PayToEdit::parseAddress(QString address) {
|
||||||
|
if (!WalletManager::addressValid(address.trimmed(), m_netType)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PayToEdit::parseAsMultiline(const QStringList &lines) {
|
||||||
|
m_outputs.clear();
|
||||||
|
m_total = 0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (auto &line : lines) {
|
||||||
|
PartialTxOutput output = this->parseAddressAndAmount(line);
|
||||||
|
if (output.address.isEmpty() && output.amount == 0) {
|
||||||
|
m_errors.append(PayToLineError(line, "Expected two comma-separated values: (address, amount)", i, true));
|
||||||
|
continue;
|
||||||
|
} else if (output.address.isEmpty()) {
|
||||||
|
m_errors.append(PayToLineError(line, "Invalid address", i, true));
|
||||||
|
continue;
|
||||||
|
} else if (output.amount == 0) {
|
||||||
|
m_errors.append(PayToLineError(line, "Invalid amount", i, true));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_outputs.append(output);
|
||||||
|
m_total += output.amount;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
70
src/widgets/PayToEdit.h
Normal file
70
src/widgets/PayToEdit.h
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020-2021, The Monero Project.
|
||||||
|
// Copyright (c) 2012 thomasv@gitorious
|
||||||
|
|
||||||
|
#ifndef FEATHER_PAYTOEDIT_H
|
||||||
|
#define FEATHER_PAYTOEDIT_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
struct PartialTxOutput {
|
||||||
|
explicit PartialTxOutput(QString address = "", quint64 amount = 0)
|
||||||
|
: address(address), amount(amount) {}
|
||||||
|
|
||||||
|
QString address;
|
||||||
|
quint64 amount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PayToLineError {
|
||||||
|
explicit PayToLineError(QString lineContent, QString error, int idx = 0, bool isMultiline = false)
|
||||||
|
: lineContent(lineContent), error(error), idx(idx), isMultiline(isMultiline) {}
|
||||||
|
|
||||||
|
QString lineContent;
|
||||||
|
QString error;
|
||||||
|
int idx;
|
||||||
|
bool isMultiline;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PayToEdit : public QPlainTextEdit
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PayToEdit(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void setNetType(NetworkType::Type netType);
|
||||||
|
void setText(const QString &text);
|
||||||
|
QString text();
|
||||||
|
|
||||||
|
QVector<PayToLineError> getErrors();
|
||||||
|
QVector<PartialTxOutput> getOutputs();
|
||||||
|
quint64 getTotal();
|
||||||
|
|
||||||
|
QStringList lines();
|
||||||
|
bool isMultiline();
|
||||||
|
void payToMany();
|
||||||
|
bool isOpenAlias();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkText();
|
||||||
|
void updateSize();
|
||||||
|
|
||||||
|
PartialTxOutput parseAddressAndAmount(const QString &line);
|
||||||
|
quint64 parseAmount(QString amount);
|
||||||
|
QString parseAddress(QString address);
|
||||||
|
|
||||||
|
void parseAsMultiline(const QStringList &lines);
|
||||||
|
|
||||||
|
int m_heightMin = 0;
|
||||||
|
int m_heightMax = 150;
|
||||||
|
quint64 m_total = 0;
|
||||||
|
NetworkType::Type m_netType = NetworkType::Type::MAINNET;
|
||||||
|
|
||||||
|
QVector<PayToLineError> m_errors;
|
||||||
|
QVector<PartialTxOutput> m_outputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //FEATHER_PAYTOEDIT_H
|
Loading…
Reference in a new issue