Bitcoin Core  21.99.0
P2P Digital Currency
sendcoinsdialog.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2020 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #if defined(HAVE_CONFIG_H)
7 #endif
8 
9 #include <qt/sendcoinsdialog.h>
10 #include <qt/forms/ui_sendcoinsdialog.h>
11 
12 #include <qt/addresstablemodel.h>
13 #include <qt/bitcoinunits.h>
14 #include <qt/clientmodel.h>
15 #include <qt/coincontroldialog.h>
16 #include <qt/guiutil.h>
17 #include <qt/optionsmodel.h>
18 #include <qt/platformstyle.h>
19 #include <qt/sendcoinsentry.h>
20 
21 #include <chainparams.h>
22 #include <interfaces/node.h>
23 #include <key_io.h>
24 #include <node/ui_interface.h>
25 #include <policy/fees.h>
26 #include <txmempool.h>
27 #include <wallet/coincontrol.h>
28 #include <wallet/fees.h>
29 #include <wallet/wallet.h>
30 
31 #include <validation.h>
32 
33 #include <QFontMetrics>
34 #include <QScrollBar>
35 #include <QSettings>
36 #include <QTextDocument>
37 
38 static constexpr std::array confTargets{2, 4, 6, 12, 24, 48, 144, 504, 1008};
39 int getConfTargetForIndex(int index) {
40  if (index+1 > static_cast<int>(confTargets.size())) {
41  return confTargets.back();
42  }
43  if (index < 0) {
44  return confTargets[0];
45  }
46  return confTargets[index];
47 }
48 int getIndexForConfTarget(int target) {
49  for (unsigned int i = 0; i < confTargets.size(); i++) {
50  if (confTargets[i] >= target) {
51  return i;
52  }
53  }
54  return confTargets.size() - 1;
55 }
56 
57 SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
58  QDialog(parent, GUIUtil::dialog_flags),
59  ui(new Ui::SendCoinsDialog),
60  clientModel(nullptr),
61  model(nullptr),
62  m_coin_control(new CCoinControl),
63  fNewRecipientAllowed(true),
64  fFeeMinimized(true),
65  platformStyle(_platformStyle)
66 {
67  ui->setupUi(this);
68 
69  if (!_platformStyle->getImagesOnButtons()) {
70  ui->addButton->setIcon(QIcon());
71  ui->clearButton->setIcon(QIcon());
72  ui->sendButton->setIcon(QIcon());
73  } else {
74  ui->addButton->setIcon(_platformStyle->SingleColorIcon(":/icons/add"));
75  ui->clearButton->setIcon(_platformStyle->SingleColorIcon(":/icons/remove"));
76  ui->sendButton->setIcon(_platformStyle->SingleColorIcon(":/icons/send"));
77  }
78 
79  GUIUtil::setupAddressWidget(ui->lineEditCoinControlChange, this);
80 
81  addEntry();
82 
83  connect(ui->addButton, &QPushButton::clicked, this, &SendCoinsDialog::addEntry);
84  connect(ui->clearButton, &QPushButton::clicked, this, &SendCoinsDialog::clear);
85 
86  // Coin Control
87  connect(ui->pushButtonCoinControl, &QPushButton::clicked, this, &SendCoinsDialog::coinControlButtonClicked);
88  connect(ui->checkBoxCoinControlChange, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlChangeChecked);
89  connect(ui->lineEditCoinControlChange, &QValidatedLineEdit::textEdited, this, &SendCoinsDialog::coinControlChangeEdited);
90 
91  // Coin Control: clipboard actions
92  QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this);
93  QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this);
94  QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this);
95  QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this);
96  QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this);
97  QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this);
98  QAction *clipboardChangeAction = new QAction(tr("Copy change"), this);
99  connect(clipboardQuantityAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardQuantity);
100  connect(clipboardAmountAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardAmount);
101  connect(clipboardFeeAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardFee);
102  connect(clipboardAfterFeeAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardAfterFee);
103  connect(clipboardBytesAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardBytes);
104  connect(clipboardLowOutputAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardLowOutput);
105  connect(clipboardChangeAction, &QAction::triggered, this, &SendCoinsDialog::coinControlClipboardChange);
106  ui->labelCoinControlQuantity->addAction(clipboardQuantityAction);
107  ui->labelCoinControlAmount->addAction(clipboardAmountAction);
108  ui->labelCoinControlFee->addAction(clipboardFeeAction);
109  ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction);
110  ui->labelCoinControlBytes->addAction(clipboardBytesAction);
111  ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction);
112  ui->labelCoinControlChange->addAction(clipboardChangeAction);
113 
114  // init transaction fee section
115  QSettings settings;
116  if (!settings.contains("fFeeSectionMinimized"))
117  settings.setValue("fFeeSectionMinimized", true);
118  if (!settings.contains("nFeeRadio") && settings.contains("nTransactionFee") && settings.value("nTransactionFee").toLongLong() > 0) // compatibility
119  settings.setValue("nFeeRadio", 1); // custom
120  if (!settings.contains("nFeeRadio"))
121  settings.setValue("nFeeRadio", 0); // recommended
122  if (!settings.contains("nSmartFeeSliderPosition"))
123  settings.setValue("nSmartFeeSliderPosition", 0);
124  if (!settings.contains("nTransactionFee"))
125  settings.setValue("nTransactionFee", (qint64)DEFAULT_PAY_TX_FEE);
126  ui->groupFee->setId(ui->radioSmartFee, 0);
127  ui->groupFee->setId(ui->radioCustomFee, 1);
128  ui->groupFee->button((int)std::max(0, std::min(1, settings.value("nFeeRadio").toInt())))->setChecked(true);
129  ui->customFee->SetAllowEmpty(false);
130  ui->customFee->setValue(settings.value("nTransactionFee").toLongLong());
131  minimizeFeeSection(settings.value("fFeeSectionMinimized").toBool());
132 
133  GUIUtil::ExceptionSafeConnect(ui->sendButton, &QPushButton::clicked, this, &SendCoinsDialog::sendButtonClicked);
134 }
135 
137 {
138  this->clientModel = _clientModel;
139 
140  if (_clientModel) {
142  }
143 }
144 
146 {
147  this->model = _model;
148 
149  if(_model && _model->getOptionsModel())
150  {
151  for(int i = 0; i < ui->entries->count(); ++i)
152  {
153  SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
154  if(entry)
155  {
156  entry->setModel(_model);
157  }
158  }
159 
160  interfaces::WalletBalances balances = _model->wallet().getBalances();
161  setBalance(balances);
165 
166  // Coin Control
169  ui->frameCoinControl->setVisible(_model->getOptionsModel()->getCoinControlFeatures());
171 
172  // fee section
173  for (const int n : confTargets) {
174  ui->confTargetSelector->addItem(tr("%1 (%2 blocks)").arg(GUIUtil::formatNiceTimeOffset(n*Params().GetConsensus().nPowTargetSpacing)).arg(n));
175  }
176  connect(ui->confTargetSelector, qOverload<int>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::updateSmartFeeLabel);
177  connect(ui->confTargetSelector, qOverload<int>(&QComboBox::currentIndexChanged), this, &SendCoinsDialog::coinControlUpdateLabels);
178 
179 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
180  connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::updateFeeSectionControls);
181  connect(ui->groupFee, &QButtonGroup::idClicked, this, &SendCoinsDialog::coinControlUpdateLabels);
182 #else
183  connect(ui->groupFee, qOverload<int>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::updateFeeSectionControls);
184  connect(ui->groupFee, qOverload<int>(&QButtonGroup::buttonClicked), this, &SendCoinsDialog::coinControlUpdateLabels);
185 #endif
186 
188  connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::updateSmartFeeLabel);
189  connect(ui->optInRBF, &QCheckBox::stateChanged, this, &SendCoinsDialog::coinControlUpdateLabels);
190  CAmount requiredFee = model->wallet().getRequiredFee(1000);
191  ui->customFee->SetMinValue(requiredFee);
192  if (ui->customFee->value() < requiredFee) {
193  ui->customFee->setValue(requiredFee);
194  }
195  ui->customFee->setSingleStep(requiredFee);
198 
199  // set default rbf checkbox state
200  ui->optInRBF->setCheckState(Qt::Checked);
201 
202  if (model->wallet().hasExternalSigner()) {
203  ui->sendButton->setText(tr("Sign on device"));
204  if (gArgs.GetArg("-signer", "") != "") {
205  ui->sendButton->setEnabled(true);
206  ui->sendButton->setToolTip(tr("Connect your hardware wallet first."));
207  } else {
208  ui->sendButton->setEnabled(false);
209  ui->sendButton->setToolTip(tr("Set external signer script path in Options -> Wallet"));
210  }
211  } else if (model->wallet().privateKeysDisabled()) {
212  ui->sendButton->setText(tr("Cr&eate Unsigned"));
213  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));
214  }
215 
216  // set the smartfee-sliders default value (wallets default conf.target or last stored value)
217  QSettings settings;
218  if (settings.value("nSmartFeeSliderPosition").toInt() != 0) {
219  // migrate nSmartFeeSliderPosition to nConfTarget
220  // nConfTarget is available since 0.15 (replaced nSmartFeeSliderPosition)
221  int nConfirmTarget = 25 - settings.value("nSmartFeeSliderPosition").toInt(); // 25 == old slider range
222  settings.setValue("nConfTarget", nConfirmTarget);
223  settings.remove("nSmartFeeSliderPosition");
224  }
225  if (settings.value("nConfTarget").toInt() == 0)
226  ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(model->wallet().getConfirmTarget()));
227  else
228  ui->confTargetSelector->setCurrentIndex(getIndexForConfTarget(settings.value("nConfTarget").toInt()));
229  }
230 }
231 
233 {
234  QSettings settings;
235  settings.setValue("fFeeSectionMinimized", fFeeMinimized);
236  settings.setValue("nFeeRadio", ui->groupFee->checkedId());
237  settings.setValue("nConfTarget", getConfTargetForIndex(ui->confTargetSelector->currentIndex()));
238  settings.setValue("nTransactionFee", (qint64)ui->customFee->value());
239 
240  delete ui;
241 }
242 
243 bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informative_text, QString& detailed_text)
244 {
245  QList<SendCoinsRecipient> recipients;
246  bool valid = true;
247 
248  for(int i = 0; i < ui->entries->count(); ++i)
249  {
250  SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
251  if(entry)
252  {
253  if(entry->validate(model->node()))
254  {
255  recipients.append(entry->getValue());
256  }
257  else if (valid)
258  {
259  ui->scrollArea->ensureWidgetVisible(entry);
260  valid = false;
261  }
262  }
263  }
264 
265  if(!valid || recipients.isEmpty())
266  {
267  return false;
268  }
269 
270  fNewRecipientAllowed = false;
272  if(!ctx.isValid())
273  {
274  // Unlock wallet was cancelled
275  fNewRecipientAllowed = true;
276  return false;
277  }
278 
279  // prepare transaction for getting txFee earlier
280  m_current_transaction = std::make_unique<WalletModelTransaction>(recipients);
281  WalletModel::SendCoinsReturn prepareStatus;
282 
284 
286 
287  // process prepareStatus and on error generate message shown to user
288  processSendCoinsReturn(prepareStatus,
290 
291  if(prepareStatus.status != WalletModel::OK) {
292  fNewRecipientAllowed = true;
293  return false;
294  }
295 
296  CAmount txFee = m_current_transaction->getTransactionFee();
297  QStringList formatted;
298  for (const SendCoinsRecipient &rcp : m_current_transaction->getRecipients())
299  {
300  // generate amount string with wallet name in case of multiwallet
301  QString amount = BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
302  if (model->isMultiwallet()) {
303  amount.append(tr(" from wallet '%1'").arg(GUIUtil::HtmlEscape(model->getWalletName())));
304  }
305 
306  // generate address string
307  QString address = rcp.address;
308 
309  QString recipientElement;
310 
311  {
312  if(rcp.label.length() > 0) // label with address
313  {
314  recipientElement.append(tr("%1 to '%2'").arg(amount, GUIUtil::HtmlEscape(rcp.label)));
315  recipientElement.append(QString(" (%1)").arg(address));
316  }
317  else // just address
318  {
319  recipientElement.append(tr("%1 to %2").arg(amount, address));
320  }
321  }
322  formatted.append(recipientElement);
323  }
324 
326  question_string.append(tr("Do you want to draft this transaction?"));
327  } else {
328  question_string.append(tr("Are you sure you want to send?"));
329  }
330 
331  question_string.append("<br /><span style='font-size:10pt;'>");
333  question_string.append(tr("Please, review your transaction proposal. This will produce a Partially Signed Bitcoin Transaction (PSBT) which you can save or copy and then sign with e.g. an offline %1 wallet, or a PSBT-compatible hardware wallet.").arg(PACKAGE_NAME));
334  } else {
335  question_string.append(tr("Please, review your transaction."));
336  }
337  question_string.append("</span>%1");
338 
339  if(txFee > 0)
340  {
341  // append fee string if a fee is required
342  question_string.append("<hr /><b>");
343  question_string.append(tr("Transaction fee"));
344  question_string.append("</b>");
345 
346  // append transaction size
347  question_string.append(" (" + QString::number((double)m_current_transaction->getTransactionSize() / 1000) + " kB): ");
348 
349  // append transaction fee value
350  question_string.append("<span style='color:#aa0000; font-weight:bold;'>");
351  question_string.append(BitcoinUnits::formatHtmlWithUnit(model->getOptionsModel()->getDisplayUnit(), txFee));
352  question_string.append("</span><br />");
353 
354  // append RBF message according to transaction's signalling
355  question_string.append("<span style='font-size:10pt; font-weight:normal;'>");
356  if (ui->optInRBF->isChecked()) {
357  question_string.append(tr("You can increase the fee later (signals Replace-By-Fee, BIP-125)."));
358  } else {
359  question_string.append(tr("Not signalling Replace-By-Fee, BIP-125."));
360  }
361  question_string.append("</span>");
362  }
363 
364  // add total amount in all subdivision units
365  question_string.append("<hr />");
366  CAmount totalAmount = m_current_transaction->getTotalTransactionAmount() + txFee;
367  QStringList alternativeUnits;
369  {
370  if(u != model->getOptionsModel()->getDisplayUnit())
371  alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount));
372  }
373  question_string.append(QString("<b>%1</b>: <b>%2</b>").arg(tr("Total Amount"))
375  question_string.append(QString("<br /><span style='font-size:10pt; font-weight:normal;'>(=%1)</span>")
376  .arg(alternativeUnits.join(" " + tr("or") + " ")));
377 
378  if (formatted.size() > 1) {
379  question_string = question_string.arg("");
380  informative_text = tr("To review recipient list click \"Show Details…\"");
381  detailed_text = formatted.join("\n\n");
382  } else {
383  question_string = question_string.arg("<br /><br />" + formatted.at(0));
384  }
385 
386  return true;
387 }
388 
389 void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
390 {
391  if(!model || !model->getOptionsModel())
392  return;
393 
394  QString question_string, informative_text, detailed_text;
395  if (!PrepareSendText(question_string, informative_text, detailed_text)) return;
397 
398  const QString confirmation = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner() ? tr("Confirm transaction proposal") : tr("Confirm send coins");
399  const QString confirmButtonText = model->wallet().privateKeysDisabled() && !model->wallet().hasExternalSigner() ? tr("Create Unsigned") : tr("Sign and send");
400  SendConfirmationDialog confirmationDialog(confirmation, question_string, informative_text, detailed_text, SEND_CONFIRM_DELAY, confirmButtonText, this);
401  confirmationDialog.exec();
402  QMessageBox::StandardButton retval = static_cast<QMessageBox::StandardButton>(confirmationDialog.result());
403 
404  if(retval != QMessageBox::Yes)
405  {
406  fNewRecipientAllowed = true;
407  return;
408  }
409 
410  bool send_failure = false;
411  if (model->wallet().privateKeysDisabled()) {
413  PartiallySignedTransaction psbtx(mtx);
414  bool complete = false;
415  // Always fill without signing first. This prevents an external signer
416  // from being called prematurely and is not expensive.
417  TransactionError err = model->wallet().fillPSBT(SIGHASH_ALL, false /* sign */, true /* bip32derivs */, nullptr, psbtx, complete);
418  assert(!complete);
420  if (model->wallet().hasExternalSigner()) {
421  try {
422  err = model->wallet().fillPSBT(SIGHASH_ALL, true /* sign */, true /* bip32derivs */, nullptr, psbtx, complete);
423  } catch (const std::runtime_error& e) {
424  QMessageBox::critical(nullptr, tr("Sign failed"), e.what());
425  send_failure = true;
426  return;
427  }
429  QMessageBox::critical(nullptr, tr("External signer not found"), "External signer not found");
430  send_failure = true;
431  return;
432  }
434  QMessageBox::critical(nullptr, tr("External signer failure"), "External signer failure");
435  send_failure = true;
436  return;
437  }
438  if (err != TransactionError::OK) {
439  tfm::format(std::cerr, "Failed to sign PSBT");
441  send_failure = true;
442  return;
443  }
444  // fillPSBT does not always properly finalize
445  complete = FinalizeAndExtractPSBT(psbtx, mtx);
446  }
447 
448  // Broadcast transaction if complete (even with an external signer this
449  // is not always the case, e.g. in a multisig wallet).
450  if (complete) {
451  const CTransactionRef tx = MakeTransactionRef(mtx);
452  m_current_transaction->setWtx(tx);
454  // process sendStatus and on error generate message shown to user
455  processSendCoinsReturn(sendStatus);
456 
457  if (sendStatus.status == WalletModel::OK) {
458  Q_EMIT coinsSent(m_current_transaction->getWtx()->GetHash());
459  } else {
460  send_failure = true;
461  }
462  return;
463  }
464 
465  // Copy PSBT to clipboard and offer to save
466  assert(!complete);
467  // Serialize the PSBT
469  ssTx << psbtx;
470  GUIUtil::setClipboard(EncodeBase64(ssTx.str()).c_str());
471  QMessageBox msgBox;
472  msgBox.setText("Unsigned Transaction");
473  msgBox.setInformativeText("The PSBT has been copied to the clipboard. You can also save it.");
474  msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard);
475  msgBox.setDefaultButton(QMessageBox::Discard);
476  switch (msgBox.exec()) {
477  case QMessageBox::Save: {
478  QString selectedFilter;
479  QString fileNameSuggestion = "";
480  bool first = true;
481  for (const SendCoinsRecipient &rcp : m_current_transaction->getRecipients()) {
482  if (!first) {
483  fileNameSuggestion.append(" - ");
484  }
485  QString labelOrAddress = rcp.label.isEmpty() ? rcp.address : rcp.label;
486  QString amount = BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), rcp.amount);
487  fileNameSuggestion.append(labelOrAddress + "-" + amount);
488  first = false;
489  }
490  fileNameSuggestion.append(".psbt");
491  QString filename = GUIUtil::getSaveFileName(this,
492  tr("Save Transaction Data"), fileNameSuggestion,
493  //: Expanded name of the binary PSBT file format. See: BIP 174.
494  tr("Partially Signed Transaction (Binary)") + QLatin1String(" (*.psbt)"), &selectedFilter);
495  if (filename.isEmpty()) {
496  return;
497  }
498  std::ofstream out(filename.toLocal8Bit().data(), std::ofstream::out | std::ofstream::binary);
499  out << ssTx.str();
500  out.close();
501  Q_EMIT message(tr("PSBT saved"), "PSBT saved to disk", CClientUIInterface::MSG_INFORMATION);
502  break;
503  }
504  case QMessageBox::Discard:
505  break;
506  default:
507  assert(false);
508  } // msgBox.exec()
509  } else {
510  // now send the prepared transaction
512  // process sendStatus and on error generate message shown to user
513  processSendCoinsReturn(sendStatus);
514 
515  if (sendStatus.status == WalletModel::OK) {
516  Q_EMIT coinsSent(m_current_transaction->getWtx()->GetHash());
517  } else {
518  send_failure = true;
519  }
520  }
521  if (!send_failure) {
522  accept();
523  m_coin_control->UnSelectAll();
525  }
526  fNewRecipientAllowed = true;
527  m_current_transaction.reset();
528 }
529 
531 {
532  m_current_transaction.reset();
533 
534  // Clear coin control settings
535  m_coin_control->UnSelectAll();
536  ui->checkBoxCoinControlChange->setChecked(false);
537  ui->lineEditCoinControlChange->clear();
539 
540  // Remove entries until only one left
541  while(ui->entries->count())
542  {
543  ui->entries->takeAt(0)->widget()->deleteLater();
544  }
545  addEntry();
546 
548 }
549 
551 {
552  clear();
553 }
554 
556 {
557  clear();
558 }
559 
561 {
562  SendCoinsEntry *entry = new SendCoinsEntry(platformStyle, this);
563  entry->setModel(model);
564  ui->entries->addWidget(entry);
569 
570  // Focus the field, so that entry can start immediately
571  entry->clear();
572  entry->setFocus();
573  ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
574  qApp->processEvents();
575  QScrollBar* bar = ui->scrollArea->verticalScrollBar();
576  if(bar)
577  bar->setSliderPosition(bar->maximum());
578 
580  return entry;
581 }
582 
584 {
585  setupTabChain(nullptr);
587 }
588 
590 {
591  entry->hide();
592 
593  // If the last entry is about to be removed add an empty one
594  if (ui->entries->count() == 1)
595  addEntry();
596 
597  entry->deleteLater();
598 
600 }
601 
602 QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
603 {
604  for(int i = 0; i < ui->entries->count(); ++i)
605  {
606  SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
607  if(entry)
608  {
609  prev = entry->setupTabChain(prev);
610  }
611  }
612  QWidget::setTabOrder(prev, ui->sendButton);
613  QWidget::setTabOrder(ui->sendButton, ui->clearButton);
614  QWidget::setTabOrder(ui->clearButton, ui->addButton);
615  return ui->addButton;
616 }
617 
618 void SendCoinsDialog::setAddress(const QString &address)
619 {
620  SendCoinsEntry *entry = nullptr;
621  // Replace the first entry if it is still unused
622  if(ui->entries->count() == 1)
623  {
624  SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
625  if(first->isClear())
626  {
627  entry = first;
628  }
629  }
630  if(!entry)
631  {
632  entry = addEntry();
633  }
634 
635  entry->setAddress(address);
636 }
637 
639 {
641  return;
642 
643  SendCoinsEntry *entry = nullptr;
644  // Replace the first entry if it is still unused
645  if(ui->entries->count() == 1)
646  {
647  SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
648  if(first->isClear())
649  {
650  entry = first;
651  }
652  }
653  if(!entry)
654  {
655  entry = addEntry();
656  }
657 
658  entry->setValue(rv);
660 }
661 
663 {
664  // Just paste the entry, all pre-checks
665  // are done in paymentserver.cpp.
666  pasteEntry(rv);
667  return true;
668 }
669 
671 {
672  if(model && model->getOptionsModel())
673  {
674  CAmount balance = balances.balance;
675  if (model->wallet().hasExternalSigner()) {
676  ui->labelBalanceName->setText(tr("External balance:"));
677  } else if (model->wallet().privateKeysDisabled()) {
678  balance = balances.watch_only_balance;
679  ui->labelBalanceName->setText(tr("Watch-only balance:"));
680  }
682  }
683 }
684 
686 {
688  ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
690 }
691 
692 void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg)
693 {
694  QPair<QString, CClientUIInterface::MessageBoxFlags> msgParams;
695  // Default to a warning message, override if error message is needed
696  msgParams.second = CClientUIInterface::MSG_WARNING;
697 
698  // This comment is specific to SendCoinsDialog usage of WalletModel::SendCoinsReturn.
699  // All status values are used only in WalletModel::prepareTransaction()
700  switch(sendCoinsReturn.status)
701  {
703  msgParams.first = tr("The recipient address is not valid. Please recheck.");
704  break;
706  msgParams.first = tr("The amount to pay must be larger than 0.");
707  break;
709  msgParams.first = tr("The amount exceeds your balance.");
710  break;
712  msgParams.first = tr("The total exceeds your balance when the %1 transaction fee is included.").arg(msgArg);
713  break;
715  msgParams.first = tr("Duplicate address found: addresses should only be used once each.");
716  break;
718  msgParams.first = tr("Transaction creation failed!");
719  msgParams.second = CClientUIInterface::MSG_ERROR;
720  break;
722  msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), model->wallet().getDefaultMaxTxFee()));
723  break;
725  msgParams.first = tr("Payment request expired.");
726  msgParams.second = CClientUIInterface::MSG_ERROR;
727  break;
728  // included to prevent a compiler warning.
729  case WalletModel::OK:
730  default:
731  return;
732  }
733 
734  Q_EMIT message(tr("Send Coins"), msgParams.first, msgParams.second);
735 }
736 
738 {
739  ui->labelFeeMinimized->setVisible(fMinimize);
740  ui->buttonChooseFee ->setVisible(fMinimize);
741  ui->buttonMinimizeFee->setVisible(!fMinimize);
742  ui->frameFeeSelection->setVisible(!fMinimize);
743  ui->horizontalLayoutSmartFee->setContentsMargins(0, (fMinimize ? 0 : 6), 0, 0);
744  fFeeMinimized = fMinimize;
745 }
746 
748 {
749  minimizeFeeSection(false);
750 }
751 
753 {
755  minimizeFeeSection(true);
756 }
757 
759 {
760  // Include watch-only for wallets without private key
762 
763  // Calculate available amount to send.
765  for (int i = 0; i < ui->entries->count(); ++i) {
766  SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
767  if (e && !e->isHidden() && e != entry) {
768  amount -= e->getValue().amount;
769  }
770  }
771 
772  if (amount > 0) {
774  entry->setAmount(amount);
775  } else {
776  entry->setAmount(0);
777  }
778 }
779 
781 {
782  ui->confTargetSelector ->setEnabled(ui->radioSmartFee->isChecked());
783  ui->labelSmartFee ->setEnabled(ui->radioSmartFee->isChecked());
784  ui->labelSmartFee2 ->setEnabled(ui->radioSmartFee->isChecked());
785  ui->labelSmartFee3 ->setEnabled(ui->radioSmartFee->isChecked());
786  ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked());
787  ui->labelCustomFeeWarning ->setEnabled(ui->radioCustomFee->isChecked());
788  ui->labelCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked());
789  ui->customFee ->setEnabled(ui->radioCustomFee->isChecked());
790 }
791 
793 {
794  if(!model || !model->getOptionsModel())
795  return;
796 
797  if (ui->radioSmartFee->isChecked())
798  ui->labelFeeMinimized->setText(ui->labelSmartFee->text());
799  else {
800  ui->labelFeeMinimized->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), ui->customFee->value()) + "/kvB");
801  }
802 }
803 
805 {
806  if (ui->radioCustomFee->isChecked()) {
807  m_coin_control->m_feerate = CFeeRate(ui->customFee->value());
808  } else {
809  m_coin_control->m_feerate.reset();
810  }
811  // Avoid using global defaults when sending money from the GUI
812  // Either custom fee will be used or if not selected, the confirmation target from dropdown box
813  m_coin_control->m_confirm_target = getConfTargetForIndex(ui->confTargetSelector->currentIndex());
814  m_coin_control->m_signal_bip125_rbf = ui->optInRBF->isChecked();
815  // Include watch-only for wallets without private key
817 }
818 
819 void SendCoinsDialog::updateNumberOfBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state) {
820  if (sync_state == SynchronizationState::POST_INIT) {
822  }
823 }
824 
826 {
827  if(!model || !model->getOptionsModel())
828  return;
830  m_coin_control->m_feerate.reset(); // Explicitly use only fee estimation rate for smart fee labels
831  int returned_target;
832  FeeReason reason;
833  CFeeRate feeRate = CFeeRate(model->wallet().getMinimumFee(1000, *m_coin_control, &returned_target, &reason));
834 
835  ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kvB");
836 
837  if (reason == FeeReason::FALLBACK) {
838  ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...)
839  ui->labelFeeEstimation->setText("");
840  ui->fallbackFeeWarningLabel->setVisible(true);
841  int lightness = ui->fallbackFeeWarningLabel->palette().color(QPalette::WindowText).lightness();
842  QColor warning_colour(255 - (lightness / 5), 176 - (lightness / 3), 48 - (lightness / 14));
843  ui->fallbackFeeWarningLabel->setStyleSheet("QLabel { color: " + warning_colour.name() + "; }");
844  ui->fallbackFeeWarningLabel->setIndent(GUIUtil::TextWidth(QFontMetrics(ui->fallbackFeeWarningLabel->font()), "x"));
845  }
846  else
847  {
848  ui->labelSmartFee2->hide();
849  ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", returned_target));
850  ui->fallbackFeeWarningLabel->setVisible(false);
851  }
852 
854 }
855 
856 // Coin Control: copy label "Quantity" to clipboard
858 {
859  GUIUtil::setClipboard(ui->labelCoinControlQuantity->text());
860 }
861 
862 // Coin Control: copy label "Amount" to clipboard
864 {
865  GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" ")));
866 }
867 
868 // Coin Control: copy label "Fee" to clipboard
870 {
871  GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
872 }
873 
874 // Coin Control: copy label "After fee" to clipboard
876 {
877  GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
878 }
879 
880 // Coin Control: copy label "Bytes" to clipboard
882 {
883  GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, ""));
884 }
885 
886 // Coin Control: copy label "Dust" to clipboard
888 {
889  GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text());
890 }
891 
892 // Coin Control: copy label "Change" to clipboard
894 {
895  GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace(ASYMP_UTF8, ""));
896 }
897 
898 // Coin Control: settings menu - coin control enabled/disabled by user
900 {
901  ui->frameCoinControl->setVisible(checked);
902 
903  if (!checked && model) { // coin control features disabled
904  m_coin_control = std::make_unique<CCoinControl>();
905  }
906 
908 }
909 
910 // Coin Control: button inputs -> show actual coin control dialog
912 {
914  dlg.exec();
916 }
917 
918 // Coin Control: checkbox custom change address
920 {
921  if (state == Qt::Unchecked)
922  {
923  m_coin_control->destChange = CNoDestination();
924  ui->labelCoinControlChangeLabel->clear();
925  }
926  else
927  // use this to re-validate an already entered address
928  coinControlChangeEdited(ui->lineEditCoinControlChange->text());
929 
930  ui->lineEditCoinControlChange->setEnabled((state == Qt::Checked));
931 }
932 
933 // Coin Control: custom change address changed
935 {
936  if (model && model->getAddressTableModel())
937  {
938  // Default to no change address until verified
939  m_coin_control->destChange = CNoDestination();
940  ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
941 
942  const CTxDestination dest = DecodeDestination(text.toStdString());
943 
944  if (text.isEmpty()) // Nothing entered
945  {
946  ui->labelCoinControlChangeLabel->setText("");
947  }
948  else if (!IsValidDestination(dest)) // Invalid address
949  {
950  ui->labelCoinControlChangeLabel->setText(tr("Warning: Invalid Bitcoin address"));
951  }
952  else // Valid address
953  {
954  if (!model->wallet().isSpendable(dest)) {
955  ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address"));
956 
957  // confirmation dialog
958  QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm custom change address"), tr("The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?"),
959  QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
960 
961  if(btnRetVal == QMessageBox::Yes)
962  m_coin_control->destChange = dest;
963  else
964  {
965  ui->lineEditCoinControlChange->setText("");
966  ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}");
967  ui->labelCoinControlChangeLabel->setText("");
968  }
969  }
970  else // Known change address
971  {
972  ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}");
973 
974  // Query label
975  QString associatedLabel = model->getAddressTableModel()->labelForAddress(text);
976  if (!associatedLabel.isEmpty())
977  ui->labelCoinControlChangeLabel->setText(associatedLabel);
978  else
979  ui->labelCoinControlChangeLabel->setText(tr("(no label)"));
980 
981  m_coin_control->destChange = dest;
982  }
983  }
984  }
985 }
986 
987 // Coin Control: update labels
989 {
990  if (!model || !model->getOptionsModel())
991  return;
992 
994 
995  // set pay amounts
998 
999  for(int i = 0; i < ui->entries->count(); ++i)
1000  {
1001  SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
1002  if(entry && !entry->isHidden())
1003  {
1004  SendCoinsRecipient rcp = entry->getValue();
1006  if (rcp.fSubtractFeeFromAmount)
1008  }
1009  }
1010 
1011  if (m_coin_control->HasSelected())
1012  {
1013  // actual coin control calculation
1015 
1016  // show coin control stats
1017  ui->labelCoinControlAutomaticallySelected->hide();
1018  ui->widgetCoinControl->show();
1019  }
1020  else
1021  {
1022  // hide coin control stats
1023  ui->labelCoinControlAutomaticallySelected->show();
1024  ui->widgetCoinControl->hide();
1025  ui->labelCoinControlInsuffFunds->hide();
1026  }
1027 }
1028 
1029 SendConfirmationDialog::SendConfirmationDialog(const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, const QString& _confirmButtonText, QWidget* parent)
1030  : QMessageBox(parent), secDelay(_secDelay), confirmButtonText(_confirmButtonText)
1031 {
1032  setIcon(QMessageBox::Question);
1033  setWindowTitle(title); // On macOS, the window title is ignored (as required by the macOS Guidelines).
1034  setText(text);
1035  setInformativeText(informative_text);
1036  setDetailedText(detailed_text);
1037  setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel);
1038  setDefaultButton(QMessageBox::Cancel);
1039  yesButton = button(QMessageBox::Yes);
1040  if (confirmButtonText.isEmpty()) {
1041  confirmButtonText = yesButton->text();
1042  }
1043  updateYesButton();
1044  connect(&countDownTimer, &QTimer::timeout, this, &SendConfirmationDialog::countDown);
1045 }
1046 
1048 {
1049  updateYesButton();
1050  countDownTimer.start(1000);
1051  return QMessageBox::exec();
1052 }
1053 
1055 {
1056  secDelay--;
1057  updateYesButton();
1058 
1059  if(secDelay <= 0)
1060  {
1061  countDownTimer.stop();
1062  }
1063 }
1064 
1066 {
1067  if(secDelay > 0)
1068  {
1069  yesButton->setEnabled(false);
1070  yesButton->setText(confirmButtonText + " (" + QString::number(secDelay) + ")");
1071  }
1072  else
1073  {
1074  yesButton->setEnabled(true);
1075  yesButton->setText(confirmButtonText);
1076  }
1077 }
SendCoinsRecipient::amount
CAmount amount
Definition: sendcoinsrecipient.h:33
interfaces::Wallet::getAvailableBalance
virtual CAmount getAvailableBalance(const CCoinControl &coin_control)=0
Get available balance.
ASYMP_UTF8
#define ASYMP_UTF8
Definition: coincontroldialog.h:28
ClientModel::numBlocksChanged
void numBlocksChanged(int count, const QDateTime &blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state)
SendCoinsDialog::coinControlClipboardAmount
void coinControlClipboardAmount()
Definition: sendcoinsdialog.cpp:863
SendCoinsDialog::on_buttonChooseFee_clicked
void on_buttonChooseFee_clicked()
Definition: sendcoinsdialog.cpp:747
CClientUIInterface::MSG_INFORMATION
@ MSG_INFORMATION
Predefined combinations for certain default usage cases.
Definition: ui_interface.h:66
interfaces::Wallet::getMinimumFee
virtual CAmount getMinimumFee(unsigned int tx_bytes, const CCoinControl &coin_control, int *returned_target, FeeReason *reason)=0
Get minimum fee.
WalletModel::getOptionsModel
OptionsModel * getOptionsModel()
Definition: walletmodel.cpp:284
SendCoinsEntry::setAddress
void setAddress(const QString &address)
Definition: sendcoinsentry.cpp:207
FeeReason
FeeReason
Definition: fees.h:43
SendCoinsDialog::fNewRecipientAllowed
bool fNewRecipientAllowed
Definition: sendcoinsdialog.h:67
count
static int count
Definition: tests.c:41
assert
assert(!tx.IsCoinBase())
CoinControlDialog::payAmounts
static QList< CAmount > payAmounts
Definition: coincontroldialog.h:51
tinyformat::format
void format(std::ostream &out, const char *fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition: tinyformat.h:1062
SendConfirmationDialog
Definition: sendcoinsdialog.h:112
SendCoinsDialog::coinsSent
void coinsSent(const uint256 &txid)
interfaces::Wallet::hasExternalSigner
virtual bool hasExternalSigner()=0
wallet.h
WalletModel
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:51
SendCoinsEntry::payAmountChanged
void payAmountChanged()
SEND_CONFIRM_DELAY
#define SEND_CONFIRM_DELAY
Definition: sendcoinsdialog.h:110
SendCoinsEntry::setValue
void setValue(const SendCoinsRecipient &value)
Definition: sendcoinsentry.cpp:190
interfaces::Wallet::getConfirmTarget
virtual unsigned int getConfirmTarget()=0
Get tx confirm target.
BitcoinUnits::formatWithUnit
static QString formatWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as string (with unit)
Definition: bitcoinunits.cpp:148
BitcoinAmountField::valueChanged
void valueChanged()
key_io.h
PlatformStyle::SingleColorIcon
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
Definition: platformstyle.cpp:105
WalletModel::TransactionCreationFailed
@ TransactionCreationFailed
Definition: walletmodel.h:67
sendcoinsdialog.h
TransactionError::EXTERNAL_SIGNER_FAILED
@ EXTERNAL_SIGNER_FAILED
getIndexForConfTarget
int getIndexForConfTarget(int target)
Definition: sendcoinsdialog.cpp:48
WalletModel::getAddressTableModel
AddressTableModel * getAddressTableModel()
Definition: walletmodel.cpp:289
SendCoinsEntry::setFocus
void setFocus()
Definition: sendcoinsentry.cpp:223
AddressTableModel::labelForAddress
QString labelForAddress(const QString &address) const
Look up label for address in address book, if not found return empty string.
Definition: addresstablemodel.cpp:412
WalletModel::DuplicateAddress
@ DuplicateAddress
Definition: walletmodel.h:66
CCoinControl
Coin Control Features.
Definition: coincontrol.h:23
WalletModel::sendCoins
SendCoinsReturn sendCoins(WalletModelTransaction &transaction)
Definition: walletmodel.cpp:234
WalletModel::AmountWithFeeExceedsBalance
@ AmountWithFeeExceedsBalance
Definition: walletmodel.h:65
CoinControlDialog
Definition: coincontroldialog.h:40
SendCoinsDialog::updateNumberOfBlocks
void updateNumberOfBlocks(int count, const QDateTime &blockDate, double nVerificationProgress, bool headers, SynchronizationState sync_state)
Definition: sendcoinsdialog.cpp:819
WalletModel::AbsurdFee
@ AbsurdFee
Definition: walletmodel.h:68
GUIUtil
Utility functions used by the Bitcoin Qt UI.
Definition: bitcoingui.h:59
SendCoinsDialog::coinControlFeatureChanged
void coinControlFeatureChanged(bool)
Definition: sendcoinsdialog.cpp:899
SendCoinsEntry::setupTabChain
QWidget * setupTabChain(QWidget *prev)
Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://...
Definition: sendcoinsentry.cpp:178
WalletModel::isMultiwallet
bool isMultiwallet()
Definition: walletmodel.cpp:583
SendCoinsDialog::coinControlButtonClicked
void coinControlButtonClicked()
Definition: sendcoinsdialog.cpp:911
SendCoinsDialog::updateCoinControlState
void updateCoinControlState()
Definition: sendcoinsdialog.cpp:804
BitcoinUnits::formatHtmlWithUnit
static QString formatHtmlWithUnit(int unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD)
Format as HTML string (with unit)
Definition: bitcoinunits.cpp:153
MakeTransactionRef
static CTransactionRef MakeTransactionRef(Tx &&txIn)
Definition: transaction.h:387
OptionsModel::displayUnitChanged
void displayUnitChanged(int unit)
GUIUtil::ExceptionSafeConnect
auto ExceptionSafeConnect(Sender sender, Signal signal, Receiver receiver, Slot method, Qt::ConnectionType type=Qt::AutoConnection)
A drop-in replacement of QObject::connect function (see: https://doc.qt.io/qt-5/qobject....
Definition: guiutil.h:386
SendCoinsDialog::addEntry
SendCoinsEntry * addEntry()
Definition: sendcoinsdialog.cpp:560
SendCoinsDialog::useAvailableBalance
void useAvailableBalance(SendCoinsEntry *entry)
Definition: sendcoinsdialog.cpp:758
CoinControlDialog::updateLabels
static void updateLabels(CCoinControl &m_coin_control, WalletModel *, QDialog *)
Definition: coincontroldialog.cpp:379
EncodeBase64
std::string EncodeBase64(Span< const unsigned char > input)
Definition: strencodings.cpp:131
bitcoin-config.h
FinalizeAndExtractPSBT
bool FinalizeAndExtractPSBT(PartiallySignedTransaction &psbtx, CMutableTransaction &result)
Finalizes a PSBT if possible, and extracts it to a CMutableTransaction if it could be finalized.
Definition: psbt.cpp:312
chainparams.h
CTransactionRef
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:386
SendCoinsDialog::~SendCoinsDialog
~SendCoinsDialog()
Definition: sendcoinsdialog.cpp:232
WalletModel::requestUnlock
UnlockContext requestUnlock()
Definition: walletmodel.cpp:433
GUIUtil::dialog_flags
constexpr auto dialog_flags
Definition: guiutil.h:59
WalletModel::prepareTransaction
SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl &coinControl)
Definition: walletmodel.cpp:150
interfaces::WalletBalances::balance
CAmount balance
Definition: wallet.h:354
CFeeRate
Fee rate in satoshis per kilobyte: CAmount / kB.
Definition: feerate.h:29
balance
static CAmount balance
Definition: coinselector_tests.cpp:33
SendCoinsDialog::clientModel
ClientModel * clientModel
Definition: sendcoinsdialog.h:63
SendCoinsDialog::updateDisplayUnit
void updateDisplayUnit()
Definition: sendcoinsdialog.cpp:685
SendCoinsDialog::sendButtonClicked
void sendButtonClicked(bool checked)
Definition: sendcoinsdialog.cpp:389
GUIUtil::setClipboard
void setClipboard(const QString &str)
Definition: guiutil.cpp:638
txmempool.h
SendCoinsDialog::coinControlClipboardAfterFee
void coinControlClipboardAfterFee()
Definition: sendcoinsdialog.cpp:875
WalletModel::node
interfaces::Node & node() const
Definition: walletmodel.h:143
CoinControlDialog::fSubtractFeeFromAmount
static bool fSubtractFeeFromAmount
Definition: coincontroldialog.h:52
interfaces::WalletBalances::watch_only_balance
CAmount watch_only_balance
Definition: wallet.h:358
SendCoinsEntry::clear
void clear()
Definition: sendcoinsentry.cpp:94
fsbridge::ofstream
fs::ofstream ofstream
Definition: fs.h:102
SendCoinsRecipient
Definition: sendcoinsrecipient.h:19
fees.h
SendCoinsDialog::updateFeeMinimizedLabel
void updateFeeMinimizedLabel()
Definition: sendcoinsdialog.cpp:792
TransactionError
TransactionError
Definition: error.h:22
WalletModel::wallet
interfaces::Wallet & wallet() const
Definition: walletmodel.h:144
BitcoinUnits::availableUnits
static QList< Unit > availableUnits()
Get list of units, for drop-down box.
Definition: bitcoinunits.cpp:19
interfaces::WalletBalances
Collection of wallet balances.
Definition: wallet.h:352
WalletModel::AmountExceedsBalance
@ AmountExceedsBalance
Definition: walletmodel.h:64
CTxDestination
std::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessV1Taproot, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:156
SendConfirmationDialog::confirmButtonText
QString confirmButtonText
Definition: sendcoinsdialog.h:128
FeeReason::FALLBACK
@ FALLBACK
IsValidDestination
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:373
GUIUtil::formatNiceTimeOffset
QString formatNiceTimeOffset(qint64 secs)
Definition: guiutil.cpp:735
interfaces::Wallet::getRequiredFee
virtual CAmount getRequiredFee(unsigned int tx_bytes)=0
Get required fee.
sendcoinsentry.h
PACKAGE_NAME
#define PACKAGE_NAME
Definition: bitcoin-config.h:365
WalletModel::SendCoinsReturn::status
StatusCode status
Definition: walletmodel.h:97
PlatformStyle::getImagesOnButtons
bool getImagesOnButtons() const
Definition: platformstyle.h:21
node.h
SendCoinsDialog::handlePaymentRequest
bool handlePaymentRequest(const SendCoinsRecipient &recipient)
Definition: sendcoinsdialog.cpp:662
TransactionError::EXTERNAL_SIGNER_NOT_FOUND
@ EXTERNAL_SIGNER_NOT_FOUND
OptionsModel::getCoinControlFeatures
bool getCoinControlFeatures() const
Definition: optionsmodel.h:90
CClientUIInterface::MSG_WARNING
@ MSG_WARNING
Definition: ui_interface.h:67
SendCoinsEntry::isClear
bool isClear()
Return whether the entry is still empty and unedited.
Definition: sendcoinsentry.cpp:218
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:583
CAmount
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
getConfTargetForIndex
int getConfTargetForIndex(int index)
Definition: sendcoinsdialog.cpp:39
SendCoinsDialog::m_current_transaction
std::unique_ptr< WalletModelTransaction > m_current_transaction
Definition: sendcoinsdialog.h:66
SendCoinsDialog
Dialog for sending bitcoins.
Definition: sendcoinsdialog.h:31
guiutil.h
WalletModel::getWalletName
QString getWalletName() const
Definition: walletmodel.cpp:572
SendConfirmationDialog::secDelay
int secDelay
Definition: sendcoinsdialog.h:127
SendCoinsDialog::minimizeFeeSection
void minimizeFeeSection(bool fMinimize)
Definition: sendcoinsdialog.cpp:737
SendCoinsDialog::setBalance
void setBalance(const interfaces::WalletBalances &balances)
Definition: sendcoinsdialog.cpp:670
SendCoinsDialog::setAddress
void setAddress(const QString &address)
Definition: sendcoinsdialog.cpp:618
SendCoinsDialog::setupTabChain
QWidget * setupTabChain(QWidget *prev)
Set up the tab chain manually, as Qt messes up the tab chain by default in some cases (issue https://...
Definition: sendcoinsdialog.cpp:602
interfaces::Wallet::getBalances
virtual WalletBalances getBalances()=0
Get balances.
SendCoinsEntry::validate
bool validate(interfaces::Node &node)
Definition: sendcoinsentry.cpp:132
DecodeDestination
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg)
Definition: key_io.cpp:261
confTargets
static constexpr std::array confTargets
Definition: sendcoinsdialog.cpp:38
SendCoinsDialog::platformStyle
const PlatformStyle * platformStyle
Definition: sendcoinsdialog.h:69
CNoDestination
Definition: standard.h:72
SendCoinsDialog::PrepareSendText
bool PrepareSendText(QString &question_string, QString &informative_text, QString &detailed_text)
Definition: sendcoinsdialog.cpp:243
SendCoinsDialog::coinControlClipboardBytes
void coinControlClipboardBytes()
Definition: sendcoinsdialog.cpp:881
SendCoinsDialog::ui
Ui::SendCoinsDialog * ui
Definition: sendcoinsdialog.h:62
interfaces::Wallet::getDefaultMaxTxFee
virtual CAmount getDefaultMaxTxFee()=0
Get max tx fee.
SendCoinsDialog::updateTabsAndLabels
void updateTabsAndLabels()
Definition: sendcoinsdialog.cpp:583
SendCoinsEntry::setModel
void setModel(WalletModel *model)
Definition: sendcoinsentry.cpp:84
ui_interface.h
GUIUtil::getSaveFileName
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
Definition: guiutil.cpp:279
SendCoinsDialog::m_coin_control
std::unique_ptr< CCoinControl > m_coin_control
Definition: sendcoinsdialog.h:65
platformstyle.h
SendCoinsDialog::coinControlClipboardChange
void coinControlClipboardChange()
Definition: sendcoinsdialog.cpp:893
CClientUIInterface::MSG_ERROR
@ MSG_ERROR
Definition: ui_interface.h:68
SendCoinsEntry::useAvailableBalance
void useAvailableBalance(SendCoinsEntry *entry)
ClientModel
Model for Bitcoin network client.
Definition: clientmodel.h:47
SIGHASH_ALL
@ SIGHASH_ALL
Definition: interpreter.h:27
Ui
Definition: addressbookpage.h:14
WalletModel::OK
@ OK
Definition: walletmodel.h:61
SendConfirmationDialog::countDown
void countDown()
Definition: sendcoinsdialog.cpp:1054
GUIUtil::HtmlEscape
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:232
SendCoinsDialog::pasteEntry
void pasteEntry(const SendCoinsRecipient &rv)
Definition: sendcoinsdialog.cpp:638
SendConfirmationDialog::exec
int exec() override
Definition: sendcoinsdialog.cpp:1047
SendCoinsDialog::model
WalletModel * model
Definition: sendcoinsdialog.h:64
fees.h
WalletModel::UnlockContext
Definition: walletmodel.h:114
WalletModel::InvalidAmount
@ InvalidAmount
Definition: walletmodel.h:62
SendCoinsDialog::SendCoinsDialog
SendCoinsDialog(const PlatformStyle *platformStyle, QWidget *parent=nullptr)
Definition: sendcoinsdialog.cpp:57
OptionsModel::getDisplayUnit
int getDisplayUnit() const
Definition: optionsmodel.h:87
SendCoinsDialog::setClientModel
void setClientModel(ClientModel *clientModel)
Definition: sendcoinsdialog.cpp:136
PartiallySignedTransaction
A version of CTransaction with the PSBT format.
Definition: psbt.h:391
gArgs
ArgsManager gArgs
Definition: system.cpp:79
DEFAULT_PAY_TX_FEE
constexpr CAmount DEFAULT_PAY_TX_FEE
-paytxfee default
Definition: wallet.h:68
WalletModel::InvalidAddress
@ InvalidAddress
Definition: walletmodel.h:63
TransactionError::OK
@ OK
No error.
SendCoinsEntry::removeEntry
void removeEntry(SendCoinsEntry *entry)
SendCoinsDialog::coinControlClipboardLowOutput
void coinControlClipboardLowOutput()
Definition: sendcoinsdialog.cpp:887
SendConfirmationDialog::updateYesButton
void updateYesButton()
Definition: sendcoinsdialog.cpp:1065
BitcoinUnits::Unit
Unit
Bitcoin units.
Definition: bitcoinunits.h:41
SendCoinsDialog::setModel
void setModel(WalletModel *model)
Definition: sendcoinsdialog.cpp:145
coincontroldialog.h
SendConfirmationDialog::yesButton
QAbstractButton * yesButton
Definition: sendcoinsdialog.h:125
SendCoinsDialog::coinControlChangeChecked
void coinControlChangeChecked(int)
Definition: sendcoinsdialog.cpp:919
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:538
WalletModel::SendCoinsReturn
Definition: walletmodel.h:90
SendCoinsEntry::checkSubtractFeeFromAmount
void checkSubtractFeeFromAmount()
Definition: sendcoinsentry.cpp:117
bitcoinunits.h
SendCoinsDialog::message
void message(const QString &title, const QString &message, unsigned int style)
SendCoinsDialog::updateFeeSectionControls
void updateFeeSectionControls()
Definition: sendcoinsdialog.cpp:780
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:204
SendCoinsDialog::coinControlClipboardFee
void coinControlClipboardFee()
Definition: sendcoinsdialog.cpp:869
SendCoinsDialog::coinControlChangeEdited
void coinControlChangeEdited(const QString &)
Definition: sendcoinsdialog.cpp:934
SendCoinsEntry
A single entry in the dialog for sending bitcoins.
Definition: sendcoinsentry.h:28
SendCoinsDialog::coinControlUpdateLabels
void coinControlUpdateLabels()
Definition: sendcoinsdialog.cpp:988
SendCoinsDialog::removeEntry
void removeEntry(SendCoinsEntry *entry)
Definition: sendcoinsdialog.cpp:589
SER_NETWORK
@ SER_NETWORK
Definition: serialize.h:138
GUIUtil::TextWidth
int TextWidth(const QFontMetrics &fm, const QString &text)
Returns the distance in pixels appropriate for drawing a subsequent character after text.
Definition: guiutil.cpp:864
SendCoinsDialog::fFeeMinimized
bool fFeeMinimized
Definition: sendcoinsdialog.h:68
SynchronizationState
SynchronizationState
Current sync state passed to tip changed callbacks.
Definition: validation.h:103
SendCoinsEntry::subtractFeeFromAmountChanged
void subtractFeeFromAmountChanged()
SendCoinsDialog::clear
void clear()
Definition: sendcoinsdialog.cpp:530
optionsmodel.h
WalletModel::PaymentRequestExpired
@ PaymentRequestExpired
Definition: walletmodel.h:69
interfaces::Wallet::isSpendable
virtual bool isSpendable(const CTxDestination &dest)=0
Return whether wallet has private key.
SendCoinsDialog::accept
void accept() override
Definition: sendcoinsdialog.cpp:555
CMutableTransaction
A mutable version of CTransaction.
Definition: transaction.h:344
coincontrol.h
CFeeRate::GetFeePerK
CAmount GetFeePerK() const
Return the fee in satoshis for a size of 1000 bytes.
Definition: feerate.h:56
WalletModel::balanceChanged
void balanceChanged(const interfaces::WalletBalances &balances)
PlatformStyle
Definition: platformstyle.h:13
CDataStream::str
std::string str() const
Definition: streams.h:242
GUIUtil::setupAddressWidget
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
Definition: guiutil.cpp:113
SendCoinsEntry::setAmount
void setAmount(const CAmount &amount)
Definition: sendcoinsentry.cpp:213
interfaces::Wallet::fillPSBT
virtual TransactionError fillPSBT(int sighash_type, bool sign, bool bip32derivs, size_t *n_signed, PartiallySignedTransaction &psbtx, bool &complete)=0
Fill PSBT.
interfaces::Wallet::privateKeysDisabled
virtual bool privateKeysDisabled()=0
addresstablemodel.h
SendCoinsDialog::processSendCoinsReturn
void processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg=QString())
Definition: sendcoinsdialog.cpp:692
SendCoinsDialog::updateSmartFeeLabel
void updateSmartFeeLabel()
Definition: sendcoinsdialog.cpp:825
SynchronizationState::POST_INIT
@ POST_INIT
SendConfirmationDialog::SendConfirmationDialog
SendConfirmationDialog(const QString &title, const QString &text, const QString &informative_text="", const QString &detailed_text="", int secDelay=SEND_CONFIRM_DELAY, const QString &confirmText="", QWidget *parent=nullptr)
Definition: sendcoinsdialog.cpp:1029
SendCoinsDialog::coinControlClipboardQuantity
void coinControlClipboardQuantity()
Definition: sendcoinsdialog.cpp:857
clientmodel.h
ctx
static secp256k1_context * ctx
Definition: tests.c:42
OptionsModel::coinControlFeaturesChanged
void coinControlFeaturesChanged(bool)
SendCoinsRecipient::fSubtractFeeFromAmount
bool fSubtractFeeFromAmount
Definition: sendcoinsrecipient.h:42
SendCoinsEntry::getValue
SendCoinsRecipient getValue()
Definition: sendcoinsentry.cpp:167
SendCoinsDialog::on_buttonMinimizeFee_clicked
void on_buttonMinimizeFee_clicked()
Definition: sendcoinsdialog.cpp:752
PROTOCOL_VERSION
static const int PROTOCOL_VERSION
network protocol versioning
Definition: version.h:12
SendConfirmationDialog::countDownTimer
QTimer countDownTimer
Definition: sendcoinsdialog.h:126
SendCoinsDialog::reject
void reject() override
Definition: sendcoinsdialog.cpp:550