Changeset View
Changeset View
Standalone View
Standalone View
src/qt/sendcoinsdialog.cpp
Show All 18 Lines | |||||
#include <qt/guiutil.h> | #include <qt/guiutil.h> | ||||
#include <qt/optionsmodel.h> | #include <qt/optionsmodel.h> | ||||
#include <qt/platformstyle.h> | #include <qt/platformstyle.h> | ||||
#include <qt/sendcoinsentry.h> | #include <qt/sendcoinsentry.h> | ||||
#include <txmempool.h> | #include <txmempool.h> | ||||
#include <ui_interface.h> | #include <ui_interface.h> | ||||
#include <wallet/coincontrol.h> | #include <wallet/coincontrol.h> | ||||
#include <wallet/fees.h> | #include <wallet/fees.h> | ||||
#include <wallet/psbtwallet.h> | |||||
#include <wallet/wallet.h> | #include <wallet/wallet.h> | ||||
#include <QScrollBar> | #include <QScrollBar> | ||||
#include <QSettings> | #include <QSettings> | ||||
#include <QTextDocument> | #include <QTextDocument> | ||||
SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, | SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, | ||||
WalletModel *_model, QWidget *parent) | WalletModel *_model, QWidget *parent) | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | #endif | ||||
&SendCoinsDialog::updateFeeSectionControls); | &SendCoinsDialog::updateFeeSectionControls); | ||||
connect(ui->checkBoxMinimumFee, &QCheckBox::stateChanged, this, | connect(ui->checkBoxMinimumFee, &QCheckBox::stateChanged, this, | ||||
&SendCoinsDialog::coinControlUpdateLabels); | &SendCoinsDialog::coinControlUpdateLabels); | ||||
ui->customFee->setSingleStep(model->wallet().getRequiredFee(1000)); | ui->customFee->setSingleStep(model->wallet().getRequiredFee(1000)); | ||||
updateFeeSectionControls(); | updateFeeSectionControls(); | ||||
updateMinFeeLabel(); | updateMinFeeLabel(); | ||||
updateSmartFeeLabel(); | updateSmartFeeLabel(); | ||||
if (model->privateKeysDisabled()) { | |||||
ui->sendButton->setText(tr("Cr&eate Unsigned")); | |||||
ui->sendButton->setToolTip( | |||||
tr("Creates a Partially Signed Bitcoin Transaction (PSBT) for " | |||||
"use with e.g. an offline %1 wallet, or a PSBT-compatible " | |||||
"hardware wallet.") | |||||
.arg(PACKAGE_NAME)); | |||||
} | |||||
} | } | ||||
} | } | ||||
SendCoinsDialog::~SendCoinsDialog() { | SendCoinsDialog::~SendCoinsDialog() { | ||||
QSettings settings; | QSettings settings; | ||||
settings.setValue("fFeeSectionMinimized", fFeeMinimized); | settings.setValue("fFeeSectionMinimized", fFeeMinimized); | ||||
settings.setValue("nFeeRadio", ui->groupFee->checkedId()); | settings.setValue("nFeeRadio", ui->groupFee->checkedId()); | ||||
settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId()); | settings.setValue("nCustomFeeRadio", ui->groupCustomFee->checkedId()); | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | #ifdef ENABLE_BIP70 | ||||
// unauthenticated payment request | // unauthenticated payment request | ||||
recipientElement.append(tr("%1 to %2").arg(amount, address)); | recipientElement.append(tr("%1 to %2").arg(amount, address)); | ||||
} | } | ||||
#endif | #endif | ||||
formatted.append(recipientElement); | formatted.append(recipientElement); | ||||
} | } | ||||
QString questionString = tr("Are you sure you want to send?"); | QString questionString; | ||||
if (model->privateKeysDisabled()) { | |||||
questionString.append(tr("Do you want to draft this transaction?")); | |||||
} else { | |||||
questionString.append(tr("Are you sure you want to send?")); | |||||
} | |||||
questionString.append("<br /><span style='font-size:10pt;'>"); | questionString.append("<br /><span style='font-size:10pt;'>"); | ||||
if (model->privateKeysDisabled()) { | |||||
questionString.append( | |||||
tr("Please, review your transaction proposal. This will produce a " | |||||
"Partially Signed Bitcoin Transaction (PSBT) which you can copy " | |||||
"and then sign with e.g. an offline %1 wallet, or a " | |||||
"PSBT-compatible hardware wallet.") | |||||
.arg(PACKAGE_NAME)); | |||||
} else { | |||||
questionString.append(tr("Please, review your transaction.")); | questionString.append(tr("Please, review your transaction.")); | ||||
} | |||||
questionString.append("</span>%1"); | questionString.append("</span>%1"); | ||||
if (txFee > Amount::zero()) { | if (txFee > Amount::zero()) { | ||||
// append fee string if a fee is required | // append fee string if a fee is required | ||||
questionString.append("<hr /><b>"); | questionString.append("<hr /><b>"); | ||||
questionString.append(tr("Transaction fee")); | questionString.append(tr("Transaction fee")); | ||||
questionString.append("</b>"); | questionString.append("</b>"); | ||||
Show All 38 Lines | if (formatted.size() > 1) { | ||||
questionString = questionString.arg(""); | questionString = questionString.arg(""); | ||||
informative_text = | informative_text = | ||||
tr("To review recipient list click \"Show Details...\""); | tr("To review recipient list click \"Show Details...\""); | ||||
detailed_text = formatted.join("\n\n"); | detailed_text = formatted.join("\n\n"); | ||||
} else { | } else { | ||||
questionString = questionString.arg("<br /><br />" + formatted.at(0)); | questionString = questionString.arg("<br /><br />" + formatted.at(0)); | ||||
} | } | ||||
const QString confirmation = model->privateKeysDisabled() | |||||
? tr("Confirm transaction proposal") | |||||
: tr("Confirm send coins"); | |||||
const QString confirmButtonText = model->privateKeysDisabled() | |||||
? tr("Copy PSBT to clipboard") | |||||
: tr("Send"); | |||||
SendConfirmationDialog confirmationDialog( | SendConfirmationDialog confirmationDialog( | ||||
tr("Confirm send coins"), questionString, informative_text, | confirmation, questionString, informative_text, detailed_text, | ||||
detailed_text, SEND_CONFIRM_DELAY, this); | SEND_CONFIRM_DELAY, confirmButtonText, this); | ||||
confirmationDialog.exec(); | confirmationDialog.exec(); | ||||
QMessageBox::StandardButton retval = | QMessageBox::StandardButton retval = | ||||
static_cast<QMessageBox::StandardButton>(confirmationDialog.result()); | static_cast<QMessageBox::StandardButton>(confirmationDialog.result()); | ||||
if (retval != QMessageBox::Yes) { | if (retval != QMessageBox::Yes) { | ||||
fNewRecipientAllowed = true; | fNewRecipientAllowed = true; | ||||
return; | return; | ||||
} | } | ||||
bool send_failure = false; | |||||
if (model->privateKeysDisabled()) { | |||||
CMutableTransaction mtx = | |||||
CMutableTransaction{*(currentTransaction.getWtx())}; | |||||
PartiallySignedTransaction psbtx(mtx); | |||||
bool complete = false; | |||||
const TransactionError err = model->wallet().fillPSBT( | |||||
psbtx, complete, SigHashType().withForkId(), false /* sign */, | |||||
true /* bip32derivs */); | |||||
assert(!complete); | |||||
assert(err == TransactionError::OK); | |||||
// Serialize the PSBT | |||||
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); | |||||
ssTx << psbtx; | |||||
GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str()); | |||||
Q_EMIT message(tr("PSBT copied"), "Copied to clipboard", | |||||
CClientUIInterface::MSG_INFORMATION); | |||||
} else { | |||||
// now send the prepared transaction | // now send the prepared transaction | ||||
WalletModel::SendCoinsReturn sendStatus = | WalletModel::SendCoinsReturn sendStatus = | ||||
model->sendCoins(currentTransaction); | model->sendCoins(currentTransaction); | ||||
// process sendStatus and on error generate message shown to user | // process sendStatus and on error generate message shown to user | ||||
processSendCoinsReturn(sendStatus); | processSendCoinsReturn(sendStatus); | ||||
if (sendStatus.status == WalletModel::OK) { | if (sendStatus.status == WalletModel::OK) { | ||||
Q_EMIT coinsSent(currentTransaction.getWtx()->GetId()); | |||||
} else { | |||||
send_failure = true; | |||||
} | |||||
} | |||||
if (!send_failure) { | |||||
accept(); | accept(); | ||||
CoinControlDialog::coinControl()->UnSelectAll(); | CoinControlDialog::coinControl()->UnSelectAll(); | ||||
coinControlUpdateLabels(); | coinControlUpdateLabels(); | ||||
Q_EMIT coinsSent(currentTransaction.getWtx()->GetId()); | |||||
} | } | ||||
fNewRecipientAllowed = true; | fNewRecipientAllowed = true; | ||||
} | } | ||||
void SendCoinsDialog::clear() { | void SendCoinsDialog::clear() { | ||||
// Clear coin control settings | // Clear coin control settings | ||||
CoinControlDialog::coinControl()->UnSelectAll(); | CoinControlDialog::coinControl()->UnSelectAll(); | ||||
ui->checkBoxCoinControlChange->setChecked(false); | ui->checkBoxCoinControlChange->setChecked(false); | ||||
▲ Show 20 Lines • Show All 492 Lines • ▼ Show 20 Lines | void SendCoinsDialog::coinControlUpdateLabels() { | ||||
} else { | } else { | ||||
// hide coin control stats | // hide coin control stats | ||||
ui->labelCoinControlAutomaticallySelected->show(); | ui->labelCoinControlAutomaticallySelected->show(); | ||||
ui->widgetCoinControl->hide(); | ui->widgetCoinControl->hide(); | ||||
ui->labelCoinControlInsuffFunds->hide(); | ui->labelCoinControlInsuffFunds->hide(); | ||||
} | } | ||||
} | } | ||||
SendConfirmationDialog::SendConfirmationDialog(const QString &title, | SendConfirmationDialog::SendConfirmationDialog( | ||||
const QString &text, | const QString &title, const QString &text, const QString &informative_text, | ||||
const QString &informative_text, | const QString &detailed_text, int _secDelay, | ||||
const QString &detailed_text, | const QString &_confirmButtonText, QWidget *parent) | ||||
int _secDelay, QWidget *parent) | : QMessageBox(parent), secDelay(_secDelay), | ||||
: QMessageBox(parent), secDelay(_secDelay) { | confirmButtonText(_confirmButtonText) { | ||||
setIcon(QMessageBox::Question); | setIcon(QMessageBox::Question); | ||||
// On macOS, the window title is ignored (as required by the macOS | // On macOS, the window title is ignored (as required by the macOS | ||||
// Guidelines). | // Guidelines). | ||||
setWindowTitle(title); | setWindowTitle(title); | ||||
setText(text); | setText(text); | ||||
setInformativeText(informative_text); | setInformativeText(informative_text); | ||||
setDetailedText(detailed_text); | setDetailedText(detailed_text); | ||||
setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); | setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); | ||||
Show All 17 Lines | void SendConfirmationDialog::countDown() { | ||||
if (secDelay <= 0) { | if (secDelay <= 0) { | ||||
countDownTimer.stop(); | countDownTimer.stop(); | ||||
} | } | ||||
} | } | ||||
void SendConfirmationDialog::updateYesButton() { | void SendConfirmationDialog::updateYesButton() { | ||||
if (secDelay > 0) { | if (secDelay > 0) { | ||||
yesButton->setEnabled(false); | yesButton->setEnabled(false); | ||||
yesButton->setText(tr("Send") + " (" + QString::number(secDelay) + ")"); | yesButton->setText(confirmButtonText + " (" + | ||||
QString::number(secDelay) + ")"); | |||||
} else { | } else { | ||||
yesButton->setEnabled(true); | yesButton->setEnabled(true); | ||||
yesButton->setText(tr("Send")); | yesButton->setText(confirmButtonText); | ||||
} | } | ||||
} | } |