@@ -281,6 +281,8 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa
281281 }
282282
283283 // prepare transaction for getting txFee earlier
284+ // Create unsigned transaction to support creating unsigned PSBTs.
285+ // Signing is deferred until the user clicks "Send".
284286 m_current_transaction = std::make_unique<WalletModelTransaction>(recipients);
285287 WalletModel::SendCoinsReturn prepareStatus;
286288
@@ -357,7 +359,7 @@ bool SendCoinsDialog::PrepareSendText(QString& question_string, QString& informa
357359
358360 // append transaction size
359361 // : When reviewing a newly created PSBT (via Send flow), the transaction fee is shown, with "virtual size" of the transaction displayed for context
360- question_string.append (" (" + tr (" %1 kvB" , " PSBT transaction creation" ).arg ((double )m_current_transaction->getTransactionSize () / 1000 , 0 , ' g' , 3 ) + " ): " );
362+ question_string.append (" (" + tr (" %1 kvB (unsigned) " , " PSBT transaction creation" ).arg ((double )m_current_transaction->getTransactionSize () / 1000 , 0 , ' g' , 3 ) + " ): " );
361363
362364 // append transaction fee value
363365 question_string.append (" <span style='color:#aa0000; font-weight:bold;'>" );
@@ -515,6 +517,12 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
515517 presentPSBT (psbtx);
516518 } else {
517519 // "Send" clicked
520+ WalletModel::UnlockContext ctx (model->requestUnlock ());
521+ if (!ctx.isValid ()) {
522+ fNewRecipientAllowed = true ;
523+ return ;
524+ }
525+
518526 assert (!model->wallet ().privateKeysDisabled () || model->wallet ().hasExternalSigner ());
519527 bool broadcast = true ;
520528 if (model->wallet ().hasExternalSigner ()) {
@@ -540,6 +548,24 @@ void SendCoinsDialog::sendButtonClicked([[maybe_unused]] bool checked)
540548 presentPSBT (psbtx);
541549 }
542550 }
551+ } else {
552+ // Sign the transaction now that the user has confirmed they want to send.
553+ CMutableTransaction mtx = CMutableTransaction{*(m_current_transaction->getWtx ())};
554+ PartiallySignedTransaction psbtx (mtx);
555+ bool complete = false ;
556+ // Fill and sign the PSBT
557+ const auto err{model->wallet ().fillPSBT (std::nullopt , /* sign=*/ true , /* bip32derivs=*/ false , /* n_signed=*/ nullptr , psbtx, complete)};
558+ if (err || !complete) {
559+ Q_EMIT message (tr (" Send Coins" ), tr (" Failed to sign transaction." ),
560+ CClientUIInterface::MSG_ERROR );
561+ send_failure = true ;
562+ broadcast = false ;
563+ } else {
564+ // Extract the signed transaction
565+ CHECK_NONFATAL (FinalizeAndExtractPSBT (psbtx, mtx));
566+ const CTransactionRef tx = MakeTransactionRef (mtx);
567+ m_current_transaction->setWtx (tx);
568+ }
543569 }
544570
545571 // Broadcast the transaction, unless an external signer was used and it
0 commit comments