mirror of
				https://git.wownero.com/wowlet/wowlet.git
				synced 2024-08-15 01:03:14 +00:00 
			
		
		
		
	Merge pull request 'Libwalletqt: integrate changes from upstream' (#63) from tobtoht/feather:syncing into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/63
This commit is contained in:
		
						commit
						63e2ba799d
					
				
					 4 changed files with 226 additions and 114 deletions
				
			
		| 
						 | 
				
			
			@ -2,6 +2,11 @@
 | 
			
		|||
// Copyright (c) 2014-2020, The Monero Project.
 | 
			
		||||
 | 
			
		||||
#include "Wallet.h"
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <thread>
 | 
			
		||||
 | 
			
		||||
#include "PendingTransaction.h"
 | 
			
		||||
#include "UnsignedTransaction.h"
 | 
			
		||||
#include "TransactionHistory.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +32,8 @@
 | 
			
		|||
#include <QVector>
 | 
			
		||||
#include <QMutexLocker>
 | 
			
		||||
 | 
			
		||||
#include "utils/ScopeGuard.h"
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
    static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
 | 
			
		||||
    static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +43,7 @@ namespace {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
Wallet::Wallet(QObject * parent)
 | 
			
		||||
    : Wallet(nullptr, parent)
 | 
			
		||||
        : Wallet(nullptr, parent)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -100,6 +107,19 @@ bool Wallet::disconnected() const
 | 
			
		|||
    return m_disconnected;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Wallet::refreshing() const
 | 
			
		||||
{
 | 
			
		||||
    return m_refreshing;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::refreshingSet(bool value)
 | 
			
		||||
{
 | 
			
		||||
    if (m_refreshing.exchange(value) != value)
 | 
			
		||||
    {
 | 
			
		||||
        emit refreshingChanged();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::setConnectionStatus(ConnectionStatus value)
 | 
			
		||||
{
 | 
			
		||||
    if (m_connectionStatus == value)
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +131,7 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
 | 
			
		|||
    emit connectionStatusChanged(m_connectionStatus);
 | 
			
		||||
 | 
			
		||||
    bool disconnected = m_connectionStatus == Wallet::ConnectionStatus_Connecting ||
 | 
			
		||||
        m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
 | 
			
		||||
                        m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
 | 
			
		||||
 | 
			
		||||
    if (m_disconnected != disconnected)
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -120,6 +140,29 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Wallet::getProxyAddress() const
 | 
			
		||||
{
 | 
			
		||||
    QMutexLocker locker(&m_proxyMutex);
 | 
			
		||||
    return m_proxyAddress;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::setProxyAddress(QString address)
 | 
			
		||||
{
 | 
			
		||||
    m_scheduler.run([this, address] {
 | 
			
		||||
        {
 | 
			
		||||
            QMutexLocker locker(&m_proxyMutex);
 | 
			
		||||
 | 
			
		||||
            if (!m_walletImpl->setProxy(address.toStdString()))
 | 
			
		||||
            {
 | 
			
		||||
                qCritical() << "failed to set proxy" << address;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            m_proxyAddress = address;
 | 
			
		||||
        }
 | 
			
		||||
        emit proxyAddressChanged();
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Wallet::synchronized() const
 | 
			
		||||
{
 | 
			
		||||
    return m_walletImpl->synchronized();
 | 
			
		||||
| 
						 | 
				
			
			@ -145,20 +188,18 @@ QString Wallet::path() const
 | 
			
		|||
    return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->path()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//void Wallet::storeAsync(const QVariant &callback, const QString &path /* = "" */)
 | 
			
		||||
//void Wallet::storeAsync(const QJSValue &callback, const QString &path /* = "" */)
 | 
			
		||||
//{
 | 
			
		||||
//    const auto future = m_scheduler.run(
 | 
			
		||||
//        [this, path] {
 | 
			
		||||
//            QMutexLocker locker(&m_storeMutex);
 | 
			
		||||
 | 
			
		||||
//            return QVariantList({m_walletImpl->store(path.toStdString())});
 | 
			
		||||
//        },
 | 
			
		||||
//        callback);
 | 
			
		||||
//            [this, path] {
 | 
			
		||||
//                QMutexLocker locker(&m_asyncMutex);
 | 
			
		||||
//
 | 
			
		||||
//                return QJSValueList({m_walletImpl->store(path.toStdString())});
 | 
			
		||||
//            },
 | 
			
		||||
//            callback);
 | 
			
		||||
//    if (!future.first)
 | 
			
		||||
//    {
 | 
			
		||||
//        QVariant(callback).call(QVariantList({false}));
 | 
			
		||||
//        QJSValue(callback).call(QJSValueList({false}));
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +208,7 @@ void Wallet::store(const QString &path)
 | 
			
		|||
    m_walletImpl->store(path.toStdString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
 | 
			
		||||
bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight, const QString& proxyAddress)
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "init non async";
 | 
			
		||||
    if (isRecovering){
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +222,20 @@ bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 uppe
 | 
			
		|||
    if (isRecovering || isRecoveringFromDevice) {
 | 
			
		||||
        m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
 | 
			
		||||
    }
 | 
			
		||||
    m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString());
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        QMutexLocker locker(&m_proxyMutex);
 | 
			
		||||
 | 
			
		||||
        if (!m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), false, false, proxyAddress.toStdString()))
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        m_proxyAddress = proxyAddress;
 | 
			
		||||
    }
 | 
			
		||||
    emit proxyAddressChanged();
 | 
			
		||||
 | 
			
		||||
    setTrustedDaemon(trustedDaemon);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -193,17 +247,24 @@ void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemon
 | 
			
		|||
    m_daemonPassword = daemonPassword;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight)
 | 
			
		||||
void Wallet::initAsync(
 | 
			
		||||
        const QString &daemonAddress,
 | 
			
		||||
        bool trustedDaemon /* = false */,
 | 
			
		||||
        quint64 upperTransactionLimit /* = 0 */,
 | 
			
		||||
        bool isRecovering /* = false */,
 | 
			
		||||
        bool isRecoveringFromDevice /* = false */,
 | 
			
		||||
        quint64 restoreHeight /* = 0 */,
 | 
			
		||||
        const QString &proxyAddress /* = "" */)
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "initAsync: " + daemonAddress;
 | 
			
		||||
    const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight] {
 | 
			
		||||
        bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight);
 | 
			
		||||
    const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress] {
 | 
			
		||||
        bool success = init(daemonAddress, trustedDaemon, upperTransactionLimit, isRecovering, isRecoveringFromDevice, restoreHeight, proxyAddress);
 | 
			
		||||
        if (success)
 | 
			
		||||
        {
 | 
			
		||||
            emit walletCreationHeightChanged();
 | 
			
		||||
            qDebug() << "init async finished - starting refresh";
 | 
			
		||||
            connected(true);
 | 
			
		||||
            m_walletImpl->startRefresh();
 | 
			
		||||
            startRefresh();
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    if (future.first)
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +433,7 @@ quint64 Wallet::daemonBlockChainHeight() const
 | 
			
		|||
    // cache daemon blockchain height for some time (60 seconds by default)
 | 
			
		||||
 | 
			
		||||
    if (m_daemonBlockChainHeight == 0
 | 
			
		||||
            || m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl) {
 | 
			
		||||
        || m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl) {
 | 
			
		||||
        m_daemonBlockChainHeight = m_walletImpl->daemonBlockChainHeight();
 | 
			
		||||
        m_daemonBlockChainHeightTime.restart();
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -382,7 +443,7 @@ quint64 Wallet::daemonBlockChainHeight() const
 | 
			
		|||
quint64 Wallet::daemonBlockChainTargetHeight() const
 | 
			
		||||
{
 | 
			
		||||
    if (m_daemonBlockChainTargetHeight <= 1
 | 
			
		||||
            || m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) {
 | 
			
		||||
        || m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl) {
 | 
			
		||||
        m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
 | 
			
		||||
 | 
			
		||||
        // Target height is set to 0 if daemon is synced.
 | 
			
		||||
| 
						 | 
				
			
			@ -406,42 +467,37 @@ bool Wallet::importKeyImages(const QString& path)
 | 
			
		|||
    return m_walletImpl->importKeyImages(path.toStdString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Wallet::refresh()
 | 
			
		||||
bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
 | 
			
		||||
{
 | 
			
		||||
    bool result = m_walletImpl->refresh();
 | 
			
		||||
    m_history->refresh(currentSubaddressAccount());
 | 
			
		||||
    m_subaddress->refresh(currentSubaddressAccount());
 | 
			
		||||
    m_coins->refresh(currentSubaddressAccount());
 | 
			
		||||
    m_subaddressAccount->getAll();
 | 
			
		||||
    if (result)
 | 
			
		||||
        emit updated();
 | 
			
		||||
    return result;
 | 
			
		||||
    refreshingSet(true);
 | 
			
		||||
    const auto cleanup = sg::make_scope_guard([this]() noexcept {
 | 
			
		||||
        refreshingSet(false);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        QMutexLocker locker(&m_asyncMutex);
 | 
			
		||||
 | 
			
		||||
        bool result = m_walletImpl->refresh();
 | 
			
		||||
        if (historyAndSubaddresses)
 | 
			
		||||
        {
 | 
			
		||||
            m_history->refresh(currentSubaddressAccount());
 | 
			
		||||
            m_subaddress->refresh(currentSubaddressAccount());
 | 
			
		||||
            m_subaddressAccount->getAll();
 | 
			
		||||
        }
 | 
			
		||||
        if (result)
 | 
			
		||||
                emit updated();
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::refreshAsync()
 | 
			
		||||
void Wallet::startRefresh()
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "refresh async";
 | 
			
		||||
    m_walletImpl->refreshAsync();
 | 
			
		||||
    m_refreshEnabled = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::setAutoRefreshInterval(int seconds)
 | 
			
		||||
void Wallet::pauseRefresh()
 | 
			
		||||
{
 | 
			
		||||
    m_walletImpl->setAutoRefreshInterval(seconds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Wallet::autoRefreshInterval() const
 | 
			
		||||
{
 | 
			
		||||
    return m_walletImpl->autoRefreshInterval();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::startRefresh() const
 | 
			
		||||
{
 | 
			
		||||
    m_walletImpl->startRefresh();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::pauseRefresh() const
 | 
			
		||||
{
 | 
			
		||||
    m_walletImpl->pauseRefresh();
 | 
			
		||||
    m_refreshEnabled = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -450,15 +506,15 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
 | 
			
		|||
{
 | 
			
		||||
    std::set<uint32_t> subaddr_indices;
 | 
			
		||||
    Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
 | 
			
		||||
                dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
 | 
			
		||||
                static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
 | 
			
		||||
            dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
 | 
			
		||||
            static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
 | 
			
		||||
    PendingTransaction * result = new PendingTransaction(ptImpl,0);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id,
 | 
			
		||||
                               quint64 amount, quint32 mixin_count,
 | 
			
		||||
                               PendingTransaction::Priority priority)
 | 
			
		||||
                                    quint64 amount, quint32 mixin_count,
 | 
			
		||||
                                    PendingTransaction::Priority priority)
 | 
			
		||||
{
 | 
			
		||||
    m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority] {
 | 
			
		||||
        PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority);
 | 
			
		||||
| 
						 | 
				
			
			@ -471,15 +527,15 @@ PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const
 | 
			
		|||
{
 | 
			
		||||
    std::set<uint32_t> subaddr_indices;
 | 
			
		||||
    Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
 | 
			
		||||
                dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
 | 
			
		||||
                static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
 | 
			
		||||
            dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
 | 
			
		||||
            static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
 | 
			
		||||
    PendingTransaction * result = new PendingTransaction(ptImpl, this);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
 | 
			
		||||
                               quint32 mixin_count,
 | 
			
		||||
                               PendingTransaction::Priority priority)
 | 
			
		||||
                                       quint32 mixin_count,
 | 
			
		||||
                                       PendingTransaction::Priority priority)
 | 
			
		||||
{
 | 
			
		||||
    m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority] {
 | 
			
		||||
        PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority);
 | 
			
		||||
| 
						 | 
				
			
			@ -556,7 +612,6 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
 | 
			
		|||
    delete t;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// @ TODO: QJSValue could probably be QVARIANT
 | 
			
		||||
//void Wallet::estimateTransactionFeeAsync(const QString &destination,
 | 
			
		||||
//                                         quint64 amount,
 | 
			
		||||
//                                         PendingTransaction::Priority priority,
 | 
			
		||||
| 
						 | 
				
			
			@ -564,8 +619,8 @@ void Wallet::disposeTransaction(UnsignedTransaction *t)
 | 
			
		|||
//{
 | 
			
		||||
//    m_scheduler.run([this, destination, amount, priority] {
 | 
			
		||||
//        const uint64_t fee = m_walletImpl->estimateTransactionFee(
 | 
			
		||||
//            {std::make_pair(destination.toStdString(), amount)},
 | 
			
		||||
//            static_cast<Monero::PendingTransaction::Priority>(priority));
 | 
			
		||||
//                {std::make_pair(destination.toStdString(), amount)},
 | 
			
		||||
//                static_cast<Monero::PendingTransaction::Priority>(priority));
 | 
			
		||||
//        return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
 | 
			
		||||
//    }, callback);
 | 
			
		||||
//}
 | 
			
		||||
| 
						 | 
				
			
			@ -683,17 +738,17 @@ bool Wallet::setCacheAttribute(const QString &key, const QString &val)
 | 
			
		|||
 | 
			
		||||
bool Wallet::setUserNote(const QString &txid, const QString ¬e)
 | 
			
		||||
{
 | 
			
		||||
  return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
 | 
			
		||||
    return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Wallet::getUserNote(const QString &txid) const
 | 
			
		||||
{
 | 
			
		||||
  return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString()));
 | 
			
		||||
    return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Wallet::getTxKey(const QString &txid) const
 | 
			
		||||
{
 | 
			
		||||
  return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString()));
 | 
			
		||||
    return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//void Wallet::getTxKeyAsync(const QString &txid, const QJSValue &callback)
 | 
			
		||||
| 
						 | 
				
			
			@ -831,7 +886,6 @@ bool Wallet::verifySignedMessage(const QString &message, const QString &address,
 | 
			
		|||
    return m_walletImpl->verifySignedMessage(message.toStdString(), address.toStdString(), signature.toStdString());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id, uint64_t &amount, QString &tx_description, QString &recipient_name, QVector<QString> &unknown_parameters, QString &error)
 | 
			
		||||
{
 | 
			
		||||
   std::string s_address, s_payment_id, s_tx_description, s_recipient_name, s_error;
 | 
			
		||||
| 
						 | 
				
			
			@ -852,6 +906,8 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
 | 
			
		|||
 | 
			
		||||
bool Wallet::rescanSpent()
 | 
			
		||||
{
 | 
			
		||||
    QMutexLocker locker(&m_asyncMutex);
 | 
			
		||||
 | 
			
		||||
    return m_walletImpl->rescanSpent();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -928,8 +984,8 @@ QString Wallet::getRing(const QString &key_image)
 | 
			
		|||
    {
 | 
			
		||||
        if (!ring.isEmpty())
 | 
			
		||||
            ring = ring + " ";
 | 
			
		||||
	QString s;
 | 
			
		||||
	s.setNum(out);
 | 
			
		||||
        QString s;
 | 
			
		||||
        s.setNum(out);
 | 
			
		||||
        ring = ring + s;
 | 
			
		||||
    }
 | 
			
		||||
    return ring;
 | 
			
		||||
| 
						 | 
				
			
			@ -949,8 +1005,8 @@ QString Wallet::getRings(const QString &txid)
 | 
			
		|||
        for (uint64_t out: cring.second)
 | 
			
		||||
        {
 | 
			
		||||
            ring = ring + " ";
 | 
			
		||||
	    QString s;
 | 
			
		||||
	    s.setNum(out);
 | 
			
		||||
            QString s;
 | 
			
		||||
            s.setNum(out);
 | 
			
		||||
            ring = ring + s;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -964,9 +1020,9 @@ bool Wallet::setRing(const QString &key_image, const QString &ring, bool relativ
 | 
			
		|||
    foreach(QString str, strOuts)
 | 
			
		||||
    {
 | 
			
		||||
        uint64_t out;
 | 
			
		||||
	bool ok;
 | 
			
		||||
	out = str.toULong(&ok);
 | 
			
		||||
	if (ok)
 | 
			
		||||
        bool ok;
 | 
			
		||||
        out = str.toULong(&ok);
 | 
			
		||||
        if (ok)
 | 
			
		||||
            cring.push_back(out);
 | 
			
		||||
    }
 | 
			
		||||
    return m_walletImpl->setRing(key_image.toStdString(), cring, relative);
 | 
			
		||||
| 
						 | 
				
			
			@ -1001,26 +1057,28 @@ void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
Wallet::Wallet(Monero::Wallet *w, QObject *parent)
 | 
			
		||||
    : QObject(parent)
 | 
			
		||||
    , m_walletImpl(w)
 | 
			
		||||
    , m_history(nullptr)
 | 
			
		||||
    , m_historyModel(nullptr)
 | 
			
		||||
    , m_addressBook(nullptr)
 | 
			
		||||
    , m_addressBookModel(nullptr)
 | 
			
		||||
    , m_daemonBlockChainHeight(0)
 | 
			
		||||
    , m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
 | 
			
		||||
    , m_daemonBlockChainTargetHeight(0)
 | 
			
		||||
    , m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
 | 
			
		||||
    , m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
 | 
			
		||||
    , m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
 | 
			
		||||
    , m_disconnected(true)
 | 
			
		||||
    , m_currentSubaddressAccount(0)
 | 
			
		||||
    , m_subaddress(nullptr)
 | 
			
		||||
    , m_subaddressModel(nullptr)
 | 
			
		||||
    , m_subaddressAccount(nullptr)
 | 
			
		||||
    , m_subaddressAccountModel(nullptr)
 | 
			
		||||
    , m_coinsModel(nullptr)
 | 
			
		||||
    , m_scheduler(this)
 | 
			
		||||
        : QObject(parent)
 | 
			
		||||
        , m_walletImpl(w)
 | 
			
		||||
        , m_history(nullptr)
 | 
			
		||||
        , m_historyModel(nullptr)
 | 
			
		||||
        , m_addressBook(nullptr)
 | 
			
		||||
        , m_addressBookModel(nullptr)
 | 
			
		||||
        , m_daemonBlockChainHeight(0)
 | 
			
		||||
        , m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
 | 
			
		||||
        , m_daemonBlockChainTargetHeight(0)
 | 
			
		||||
        , m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
 | 
			
		||||
        , m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
 | 
			
		||||
        , m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
 | 
			
		||||
        , m_disconnected(true)
 | 
			
		||||
        , m_currentSubaddressAccount(0)
 | 
			
		||||
        , m_subaddress(nullptr)
 | 
			
		||||
        , m_subaddressModel(nullptr)
 | 
			
		||||
        , m_subaddressAccount(nullptr)
 | 
			
		||||
        , m_subaddressAccountModel(nullptr)
 | 
			
		||||
        , m_coinsModel(nullptr)
 | 
			
		||||
        , m_refreshEnabled(false)
 | 
			
		||||
        , m_refreshing(false)
 | 
			
		||||
        , m_scheduler(this)
 | 
			
		||||
{
 | 
			
		||||
    m_history = new TransactionHistory(m_walletImpl->history(), this);
 | 
			
		||||
    m_addressBook = new AddressBook(m_walletImpl->addressBook(), this);
 | 
			
		||||
| 
						 | 
				
			
			@ -1038,11 +1096,13 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
 | 
			
		|||
    m_connectionStatusRunning = false;
 | 
			
		||||
    m_daemonUsername = "";
 | 
			
		||||
    m_daemonPassword = "";
 | 
			
		||||
 | 
			
		||||
    startRefreshThread();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Wallet::~Wallet()
 | 
			
		||||
{
 | 
			
		||||
    qDebug() << "~Wallet: Closing wallet";
 | 
			
		||||
    qDebug("~Wallet: Closing wallet");
 | 
			
		||||
 | 
			
		||||
    m_scheduler.shutdownWaitForFinished();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1072,3 +1132,32 @@ Wallet::~Wallet()
 | 
			
		|||
    m_walletListener = NULL;
 | 
			
		||||
    qDebug("m_walletImpl deleted");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Wallet::startRefreshThread()
 | 
			
		||||
{
 | 
			
		||||
    const auto future = m_scheduler.run([this] {
 | 
			
		||||
        static constexpr const size_t refreshIntervalSec = 10;
 | 
			
		||||
        static constexpr const size_t intervalResolutionMs = 100;
 | 
			
		||||
 | 
			
		||||
        auto last = std::chrono::steady_clock::now();
 | 
			
		||||
        while (!m_scheduler.stopping())
 | 
			
		||||
        {
 | 
			
		||||
            if (m_refreshEnabled)
 | 
			
		||||
            {
 | 
			
		||||
                const auto now = std::chrono::steady_clock::now();
 | 
			
		||||
                const auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - last).count();
 | 
			
		||||
                if (elapsed >= refreshIntervalSec)
 | 
			
		||||
                {
 | 
			
		||||
                    refresh(false);
 | 
			
		||||
                    last = std::chrono::steady_clock::now();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            std::this_thread::sleep_for(std::chrono::milliseconds(intervalResolutionMs));
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
    if (!future.first)
 | 
			
		||||
    {
 | 
			
		||||
        throw std::runtime_error("failed to start auto refresh thread");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,6 @@
 | 
			
		|||
#include <QObject>
 | 
			
		||||
#include <QMutex>
 | 
			
		||||
#include <QList>
 | 
			
		||||
//#include <QJSValue>
 | 
			
		||||
#include <QtConcurrent/QtConcurrent>
 | 
			
		||||
 | 
			
		||||
#include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
 | 
			
		||||
| 
						 | 
				
			
			@ -20,14 +19,13 @@
 | 
			
		|||
#include "WalletListenerImpl.h"
 | 
			
		||||
 | 
			
		||||
namespace Monero {
 | 
			
		||||
struct Wallet; // forward declaration
 | 
			
		||||
    struct Wallet; // forward declaration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TransactionHistory;
 | 
			
		||||
class TransactionHistoryModel;
 | 
			
		||||
class TransactionHistoryProxyModel;
 | 
			
		||||
class TransactionHistorySortFilterModel;
 | 
			
		||||
class AddressBook;
 | 
			
		||||
class AddressBookModel;
 | 
			
		||||
class Subaddress;
 | 
			
		||||
| 
						 | 
				
			
			@ -50,13 +48,14 @@ struct TxProofResult {
 | 
			
		|||
 | 
			
		||||
class Wallet : public QObject, public PassprasePrompter
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
Q_OBJECT
 | 
			
		||||
    Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
 | 
			
		||||
    Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
 | 
			
		||||
    Q_PROPERTY(QString seed READ getSeed)
 | 
			
		||||
    Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
 | 
			
		||||
    Q_PROPERTY(Status status READ status)
 | 
			
		||||
    Q_PROPERTY(NetworkType::Type nettype READ nettype)
 | 
			
		||||
    Q_PROPERTY(ConnectionStatus connected READ connected)
 | 
			
		||||
//    Q_PROPERTY(ConnectionStatus connected READ connected)
 | 
			
		||||
    Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged)
 | 
			
		||||
    Q_PROPERTY(bool synchronized READ synchronized)
 | 
			
		||||
    Q_PROPERTY(QString errorString READ errorString)
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +75,7 @@ class Wallet : public QObject, public PassprasePrompter
 | 
			
		|||
    Q_PROPERTY(QString secretSpendKey READ getSecretSpendKey)
 | 
			
		||||
    Q_PROPERTY(QString publicSpendKey READ getPublicSpendKey)
 | 
			
		||||
    Q_PROPERTY(QString daemonLogPath READ getDaemonLogPath CONSTANT)
 | 
			
		||||
    Q_PROPERTY(QString proxyAddress READ getProxyAddress WRITE setProxyAddress NOTIFY proxyAddressChanged)
 | 
			
		||||
    Q_PROPERTY(quint64 walletCreationHeight READ getWalletCreationHeight WRITE setWalletCreationHeight NOTIFY walletCreationHeightChanged)
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -120,6 +120,7 @@ public:
 | 
			
		|||
    //! returns true if wallet was ever synchronized
 | 
			
		||||
    bool synchronized() const;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    //! returns last operation's error message
 | 
			
		||||
    QString errorString() const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -138,7 +139,14 @@ public:
 | 
			
		|||
   // Q_INVOKABLE void storeAsync(const QJSValue &callback, const QString &path = "");
 | 
			
		||||
 | 
			
		||||
    //! initializes wallet asynchronously
 | 
			
		||||
    Q_INVOKABLE void initAsync(const QString &daemonAddress, bool trustedDaemon = false, quint64 upperTransactionLimit = 0, bool isRecovering = false, bool isRecoveringFromDevice = false, quint64 restoreHeight = 0);
 | 
			
		||||
    Q_INVOKABLE void initAsync(
 | 
			
		||||
            const QString &daemonAddress,
 | 
			
		||||
            bool trustedDaemon = false,
 | 
			
		||||
            quint64 upperTransactionLimit = 0,
 | 
			
		||||
            bool isRecovering = false,
 | 
			
		||||
            bool isRecoveringFromDevice = false,
 | 
			
		||||
            quint64 restoreHeight = 0,
 | 
			
		||||
            const QString &proxyAddress = "");
 | 
			
		||||
 | 
			
		||||
    // Set daemon rpc user/pass
 | 
			
		||||
    Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
 | 
			
		||||
| 
						 | 
				
			
			@ -188,20 +196,11 @@ public:
 | 
			
		|||
    Q_INVOKABLE bool importKeyImages(const QString& path);
 | 
			
		||||
 | 
			
		||||
    //! refreshes the wallet
 | 
			
		||||
    Q_INVOKABLE bool refresh();
 | 
			
		||||
 | 
			
		||||
    //! refreshes the wallet asynchronously
 | 
			
		||||
    Q_INVOKABLE void refreshAsync();
 | 
			
		||||
 | 
			
		||||
    //! setup auto-refresh interval in seconds
 | 
			
		||||
    Q_INVOKABLE void setAutoRefreshInterval(int seconds);
 | 
			
		||||
 | 
			
		||||
    //! return auto-refresh interval in seconds
 | 
			
		||||
    Q_INVOKABLE int autoRefreshInterval() const;
 | 
			
		||||
    Q_INVOKABLE bool refresh(bool historyAndSubaddresses = true);
 | 
			
		||||
 | 
			
		||||
    // pause/resume refresh
 | 
			
		||||
    Q_INVOKABLE void startRefresh() const;
 | 
			
		||||
    Q_INVOKABLE void pauseRefresh() const;
 | 
			
		||||
    Q_INVOKABLE void startRefresh();
 | 
			
		||||
    Q_INVOKABLE void pauseRefresh();
 | 
			
		||||
 | 
			
		||||
    //! returns current wallet's block height
 | 
			
		||||
    //! (can be less than daemon's blockchain height when wallet sync in progress)
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +224,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    //! creates transaction with all outputs
 | 
			
		||||
    Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
 | 
			
		||||
                                                       quint32 mixin_count, PendingTransaction::Priority priority);
 | 
			
		||||
                                                          quint32 mixin_count, PendingTransaction::Priority priority);
 | 
			
		||||
 | 
			
		||||
    //! creates async transaction with all outputs
 | 
			
		||||
    Q_INVOKABLE void createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -402,6 +401,8 @@ signals:
 | 
			
		|||
    void connectionStatusChanged(int status) const;
 | 
			
		||||
    void currentSubaddressAccountChanged() const;
 | 
			
		||||
    void disconnectedChanged() const;
 | 
			
		||||
    void proxyAddressChanged() const;
 | 
			
		||||
    void refreshingChanged() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Wallet(QObject * parent = nullptr);
 | 
			
		||||
| 
						 | 
				
			
			@ -409,10 +410,22 @@ private:
 | 
			
		|||
    ~Wallet();
 | 
			
		||||
 | 
			
		||||
    //! initializes wallet
 | 
			
		||||
    bool init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight);
 | 
			
		||||
    bool init(
 | 
			
		||||
            const QString &daemonAddress,
 | 
			
		||||
            bool trustedDaemon,
 | 
			
		||||
            quint64 upperTransactionLimit,
 | 
			
		||||
            bool isRecovering,
 | 
			
		||||
            bool isRecoveringFromDevice,
 | 
			
		||||
            quint64 restoreHeight,
 | 
			
		||||
            const QString& proxyAddress);
 | 
			
		||||
 | 
			
		||||
    bool disconnected() const;
 | 
			
		||||
    bool refreshing() const;
 | 
			
		||||
    void refreshingSet(bool value);
 | 
			
		||||
    void setConnectionStatus(ConnectionStatus value);
 | 
			
		||||
    QString getProxyAddress() const;
 | 
			
		||||
    void setProxyAddress(QString address);
 | 
			
		||||
    void startRefreshThread();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    friend class WalletManager;
 | 
			
		||||
| 
						 | 
				
			
			@ -445,13 +458,17 @@ private:
 | 
			
		|||
    mutable SubaddressAccountModel * m_subaddressAccountModel;
 | 
			
		||||
    Coins * m_coins;
 | 
			
		||||
    mutable CoinsModel * m_coinsModel;
 | 
			
		||||
    QMutex m_asyncMutex;
 | 
			
		||||
    QMutex m_connectionStatusMutex;
 | 
			
		||||
    bool m_connectionStatusRunning;
 | 
			
		||||
    QString m_daemonUsername;
 | 
			
		||||
    QString m_daemonPassword;
 | 
			
		||||
    QString m_proxyAddress;
 | 
			
		||||
    mutable QMutex m_proxyMutex;
 | 
			
		||||
    std::atomic<bool> m_refreshEnabled;
 | 
			
		||||
    std::atomic<bool> m_refreshing;
 | 
			
		||||
    WalletListenerImpl *m_walletListener;
 | 
			
		||||
    FutureScheduler m_scheduler;
 | 
			
		||||
    QMutex m_storeMutex;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,11 @@ QPair<bool, QFuture<void>> FutureScheduler::run(std::function<void()> function)
 | 
			
		|||
//    });
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
bool FutureScheduler::stopping() const noexcept
 | 
			
		||||
{
 | 
			
		||||
    return Stopping;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FutureScheduler::add() noexcept
 | 
			
		||||
{
 | 
			
		||||
    QMutexLocker locker(&Mutex);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    QPair<bool, QFuture<void>> run(std::function<void()> function) noexcept;
 | 
			
		||||
   // QPair<bool, QFuture<QJSValueList>> run(std::function<QJSValueList()> function, const QJSValue &callback);
 | 
			
		||||
   bool stopping() const noexcept;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    bool add() noexcept;
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +63,7 @@ private:
 | 
			
		|||
    size_t Alive;
 | 
			
		||||
    QWaitCondition Condition;
 | 
			
		||||
    QMutex Mutex;
 | 
			
		||||
    bool Stopping;
 | 
			
		||||
    std::atomic<bool> Stopping;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // FUTURE_SCHEDULER_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue