diff options
Diffstat (limited to 'src/qt/walletview.cpp')
-rw-r--r-- | src/qt/walletview.cpp | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index bdcb82e06b..d0eca1a25b 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -4,6 +4,9 @@ #include <qt/walletview.h> +#include <node/psbt.h> +#include <node/transaction.h> +#include <policy/policy.h> #include <qt/addressbookpage.h> #include <qt/askpassphrasedialog.h> #include <qt/clientmodel.h> @@ -20,6 +23,7 @@ #include <interfaces/node.h> #include <ui_interface.h> +#include <util/strencodings.h> #include <QAction> #include <QActionGroup> @@ -197,6 +201,80 @@ void WalletView::gotoVerifyMessageTab(QString addr) signVerifyMessageDialog->setAddress_VM(addr); } +void WalletView::gotoLoadPSBT() +{ + QString filename = GUIUtil::getOpenFileName(this, + tr("Load Transaction Data"), QString(), + tr("Partially Signed Transaction (*.psbt)"), nullptr); + if (filename.isEmpty()) return; + if (GetFileSize(filename.toLocal8Bit().data(), MAX_FILE_SIZE_PSBT) == MAX_FILE_SIZE_PSBT) { + Q_EMIT message(tr("Error"), tr("PSBT file must be smaller than 100 MiB"), CClientUIInterface::MSG_ERROR); + return; + } + std::ifstream in(filename.toLocal8Bit().data(), std::ios::binary); + std::string data(std::istreambuf_iterator<char>{in}, {}); + + std::string error; + PartiallySignedTransaction psbtx; + if (!DecodeRawPSBT(psbtx, data, error)) { + Q_EMIT message(tr("Error"), tr("Unable to decode PSBT file") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR); + return; + } + + CMutableTransaction mtx; + bool complete = false; + PSBTAnalysis analysis = AnalyzePSBT(psbtx); + QMessageBox msgBox; + msgBox.setText("PSBT"); + switch (analysis.next) { + case PSBTRole::CREATOR: + case PSBTRole::UPDATER: + msgBox.setInformativeText("PSBT is incomplete. Copy to clipboard for manual inspection?"); + break; + case PSBTRole::SIGNER: + msgBox.setInformativeText("Transaction needs more signatures. Copy to clipboard?"); + break; + case PSBTRole::FINALIZER: + case PSBTRole::EXTRACTOR: + complete = FinalizeAndExtractPSBT(psbtx, mtx); + if (complete) { + msgBox.setInformativeText(tr("Would you like to send this transaction?")); + } else { + // The analyzer missed something, e.g. if there are final_scriptSig/final_scriptWitness + // but with invalid signatures. + msgBox.setInformativeText(tr("There was an unexpected problem processing the PSBT. Copy to clipboard for manual inspection?")); + } + } + + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::Cancel); + switch (msgBox.exec()) { + case QMessageBox::Yes: { + if (complete) { + std::string err_string; + CTransactionRef tx = MakeTransactionRef(mtx); + + TransactionError result = BroadcastTransaction(*clientModel->node().context(), tx, err_string, DEFAULT_MAX_RAW_TX_FEE_RATE.GetFeePerK(), /* relay */ true, /* wait_callback */ false); + if (result == TransactionError::OK) { + Q_EMIT message(tr("Success"), tr("Broadcasted transaction sucessfully."), CClientUIInterface::MSG_INFORMATION | CClientUIInterface::MODAL); + } else { + Q_EMIT message(tr("Error"), QString::fromStdString(err_string), CClientUIInterface::MSG_ERROR); + } + } else { + // 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); + return; + } + } + case QMessageBox::Cancel: + break; + default: + assert(false); + } +} + bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient) { return sendCoinsPage->handlePaymentRequest(recipient); |