2121#include < chainparams.h>
2222#include < interfaces/node.h>
2323#include < key_io.h>
24- #include < wallet/coincontrol.h>
25- #include < ui_interface.h>
26- #include < txmempool.h>
2724#include < policy/fees.h>
25+ #include < txmempool.h>
26+ #include < ui_interface.h>
27+ #include < wallet/coincontrol.h>
2828#include < wallet/fees.h>
29+ #include < wallet/psbtwallet.h>
2930
3031#include < QFontMetrics>
3132#include < QScrollBar>
@@ -186,6 +187,11 @@ void SendCoinsDialog::setModel(WalletModel *_model)
186187 // set default rbf checkbox state
187188 ui->optInRBF ->setCheckState (Qt::Checked);
188189
190+ if (model->privateKeysDisabled ()) {
191+ ui->sendButton ->setText (tr (" Cr&eate Unsigned" ));
192+ 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));
193+ }
194+
189195 // set the smartfee-sliders default value (wallets default conf.target or last stored value)
190196 QSettings settings;
191197 if (settings.value (" nSmartFeeSliderPosition" ).toInt () != 0 ) {
@@ -305,9 +311,19 @@ void SendCoinsDialog::on_sendButton_clicked()
305311 formatted.append (recipientElement);
306312 }
307313
308- QString questionString = tr (" Are you sure you want to send?" );
314+ QString questionString;
315+ if (model->privateKeysDisabled ()) {
316+ questionString.append (tr (" Do you want to draft this transaction?" ));
317+ } else {
318+ questionString.append (tr (" Are you sure you want to send?" ));
319+ }
320+
309321 questionString.append (" <br /><span style='font-size:10pt;'>" );
310- questionString.append (tr (" Please, review your transaction." ));
322+ if (model->privateKeysDisabled ()) {
323+ 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));
324+ } else {
325+ questionString.append (tr (" Please, review your transaction." ));
326+ }
311327 questionString.append (" </span>%1" );
312328
313329 if (txFee > 0 )
@@ -358,8 +374,9 @@ void SendCoinsDialog::on_sendButton_clicked()
358374 } else {
359375 questionString = questionString.arg (" <br /><br />" + formatted.at (0 ));
360376 }
361-
362- SendConfirmationDialog confirmationDialog (tr (" Confirm send coins" ), questionString, informative_text, detailed_text, SEND_CONFIRM_DELAY, this );
377+ const QString confirmation = model->privateKeysDisabled () ? tr (" Confirm transaction proposal" ) : tr (" Confirm send coins" );
378+ const QString confirmButtonText = model->privateKeysDisabled () ? tr (" Copy PSBT to clipboard" ) : tr (" Send" );
379+ SendConfirmationDialog confirmationDialog (confirmation, questionString, informative_text, detailed_text, SEND_CONFIRM_DELAY, confirmButtonText, this );
363380 confirmationDialog.exec ();
364381 QMessageBox::StandardButton retval = static_cast <QMessageBox::StandardButton>(confirmationDialog.result ());
365382
@@ -369,17 +386,35 @@ void SendCoinsDialog::on_sendButton_clicked()
369386 return ;
370387 }
371388
372- // now send the prepared transaction
373- WalletModel::SendCoinsReturn sendStatus = model->sendCoins (currentTransaction);
374- // process sendStatus and on error generate message shown to user
375- processSendCoinsReturn (sendStatus);
389+ bool send_failure = false ;
390+ if (model->privateKeysDisabled ()) {
391+ CMutableTransaction mtx = CMutableTransaction{*(currentTransaction.getWtx ())};
392+ PartiallySignedTransaction psbtx (mtx);
393+ bool complete = false ;
394+ const TransactionError err = model->wallet ().fillPSBT (psbtx, complete, SIGHASH_ALL, false /* sign */ , true /* bip32derivs */ );
395+ assert (!complete);
396+ assert (err == TransactionError::OK);
397+ // Serialize the PSBT
398+ CDataStream ssTx (SER_NETWORK, PROTOCOL_VERSION);
399+ ssTx << psbtx;
400+ GUIUtil::setClipboard (EncodeBase64 (ssTx.str ()).c_str ());
401+ Q_EMIT message (tr (" PSBT copied" ), " Copied to clipboard" , CClientUIInterface::MSG_INFORMATION);
402+ } else {
403+ // now send the prepared transaction
404+ WalletModel::SendCoinsReturn sendStatus = model->sendCoins (currentTransaction);
405+ // process sendStatus and on error generate message shown to user
406+ processSendCoinsReturn (sendStatus);
376407
377- if (sendStatus.status == WalletModel::OK)
378- {
408+ if (sendStatus.status == WalletModel::OK) {
409+ Q_EMIT coinsSent (currentTransaction.getWtx ()->GetHash ());
410+ } else {
411+ send_failure = true ;
412+ }
413+ }
414+ if (!send_failure) {
379415 accept ();
380416 CoinControlDialog::coinControl ()->UnSelectAll ();
381417 coinControlUpdateLabels ();
382- Q_EMIT coinsSent (currentTransaction.getWtx ()->GetHash ());
383418 }
384419 fNewRecipientAllowed = true ;
385420}
@@ -875,8 +910,8 @@ void SendCoinsDialog::coinControlUpdateLabels()
875910 }
876911}
877912
878- SendConfirmationDialog::SendConfirmationDialog (const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, QWidget* parent)
879- : QMessageBox(parent), secDelay(_secDelay)
913+ SendConfirmationDialog::SendConfirmationDialog (const QString& title, const QString& text, const QString& informative_text, const QString& detailed_text, int _secDelay, const QString& _confirmButtonText, QWidget* parent)
914+ : QMessageBox(parent), secDelay(_secDelay), confirmButtonText(_confirmButtonText)
880915{
881916 setIcon (QMessageBox::Question);
882917 setWindowTitle (title); // On macOS, the window title is ignored (as required by the macOS Guidelines).
@@ -913,11 +948,11 @@ void SendConfirmationDialog::updateYesButton()
913948 if (secDelay > 0 )
914949 {
915950 yesButton->setEnabled (false );
916- yesButton->setText (tr ( " Send " ) + " (" + QString::number (secDelay) + " )" );
951+ yesButton->setText (confirmButtonText + " (" + QString::number (secDelay) + " )" );
917952 }
918953 else
919954 {
920955 yesButton->setEnabled (true );
921- yesButton->setText (tr ( " Send " ) );
956+ yesButton->setText (confirmButtonText );
922957 }
923958}
0 commit comments