From 205bfcdd7bf051440cda231fc49e7f58d8c1a7ee Mon Sep 17 00:00:00 2001 From: Jaquee Date: Thu, 12 Jan 2017 19:57:30 +0100 Subject: [PATCH 1/2] History: Show num of confirmations + unconfirmed payments history: refresh on new block --- components/HistoryTable.qml | 15 ++++++++++++--- main.qml | 11 +++++++++++ src/libwalletqt/TransactionInfo.cpp | 5 +++++ src/libwalletqt/TransactionInfo.h | 2 ++ src/libwalletqt/Wallet.cpp | 6 ++++++ src/libwalletqt/Wallet.h | 1 + src/model/TransactionHistoryModel.cpp | 5 +++++ src/model/TransactionHistoryModel.h | 1 + 8 files changed, 43 insertions(+), 3 deletions(-) diff --git a/components/HistoryTable.qml b/components/HistoryTable.qml index ba956015..711bc289 100644 --- a/components/HistoryTable.qml +++ b/components/HistoryTable.qml @@ -263,9 +263,18 @@ ListView { //elide: Text.ElideRight font.family: "Arial" font.pixelSize: 13 - font.letterSpacing: -1 - color: "#545454" - text: (typeof blockHeight != "undefined")? blockHeight : qsTr("Pending") + translationManager.emptyString + color: (confirmations < 10)? "#FF6C3C" : "#545454" + text: { + if (!isPending) + if(confirmations < 10) + return blockHeight + " " + qsTr("(%1/10 confirmations)").arg(confirmations) + else + return blockHeight + if (!isOut) + return qsTr("UNCONFIRMED") + translationManager.emptyString + return qsTr("PENDING") + translationManager.emptyString + + } } } diff --git a/main.qml b/main.qml index 2cf7c86f..4a8c3f91 100644 --- a/main.qml +++ b/main.qml @@ -208,6 +208,7 @@ ApplicationWindow { currentWallet.newBlock.disconnect(onWalletNewBlock) currentWallet.moneySpent.disconnect(onWalletMoneySent) currentWallet.moneyReceived.disconnect(onWalletMoneyReceived) + currentWallet.unconfirmedMoneyReceived.disconnect(onWalletUnconfirmedMoneyReceived) currentWallet.transactionCreated.disconnect(onTransactionCreated) currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged) middlePanel.paymentClicked.disconnect(handlePayment); @@ -229,6 +230,7 @@ ApplicationWindow { currentWallet.newBlock.connect(onWalletNewBlock) currentWallet.moneySpent.connect(onWalletMoneySent) currentWallet.moneyReceived.connect(onWalletMoneyReceived) + currentWallet.unconfirmedMoneyReceived.connect(onWalletUnconfirmedMoneyReceived) currentWallet.transactionCreated.connect(onTransactionCreated) currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged) middlePanel.paymentClicked.connect(handlePayment); @@ -378,6 +380,10 @@ ApplicationWindow { splashCounter = currHeight leftPanel.progressBar.updateProgress(currHeight,currentWallet.daemonBlockChainTargetHeight()); } + + // Update num of confirmations on history page + // TODO: check performance on big wallets. Maybe no need to refresh full history? + currentWallet.history.refresh() } function onWalletMoneyReceived(txId, amount) { @@ -386,6 +392,11 @@ ApplicationWindow { currentWallet.history.refresh() // this will refresh model } + function onWalletUnconfirmedMoneyReceived(txId, amount) { + // refresh history + currentWallet.history.refresh() + } + function onWalletMoneySent(txId, amount) { // refresh transaction history here currentWallet.refresh() diff --git a/src/libwalletqt/TransactionInfo.cpp b/src/libwalletqt/TransactionInfo.cpp index ed73a29f..71df2b02 100644 --- a/src/libwalletqt/TransactionInfo.cpp +++ b/src/libwalletqt/TransactionInfo.cpp @@ -46,6 +46,11 @@ quint64 TransactionInfo::blockHeight() const return m_pimpl->blockHeight(); } +quint64 TransactionInfo::confirmations() const +{ + return m_pimpl->confirmations(); +} + QString TransactionInfo::hash() const { return QString::fromStdString(m_pimpl->hash()); diff --git a/src/libwalletqt/TransactionInfo.h b/src/libwalletqt/TransactionInfo.h index 6d9fc270..30418b88 100644 --- a/src/libwalletqt/TransactionInfo.h +++ b/src/libwalletqt/TransactionInfo.h @@ -18,6 +18,7 @@ class TransactionInfo : public QObject Q_PROPERTY(QString displayAmount READ displayAmount) Q_PROPERTY(QString fee READ fee) Q_PROPERTY(quint64 blockHeight READ blockHeight) + Q_PROPERTY(quint64 confirmations READ confirmations) Q_PROPERTY(QString hash READ hash) Q_PROPERTY(QDateTime timestamp READ timestamp) Q_PROPERTY(QString date READ date) @@ -42,6 +43,7 @@ public: QString displayAmount() const; QString fee() const; quint64 blockHeight() const; + quint64 confirmations() const; //! transaction_id QString hash() const; QDateTime timestamp() const; diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 5bf75788..62c71110 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -44,6 +44,12 @@ public: emit m_wallet->moneyReceived(QString::fromStdString(txId), amount); } + virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) + { + qDebug() << __FUNCTION__; + emit m_wallet->unconfirmedMoneyReceived(QString::fromStdString(txId), amount); + } + virtual void newBlock(uint64_t height) { // qDebug() << __FUNCTION__; diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 24bdc15b..9f9ed3e1 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -206,6 +206,7 @@ signals: void moneySpent(const QString &txId, quint64 amount); void moneyReceived(const QString &txId, quint64 amount); + void unconfirmedMoneyReceived(const QString &txId, quint64 amount); void newBlock(quint64 height); void historyModelChanged() const; diff --git a/src/model/TransactionHistoryModel.cpp b/src/model/TransactionHistoryModel.cpp index 9aed10ce..2e232259 100644 --- a/src/model/TransactionHistoryModel.cpp +++ b/src/model/TransactionHistoryModel.cpp @@ -81,6 +81,10 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const result = tInfo->blockHeight(); } break; + + case TransactionConfirmationsRole: + result = tInfo->confirmations(); + break; case TransactionHashRole: result = tInfo->hash(); break; @@ -125,6 +129,7 @@ QHash TransactionHistoryModel::roleNames() const roleNames.insert(TransactionAtomicAmountRole, "atomicAmount"); roleNames.insert(TransactionFeeRole, "fee"); roleNames.insert(TransactionBlockHeightRole, "blockHeight"); + roleNames.insert(TransactionConfirmationsRole, "confirmations"); roleNames.insert(TransactionHashRole, "hash"); roleNames.insert(TransactionTimeStampRole, "timeStamp"); roleNames.insert(TransactionPaymentIdRole, "paymentId"); diff --git a/src/model/TransactionHistoryModel.h b/src/model/TransactionHistoryModel.h index 1b349914..449d8003 100644 --- a/src/model/TransactionHistoryModel.h +++ b/src/model/TransactionHistoryModel.h @@ -25,6 +25,7 @@ public: TransactionDisplayAmountRole, TransactionFeeRole, TransactionBlockHeightRole, + TransactionConfirmationsRole, TransactionHashRole, TransactionTimeStampRole, TransactionPaymentIdRole, From ad5115ac3c478d8cb8a4e040f9cc064e826a7af6 Mon Sep 17 00:00:00 2001 From: Jaquee Date: Fri, 13 Jan 2017 23:21:58 +0100 Subject: [PATCH 2/2] Add estimated time countdown for locked balance --- LeftPanel.qml | 4 +++- main.qml | 24 ++++++++++++++++-------- pages/AddressBook.qml | 2 +- src/libwalletqt/TransactionHistory.cpp | 24 ++++++++++++++++++++++-- src/libwalletqt/TransactionHistory.h | 7 +++++++ 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/LeftPanel.qml b/LeftPanel.qml index d33b2aff..65dbadad 100644 --- a/LeftPanel.qml +++ b/LeftPanel.qml @@ -39,6 +39,7 @@ Rectangle { property alias balanceText: balanceText.text property alias networkStatus : networkStatus property alias progressBar : progressBar + property alias minutesToUnlockTxt: unlockedBalanceLabel.text signal dashboardClicked() signal historyClicked() @@ -154,7 +155,8 @@ Rectangle { } Label { - text: qsTr("Unlocked balance") + translationManager.emptyString + id: unlockedBalanceLabel + text: qsTr("Unlocked balance") anchors.left: parent.left anchors.leftMargin: 50 tipText: qsTr("Test tip 2

line 2") + translationManager.emptyString diff --git a/main.qml b/main.qml index 4a8c3f91..3144a70e 100644 --- a/main.qml +++ b/main.qml @@ -61,6 +61,10 @@ ApplicationWindow { property int maxWindowHeight: (Screen.height < 900)? 720 : 800; property bool daemonRunning: false property alias toolTip: toolTip + property string walletName + property bool viewOnly: false + property bool foundNewBlock: false + property int timeToUnlock: 0 // true if wallet ever synchronized property bool walletInitialized : false @@ -293,6 +297,15 @@ ApplicationWindow { console.log(">>> wallet updated") middlePanel.unlockedBalanceText = leftPanel.unlockedBalanceText = walletManager.displayAmount(currentWallet.unlockedBalance); middlePanel.balanceText = leftPanel.balanceText = walletManager.displayAmount(currentWallet.balance); + console.log("time to unlock: ", currentWallet.history.minutesToUnlock); + // Update history if new block found since last update and balance is locked. + if(foundNewBlock && currentWallet.history.locked) { + foundNewBlock = false; + console.log("New block found - updating history") + currentWallet.history.refresh() + timeToUnlock = currentWallet.history.minutesToUnlock + leftPanel.minutesToUnlockTxt = (timeToUnlock > 0)? qsTr("Unlocked balance (~%1 min)").arg(timeToUnlock) : qsTr("Unlocked balance"); + } } function onWalletRefresh() { @@ -337,13 +350,11 @@ ApplicationWindow { } } - // initialize transaction history once wallet is initializef first time; if (!walletInitialized) { currentWallet.history.refresh() walletInitialized = true - } - + } onWalletUpdate(); } @@ -370,7 +381,6 @@ ApplicationWindow { function onWalletNewBlock(blockHeight) { - // Update progress bar var currHeight = blockHeight //fast refresh until restoreHeight is reached @@ -380,10 +390,7 @@ ApplicationWindow { splashCounter = currHeight leftPanel.progressBar.updateProgress(currHeight,currentWallet.daemonBlockChainTargetHeight()); } - - // Update num of confirmations on history page - // TODO: check performance on big wallets. Maybe no need to refresh full history? - currentWallet.history.refresh() + foundNewBlock = true; } function onWalletMoneyReceived(txId, amount) { @@ -394,6 +401,7 @@ ApplicationWindow { function onWalletUnconfirmedMoneyReceived(txId, amount) { // refresh history + console.log("unconfirmed money found") currentWallet.history.refresh() } diff --git a/pages/AddressBook.qml b/pages/AddressBook.qml index 8d8be0a7..11086b99 100644 --- a/pages/AddressBook.qml +++ b/pages/AddressBook.qml @@ -138,7 +138,7 @@ Rectangle { if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Address) informationPopup.text = qsTr("Invalid address") else if(currentWallet.addressBook.errorCode() === AddressBook.Invalid_Payment_Id) - informationPopup.text = qsTr("Invalid Payment ID") + informationPopup.text = currentWallet.addressBook.errorString() else informationPopup.text = qsTr("Can't create entry") diff --git a/src/libwalletqt/TransactionHistory.cpp b/src/libwalletqt/TransactionHistory.cpp index b2c5cebe..9cd22bee 100644 --- a/src/libwalletqt/TransactionHistory.cpp +++ b/src/libwalletqt/TransactionHistory.cpp @@ -31,7 +31,9 @@ QList TransactionHistory::getAll() const QDateTime firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones) - + quint64 lastTxHeight = 0; + m_locked = false; + m_minutesToUnlock = 0; TransactionHistory * parent = const_cast(this); for (const auto i : m_pimpl->getAll()) { TransactionInfo * ti = new TransactionInfo(i, parent); @@ -43,6 +45,14 @@ QList TransactionHistory::getAll() const if (ti->timestamp() <= firstDateTime) { firstDateTime = ti->timestamp(); } + // store last tx height + if (ti->confirmations() < 10 && ti->blockHeight() >= lastTxHeight ){ + lastTxHeight = ti->blockHeight(); + // TODO: Fetch block time and confirmations needed from wallet2? + m_minutesToUnlock = (10 - ti->confirmations()) * 2; + m_locked = true; + } + } emit refreshFinished(); @@ -81,9 +91,19 @@ QDateTime TransactionHistory::lastDateTime() const return m_lastDateTime; } +quint64 TransactionHistory::minutesToUnlock() const +{ + return m_minutesToUnlock; +} + +bool TransactionHistory::TransactionHistory::locked() const +{ + return m_locked; +} + TransactionHistory::TransactionHistory(Monero::TransactionHistory *pimpl, QObject *parent) - : QObject(parent), m_pimpl(pimpl) + : QObject(parent), m_pimpl(pimpl), m_minutesToUnlock(0), m_locked(false) { m_firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block m_lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones) diff --git a/src/libwalletqt/TransactionHistory.h b/src/libwalletqt/TransactionHistory.h index 7ded833c..0c8bfc9d 100644 --- a/src/libwalletqt/TransactionHistory.h +++ b/src/libwalletqt/TransactionHistory.h @@ -17,6 +17,8 @@ class TransactionHistory : public QObject Q_PROPERTY(int count READ count) Q_PROPERTY(QDateTime firstDateTime READ firstDateTime NOTIFY firstDateTimeChanged) Q_PROPERTY(QDateTime lastDateTime READ lastDateTime NOTIFY lastDateTimeChanged) + Q_PROPERTY(int minutesToUnlock READ minutesToUnlock) + Q_PROPERTY(bool locked READ locked) public: Q_INVOKABLE TransactionInfo *transaction(int index); @@ -26,6 +28,8 @@ public: quint64 count() const; QDateTime firstDateTime() const; QDateTime lastDateTime() const; + quint64 minutesToUnlock() const; + bool locked() const; signals: void refreshStarted() const; @@ -45,6 +49,9 @@ private: mutable QList m_tinfo; mutable QDateTime m_firstDateTime; mutable QDateTime m_lastDateTime; + mutable int m_minutesToUnlock; + // history contains locked transfers + mutable bool m_locked; };