diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -150,6 +150,7 @@ QAction *signMessageAction = nullptr; QAction *verifyMessageAction = nullptr; QAction *m_load_psbt_action = nullptr; + QAction *m_load_psbt_clipboard_action = nullptr; QAction *aboutAction = nullptr; QAction *receiveCoinsAction = nullptr; QAction *receiveCoinsMenuAction = nullptr; @@ -300,8 +301,8 @@ void gotoSignMessageTab(QString addr = ""); /** Show Sign/Verify Message dialog and switch to verify message tab */ void gotoVerifyMessageTab(QString addr = ""); - /** Show load Partially Signed Bitcoin Transaction dialog */ - void gotoLoadPSBT(); + /** Load Partially Signed Bitcoin Transaction from file or clipboard */ + void gotoLoadPSBT(bool from_clipboard = false); /** Show open dialog */ void openClicked(); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -363,6 +363,10 @@ m_load_psbt_action = new QAction(tr("&Load PSBT from file..."), this); m_load_psbt_action->setStatusTip( tr("Load Partially Signed Bitcoin Transaction")); + m_load_psbt_clipboard_action = + new QAction(tr("Load PSBT from clipboard..."), this); + m_load_psbt_clipboard_action->setStatusTip( + tr("Load Partially Signed Bitcoin Transaction from clipboard")); openRPCConsoleAction = new QAction(tr("&Debug window"), this); openRPCConsoleAction->setStatusTip( @@ -447,6 +451,8 @@ [this] { gotoVerifyMessageTab(); }); connect(m_load_psbt_action, &QAction::triggered, [this] { gotoLoadPSBT(); }); + connect(m_load_psbt_clipboard_action, &QAction::triggered, + [this] { gotoLoadPSBT(true); }); connect(usedSendingAddressesAction, &QAction::triggered, walletFrame, &WalletFrame::usedSendingAddresses); connect(usedReceivingAddressesAction, &QAction::triggered, walletFrame, @@ -538,6 +544,7 @@ file->addAction(signMessageAction); file->addAction(verifyMessageAction); file->addAction(m_load_psbt_action); + file->addAction(m_load_psbt_clipboard_action); file->addSeparator(); } file->addAction(quitAction); @@ -990,9 +997,9 @@ walletFrame->gotoVerifyMessageTab(addr); } } -void BitcoinGUI::gotoLoadPSBT() { +void BitcoinGUI::gotoLoadPSBT(bool from_clipboard) { if (walletFrame) { - walletFrame->gotoLoadPSBT(); + walletFrame->gotoLoadPSBT(from_clipboard); } } #endif // ENABLE_WALLET diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -84,7 +84,7 @@ void gotoVerifyMessageTab(QString addr = ""); /** Load Partially Signed Bitcoin Transaction */ - void gotoLoadPSBT(); + void gotoLoadPSBT(bool from_clipboard = false); /** Encrypt the wallet */ void encryptWallet(); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -200,10 +200,10 @@ } } -void WalletFrame::gotoLoadPSBT() { +void WalletFrame::gotoLoadPSBT(bool from_clipboard) { WalletView *walletView = currentWalletView(); if (walletView) { - walletView->gotoLoadPSBT(); + walletView->gotoLoadPSBT(from_clipboard); } } diff --git a/src/qt/walletview.h b/src/qt/walletview.h --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -88,7 +88,7 @@ /** Show Sign/Verify Message dialog and switch to verify message tab */ void gotoVerifyMessageTab(QString addr = ""); /** Load Partially Signed Bitcoin Transaction */ - void gotoLoadPSBT(); + void gotoLoadPSBT(bool from_clipboard = false); /** * Show incoming transaction notification for new transactions. diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -27,6 +27,8 @@ #include #include +#include +#include #include #include #include @@ -239,28 +241,43 @@ } } -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; +void WalletView::gotoLoadPSBT(bool from_clipboard) { + std::string dataStr; + + if (from_clipboard) { + std::string raw = QApplication::clipboard()->text().toStdString(); + bool invalid; + dataStr = DecodeBase64(raw, &invalid); + if (invalid) { + Q_EMIT message( + tr("Error"), + tr("Unable to decode PSBT from clipboard (invalid base64)"), + CClientUIInterface::MSG_ERROR); + return; + } + } else { + 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); + dataStr = std::string(std::istreambuf_iterator{in}, {}); } - std::ifstream in(filename.toLocal8Bit().data(), std::ios::binary); - std::string dataStr(std::istreambuf_iterator{in}, {}); std::string error; PartiallySignedTransaction psbtx; if (!DecodeRawPSBT(psbtx, dataStr, error)) { Q_EMIT message(tr("Error"), - tr("Unable to decode PSBT file") + "\n" + + tr("Unable to decode PSBT") + "\n" + QString::fromStdString(error), CClientUIInterface::MSG_ERROR); return;