diff --git a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml index 90db00268c..7506b66d01 100644 --- a/interface/resources/qml/hifi/commerce/wallet/Wallet.qml +++ b/interface/resources/qml/hifi/commerce/wallet/Wallet.qml @@ -176,6 +176,7 @@ Rectangle { id: walletChoice; proceedFunction: function (isReset) { console.log(isReset ? "Reset wallet." : "Trying again with new wallet."); + Commerce.setSoftReset(); if (isReset) { walletResetSetup(); } else { @@ -795,7 +796,7 @@ Rectangle { var timestamp = new Date(); walletSetup.startingTimestamp = timestamp; walletSetup.setupAttemptID = generateUUID(); - UserActivityLogger.commerceWalletSetupStarted(timestamp, setupAttemptID, walletSetup.setupFlowVersion, walletSetup.referrer ? walletSetup.referrer : "wallet app", + UserActivityLogger.commerceWalletSetupStarted(timestamp, walletSetup.setupAttemptID, walletSetup.setupFlowVersion, walletSetup.referrer ? walletSetup.referrer : "wallet app", (AddressManager.placename || AddressManager.hostname || '') + (AddressManager.pathname ? AddressManager.pathname.match(/\/[^\/]+/)[0] : '')); } // diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 41fb8a2ced..82ebf283de 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -101,7 +101,7 @@ void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, cons signedSend("transaction", transactionString, hfc_key, "buy", "buySuccess", "buyFailure", controlled_failure); } -bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key) { +bool Ledger::receiveAt(const QString& hfc_key, const QString& signing_key) { auto accountManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { qCWarning(commerce) << "Cannot set receiveAt when not logged in."; @@ -110,7 +110,7 @@ bool Ledger::receiveAt(const QString& hfc_key, const QString& old_key) { return false; // We know right away that we will fail, so tell the caller. } - signedSend("public_key", hfc_key.toUtf8(), old_key, "receive_at", "receiveAtSuccess", "receiveAtFailure"); + signedSend("public_key", hfc_key.toUtf8(), signing_key, "receive_at", "receiveAtSuccess", "receiveAtFailure"); return true; // Note that there may still be an asynchronous signal of failure that callers might be interested in. } @@ -248,6 +248,7 @@ void Ledger::accountSuccess(QNetworkReply& reply) { auto iv = QByteArray::fromBase64(data["iv"].toString().toUtf8()); auto ckey = QByteArray::fromBase64(data["ckey"].toString().toUtf8()); QString remotePublicKey = data["public_key"].toString(); + bool isOverride = wallet->wasSoftReset(); wallet->setSalt(salt); wallet->setIv(iv); @@ -255,9 +256,13 @@ void Ledger::accountSuccess(QNetworkReply& reply) { QString keyStatus = "ok"; QStringList localPublicKeys = wallet->listPublicKeys(); - if (remotePublicKey.isEmpty()) { + qDebug() << "FIXME isOverride:" << isOverride; + qDebug() << "remote:" << remotePublicKey; + qDebug() << " local:" << (localPublicKeys.isEmpty() ? "" : localPublicKeys.first()); + if (remotePublicKey.isEmpty() || isOverride) { if (!localPublicKeys.isEmpty()) { - receiveAt(localPublicKeys.first(), ""); + QString key = localPublicKeys.first(); + receiveAt(key, key); } } else { if (localPublicKeys.isEmpty()) { diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index ac9fe950d9..703ebda2dc 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -26,7 +26,7 @@ class Ledger : public QObject, public Dependency { public: void buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure = false); - bool receiveAt(const QString& hfc_key, const QString& old_key); + bool receiveAt(const QString& hfc_key, const QString& signing_key); void balance(const QStringList& keys); void inventory(const QStringList& keys); void history(const QStringList& keys, const int& pageNumber); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 8969d18cf5..6d4497999b 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -127,6 +127,11 @@ void QmlCommerce::changePassphrase(const QString& oldPassphrase, const QString& } } +void QmlCommerce::setSoftReset() { + auto wallet = DependencyManager::get(); + wallet->setSoftReset(); +} + void QmlCommerce::setPassphrase(const QString& passphrase) { auto wallet = DependencyManager::get(); wallet->setPassphrase(passphrase); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 2b520f8377..a2f5820b20 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -63,6 +63,7 @@ protected: Q_INVOKABLE void chooseSecurityImage(const QString& imageFile); Q_INVOKABLE void setPassphrase(const QString& passphrase); Q_INVOKABLE void changePassphrase(const QString& oldPassphrase, const QString& newPassphrase); + Q_INVOKABLE void setSoftReset(); Q_INVOKABLE void buy(const QString& assetId, int cost, const bool controlledFailure = false); Q_INVOKABLE void balance(); diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index a53f3cba56..fad82115d6 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -61,13 +61,20 @@ QString keyFilePath() { } bool Wallet::copyKeyFileFrom(const QString& pathname) { QString existing = getKeyFilePath(); + qCDebug(commerce) << "Old keyfile" << existing; if (!existing.isEmpty()) { - if (!QFile::rename(existing, existing + ".backup" + QDateTime::currentDateTime().toString(Qt::ISODate))) { - qCCritical(commerce) << "Unable to backup" << existing; + QString backup = QString(existing).insert(existing.indexOf(KEY_FILE) - 1, + QDateTime::currentDateTime().toString(Qt::ISODate).replace(":", "")); + qCDebug(commerce) << "Renaming old keyfile to" << backup; + if (!QFile::rename(existing, backup)) { + qCCritical(commerce) << "Unable to backup" << existing << "to" << backup; return false; } } - return QFile::copy(pathname, keyFilePath()); + QString destination = keyFilePath(); + bool result = QFile::copy(pathname, destination); + qCDebug(commerce) << "copy" << pathname << "to" << destination << "=>" << result; + return result; } // use the cached _passphrase if it exists, otherwise we need to prompt @@ -544,13 +551,14 @@ bool Wallet::generateKeyPair() { QString key = keyPair.first->toBase64(); _publicKeys.push_back(key); qCDebug(commerce) << "public key:" << key; + _isOverridingServer = false; // It's arguable whether we want to change the receiveAt every time, but: // 1. It's certainly needed the first time, when createIfNeeded answers true. // 2. It is maximally private, and we can step back from that later if desired. // 3. It maximally exercises all the machinery, so we are most likely to surface issues now. auto ledger = DependencyManager::get(); - return ledger->receiveAt(key, ""); + return ledger->receiveAt(key, key); } QStringList Wallet::listPublicKeys() { diff --git a/interface/src/commerce/Wallet.h b/interface/src/commerce/Wallet.h index 9abc1d871b..d771f404e5 100644 --- a/interface/src/commerce/Wallet.h +++ b/interface/src/commerce/Wallet.h @@ -49,6 +49,8 @@ public: bool getPassphraseIsCached() { return !(_passphrase->isEmpty()); } bool walletIsAuthenticatedWithPassphrase(); bool changePassphrase(const QString& newPassphrase); + void setSoftReset() { _isOverridingServer = true; } + bool wasSoftReset() { bool was = _isOverridingServer; _isOverridingServer = false; return was; } void getWalletStatus(); enum WalletStatus { @@ -76,6 +78,7 @@ private: QByteArray _iv; QByteArray _ckey; QString* _passphrase { new QString("") }; + bool _isOverridingServer { false }; bool writeWallet(const QString& newPassphrase = QString("")); void updateImageProvider();