diff --git a/main.qml b/main.qml index ba5f5ea4..9ff1f1a0 100644 --- a/main.qml +++ b/main.qml @@ -1002,11 +1002,21 @@ ApplicationWindow { ", address: ", address, ", message: ", message); - var result; + function spendProofFallback(txid, result){ + if (!result || result.indexOf("error|") === 0) { + currentWallet.getSpendProofAsync(txid, message, txProofComputed); + } else { + txProofComputed(txid, result); + } + } + if (address.length > 0) - result = currentWallet.getTxProof(txid, address, message); - if (!result || result.indexOf("error|") === 0) - result = currentWallet.getSpendProof(txid, message); + currentWallet.getTxProofAsync(txid, address, message, spendProofFallback); + else + spendProofFallback(txid, null); + } + + function txProofComputed(txid, result){ informationPopup.title = qsTr("Payment proof") + translationManager.emptyString; if (result.indexOf("error|") === 0) { var errorString = result.split("|")[1]; diff --git a/pages/History.qml b/pages/History.qml index a63887c7..4ce053a7 100644 --- a/pages/History.qml +++ b/pages/History.qml @@ -1099,17 +1099,13 @@ Rectangle { MoneroComponents.TextPlain { font.family: MoneroComponents.Style.fontRegular.name font.pixelSize: 15 - text: { - var txKey = currentWallet.getTxKey(hash) - if(txKey) return txKey; - else return "-" - } - + text: qsTr("Click to reveal") color: MoneroComponents.Style.defaultFontColor anchors.verticalCenter: parent.verticalCenter + state: "txkey_hidden" MouseArea { - state: "copyable" + state: "copyable_txkey" anchors.fill: parent hoverEnabled: true onEntered: parent.color = MoneroComponents.Style.orange @@ -1200,6 +1196,7 @@ Rectangle { if(res[i].containsMouse === true){ if(res[i].state === 'copyable' && res[i].parent.hasOwnProperty('text')) toClipboard(res[i].parent.text); if(res[i].state === 'copyable_address') root.toClipboard(address); + if(res[i].state === 'copyable_txkey') root.getTxKey(hash, res[i]); if(res[i].state === 'set_tx_note') root.editDescription(hash); if(res[i].state === 'details') root.showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex); if(res[i].state === 'proof') root.showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex); @@ -1577,8 +1574,18 @@ Rectangle { } } + function getTxKey(hash, elem){ + if (elem.parent.state != 'ready'){ + currentWallet.getTxKeyAsync(hash, function(hash, txKey) { + elem.parent.text = txKey ? txKey : '-'; + elem.parent.state = 'ready'; + }); + } + + toClipboard(elem.parent.text); + } + function showTxDetails(hash, paymentId, destinations, subaddrAccount, subaddrIndex){ - var tx_key = currentWallet.getTxKey(hash) var tx_note = currentWallet.getUserNote(hash) var rings = currentWallet.getRings(hash) var address_label = subaddrIndex == 0 ? (qsTr("Primary address") + translationManager.emptyString) : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex) @@ -1586,10 +1593,12 @@ Rectangle { if (rings) rings = rings.replace(/\|/g, '\n') - informationPopup.title = qsTr("Transaction details") + translationManager.emptyString; - informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label); - informationPopup.onCloseCallback = null - informationPopup.open(); + currentWallet.getTxKeyAsync(hash, function(hash, tx_key) { + informationPopup.title = qsTr("Transaction details") + translationManager.emptyString; + informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label); + informationPopup.onCloseCallback = null + informationPopup.open(); + }); } function showTxProof(hash, paymentId, destinations, subaddrAccount, subaddrIndex){ diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 629106da..ff0ada14 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -662,6 +662,25 @@ QString Wallet::getTxKey(const QString &txid) const return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString())); } +void Wallet::getTxKeyAsync(const QString &txid, const QJSValue &ref) +{ + QFuture future = QtConcurrent::run(this, &Wallet::getTxKey, txid); + auto watcher = new QFutureWatcher(this); + + connect(watcher, &QFutureWatcher::finished, + this, [watcher, txid, ref]() { + QFuture future = watcher->future(); + watcher->deleteLater(); + + auto txKey = future.result(); + if (ref.isCallable()){ + QJSValue cb(ref); + cb.call(QJSValueList {txid, txKey}); + } + }); + watcher->setFuture(future); +} + QString Wallet::checkTxKey(const QString &txid, const QString &tx_key, const QString &address) { uint64_t received; @@ -680,6 +699,25 @@ QString Wallet::getTxProof(const QString &txid, const QString &address, const QS return QString::fromStdString(result); } +void Wallet::getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &ref) +{ + QFuture future = QtConcurrent::run(this, &Wallet::getTxProof, txid, address, message); + auto watcher = new QFutureWatcher(this); + + connect(watcher, &QFutureWatcher::finished, + this, [watcher, txid, ref]() { + QFuture future = watcher->future(); + watcher->deleteLater(); + + auto proof = future.result(); + if (ref.isCallable()){ + QJSValue cb(ref); + cb.call(QJSValueList {txid, proof}); + } + }); + watcher->setFuture(future); +} + QString Wallet::checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature) { bool good; @@ -699,6 +737,25 @@ Q_INVOKABLE QString Wallet::getSpendProof(const QString &txid, const QString &me return QString::fromStdString(result); } +void Wallet::getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &ref) +{ + QFuture future = QtConcurrent::run(this, &Wallet::getSpendProof, txid, message); + auto watcher = new QFutureWatcher(this); + + connect(watcher, &QFutureWatcher::finished, + this, [watcher, txid, ref]() { + QFuture future = watcher->future(); + watcher->deleteLater(); + + auto proof = future.result(); + if (ref.isCallable()){ + QJSValue cb(ref); + cb.call(QJSValueList {txid, proof}); + } + }); + watcher->setFuture(future); +} + Q_INVOKABLE QString Wallet::checkSpendProof(const QString &txid, const QString &message, const QString &signature) const { bool good; diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index ba12d1de..f3726e91 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here; @@ -289,10 +290,13 @@ public: Q_INVOKABLE bool setUserNote(const QString &txid, const QString ¬e); Q_INVOKABLE QString getUserNote(const QString &txid) const; Q_INVOKABLE QString getTxKey(const QString &txid) const; + Q_INVOKABLE void getTxKeyAsync(const QString &txid, const QJSValue &ref); Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address); Q_INVOKABLE QString getTxProof(const QString &txid, const QString &address, const QString &message) const; + Q_INVOKABLE void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &ref); Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature); Q_INVOKABLE QString getSpendProof(const QString &txid, const QString &message) const; + Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &ref); Q_INVOKABLE QString checkSpendProof(const QString &txid, const QString &message, const QString &signature) const; // Rescan spent outputs Q_INVOKABLE bool rescanSpent();