21
21
#include < chainparams.h>
22
22
#include < interfaces/node.h>
23
23
#include < key_io.h>
24
- #include < wallet/coincontrol.h>
25
- #include < ui_interface.h>
26
- #include < txmempool.h>
27
24
#include < policy/fees.h>
25
+ #include < txmempool.h>
26
+ #include < ui_interface.h>
27
+ #include < wallet/coincontrol.h>
28
28
#include < wallet/fees.h>
29
+ #include < wallet/psbtwallet.h>
29
30
30
31
#include < QFontMetrics>
31
32
#include < QScrollBar>
@@ -186,6 +187,11 @@ void SendCoinsDialog::setModel(WalletModel *_model)
186
187
// set default rbf checkbox state
187
188
ui->optInRBF ->setCheckState (Qt::Checked);
188
189
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
+
189
195
// set the smartfee-sliders default value (wallets default conf.target or last stored value)
190
196
QSettings settings;
191
197
if (settings.value (" nSmartFeeSliderPosition" ).toInt () != 0 ) {
@@ -305,9 +311,19 @@ void SendCoinsDialog::on_sendButton_clicked()
305
311
formatted.append (recipientElement);
306
312
}
307
313
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
+
309
321
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
+ }
311
327
questionString.append (" </span>%1" );
312
328
313
329
if (txFee > 0 )
@@ -358,8 +374,9 @@ void SendCoinsDialog::on_sendButton_clicked()
358
374
} else {
359
375
questionString = questionString.arg (" <br /><br />" + formatted.at (0 ));
360
376
}
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 );
363
380
confirmationDialog.exec ();
364
381
QMessageBox::StandardButton retval = static_cast <QMessageBox::StandardButton>(confirmationDialog.result ());
365
382
@@ -369,17 +386,35 @@ void SendCoinsDialog::on_sendButton_clicked()
369
386
return ;
370
387
}
371
388
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);
376
407
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) {
379
415
accept ();
380
416
CoinControlDialog::coinControl ()->UnSelectAll ();
381
417
coinControlUpdateLabels ();
382
- Q_EMIT coinsSent (currentTransaction.getWtx ()->GetHash ());
383
418
}
384
419
fNewRecipientAllowed = true ;
385
420
}
@@ -875,8 +910,8 @@ void SendCoinsDialog::coinControlUpdateLabels()
875
910
}
876
911
}
877
912
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)
880
915
{
881
916
setIcon (QMessageBox::Question);
882
917
setWindowTitle (title); // On macOS, the window title is ignored (as required by the macOS Guidelines).
@@ -913,11 +948,11 @@ void SendConfirmationDialog::updateYesButton()
913
948
if (secDelay > 0 )
914
949
{
915
950
yesButton->setEnabled (false );
916
- yesButton->setText (tr ( " Send " ) + " (" + QString::number (secDelay) + " )" );
951
+ yesButton->setText (confirmButtonText + " (" + QString::number (secDelay) + " )" );
917
952
}
918
953
else
919
954
{
920
955
yesButton->setEnabled (true );
921
- yesButton->setText (tr ( " Send " ) );
956
+ yesButton->setText (confirmButtonText );
922
957
}
923
958
}
0 commit comments