]> Nutra Git (v1) - gamesguru/feather.git/commitdiff
refactor: remove appcontext, cleanup Wallet
authortobtoht <tob@featherwallet.org>
Wed, 1 Mar 2023 02:05:56 +0000 (03:05 +0100)
committertobtoht <tob@featherwallet.org>
Wed, 1 Mar 2023 02:05:56 +0000 (03:05 +0100)
82 files changed:
monero
src/CoinsWidget.cpp
src/CoinsWidget.h
src/ContactsWidget.cpp
src/ContactsWidget.h
src/HistoryWidget.cpp
src/HistoryWidget.h
src/MainWindow.cpp
src/MainWindow.h
src/ReceiveWidget.cpp
src/ReceiveWidget.h
src/SendWidget.cpp
src/SendWidget.h
src/SettingsDialog.cpp
src/SettingsDialog.h
src/WindowManager.cpp
src/WindowManager.h
src/appcontext.cpp [deleted file]
src/appcontext.h [deleted file]
src/assets/tor2/tor [new file with mode: 0755]
src/dialog/AccountSwitcherDialog.cpp
src/dialog/AccountSwitcherDialog.h
src/dialog/DebugInfoDialog.cpp
src/dialog/DebugInfoDialog.h
src/dialog/KeysDialog.cpp
src/dialog/KeysDialog.h
src/dialog/PaymentRequestDialog.cpp
src/dialog/PaymentRequestDialog.h
src/dialog/SeedDialog.cpp
src/dialog/SeedDialog.h
src/dialog/TxBroadcastDialog.cpp
src/dialog/TxBroadcastDialog.h
src/dialog/TxConfAdvDialog.cpp
src/dialog/TxConfAdvDialog.h
src/dialog/TxConfDialog.cpp
src/dialog/TxConfDialog.h
src/dialog/TxImportDialog.cpp
src/dialog/TxImportDialog.h
src/dialog/TxInfoDialog.cpp
src/dialog/TxInfoDialog.h
src/dialog/TxProofDialog.cpp
src/dialog/TxProofDialog.h
src/dialog/ViewOnlyDialog.cpp
src/dialog/ViewOnlyDialog.h
src/dialog/WalletCacheDebugDialog.cpp
src/dialog/WalletCacheDebugDialog.h
src/dialog/WalletInfoDialog.cpp
src/dialog/WalletInfoDialog.h
src/libwalletqt/CMakeLists.txt [deleted file]
src/libwalletqt/Wallet.cpp
src/libwalletqt/Wallet.h
src/libwalletqt/WalletListenerImpl.cpp
src/main.cpp
src/utils/TorManager.cpp
src/utils/TorManager.h
src/utils/nodes.cpp
src/utils/nodes.h
src/utils/xmrig.cpp
src/widgets/CCSWidget.cpp
src/widgets/CCSWidget.h
src/widgets/LocalMoneroWidget.cpp
src/widgets/LocalMoneroWidget.h
src/widgets/NodeWidget.h
src/widgets/TickerWidget.cpp
src/widgets/TickerWidget.h
src/widgets/XMRigWidget.cpp
src/widgets/XMRigWidget.h
src/wizard/PageHardwareDevice.h
src/wizard/PageMenu.h
src/wizard/PageNetwork.h
src/wizard/PageNetworkProxy.h
src/wizard/PageNetworkWebsocket.h
src/wizard/PageOpenWallet.h
src/wizard/PageSetPassword.h
src/wizard/PageSetRestoreHeight.h
src/wizard/PageSetSeedPassphrase.h
src/wizard/PageSetSubaddressLookahead.h
src/wizard/PageWalletFile.h
src/wizard/PageWalletRestoreKeys.cpp
src/wizard/PageWalletRestoreKeys.h
src/wizard/PageWalletRestoreSeed.h
src/wizard/WalletWizard.h

diff --git a/monero b/monero
index f7705c2c6740699a3fa47895473f79c006624559..772d207026dac31f927efa733fda3f73b103e71a 160000 (submodule)
--- a/monero
+++ b/monero
@@ -1 +1 @@
-Subproject commit f7705c2c6740699a3fa47895473f79c006624559
+Subproject commit 772d207026dac31f927efa733fda3f73b103e71a
index 955e7c94684d360f9c4f8a4a49595e5fe46771d4..4833ac8d788a9b6e437d7a16c4fb065a1887e633 100644 (file)
@@ -9,11 +9,12 @@
 #include "dialog/OutputInfoDialog.h"
 #include "dialog/OutputSweepDialog.h"
 #include "utils/Icons.h"
+#include "utils/Utils.h"
 
-CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
+CoinsWidget::CoinsWidget(Wallet *wallet, QWidget *parent)
         : QWidget(parent)
         , ui(new Ui::CoinsWidget)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
         , m_headerMenu(new QMenu(this))
         , m_copyMenu(new QMenu("Copy",this))
 {
@@ -71,7 +72,7 @@ CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
 
     connect(ui->search, &QLineEdit::textChanged, this, &CoinsWidget::setSearchFilter);
 
-    connect(m_ctx.get(), &AppContext::selectedInputsChanged, this, &CoinsWidget::selectCoins);
+    connect(m_wallet, &Wallet::selectedInputsChanged, this, &CoinsWidget::selectCoins);
 }
 
 void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
@@ -84,7 +85,7 @@ void CoinsWidget::setModel(CoinsModel * model, Coins * coins) {
     ui->coins->setColumnHidden(CoinsModel::SpentHeight, true);
     ui->coins->setColumnHidden(CoinsModel::Frozen, true);
 
-    if (!m_ctx->wallet->viewOnly()) {
+    if (!m_wallet->viewOnly()) {
         ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, true);
     } else {
         ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, false);
@@ -188,7 +189,7 @@ void CoinsWidget::spendSelected() {
         keyimages << m_model->entryFromIndex(m_proxyModel->mapToSource(index))->keyImage();
     }
 
-    m_ctx->setSelectedInputs(keyimages);
+    m_wallet->setSelectedInputs(keyimages);
     this->selectCoins(keyimages);
 }
 
@@ -239,7 +240,7 @@ void CoinsWidget::onSweepOutputs() {
     int ret = dialog.exec();
     if (!ret) return;
 
-    m_ctx->onSweepOutputs(keyImages, dialog.address(), dialog.churn(), dialog.outputs());
+    m_wallet->sweepOutputs(keyImages, dialog.address(), dialog.churn(), dialog.outputs());
 }
 
 void CoinsWidget::copy(copyField field) {
@@ -298,18 +299,18 @@ QVector<CoinsInfo*> CoinsWidget::currentEntries() {
 
 void CoinsWidget::freezeCoins(QStringList &pubkeys) {
     for (auto &pubkey : pubkeys) {
-        m_ctx->wallet->coins()->freeze(pubkey);
+        m_wallet->coins()->freeze(pubkey);
     }
-    m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
-    m_ctx->updateBalance();
+    m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
+    m_wallet->updateBalance();
 }
 
 void CoinsWidget::thawCoins(QStringList &pubkeys) {
     for (auto &pubkey : pubkeys) {
-        m_ctx->wallet->coins()->thaw(pubkey);
+        m_wallet->coins()->thaw(pubkey);
     }
-    m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
-    m_ctx->updateBalance();
+    m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
+    m_wallet->updateBalance();
 }
 
 void CoinsWidget::selectCoins(const QStringList &keyimages) {
index f598e984d680cee38c915189e2b23fb36ac39cf2..15d06d5df7c07176ee1359da4f550f88a0c21309 100644 (file)
@@ -8,10 +8,10 @@
 #include <QWidget>
 #include <QSvgWidget>
 
-#include "appcontext.h"
 #include "model/CoinsModel.h"
 #include "model/CoinsProxyModel.h"
 #include "libwalletqt/Coins.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class CoinsWidget;
@@ -22,7 +22,7 @@ class CoinsWidget : public QWidget
 Q_OBJECT
 
 public:
-    explicit CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit CoinsWidget(Wallet *wallet, QWidget *parent = nullptr);
     void setModel(CoinsModel * model, Coins * coins);
     ~CoinsWidget() override;
 
@@ -62,7 +62,7 @@ private:
     };
 
     QScopedPointer<Ui::CoinsWidget> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 
     QMenu *m_contextMenu;
     QMenu *m_headerMenu;
index a438ed45f6c9996fab61dd199e6905c338d86e79..47707f22c2abda15fe575b08da294f089fdf48e1 100644 (file)
@@ -8,13 +8,14 @@
 
 #include "dialog/ContactsDialog.h"
 #include "libwalletqt/AddressBook.h"
+#include "libwalletqt/WalletManager.h"
 #include "model/ModelUtils.h"
 #include "utils/Icons.h"
 
-ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
+ContactsWidget::ContactsWidget(Wallet *wallet, QWidget *parent)
         : QWidget(parent)
         , ui(new Ui::ContactsWidget)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
 {
     ui->setupUi(this);
 
@@ -23,7 +24,7 @@ ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
     ui->searchLayout->addWidget(m_btn_addContact, 0, Qt::AlignRight);
     connect(m_btn_addContact, &QPushButton::clicked, [this]{this->newContact();});
 
-    m_model = m_ctx->wallet->addressBookModel();
+    m_model = m_wallet->addressBookModel();
     m_proxyModel = new AddressBookProxyModel;
     m_proxyModel->setSourceModel(m_model);
     ui->contacts->setModel(m_proxyModel);
@@ -124,17 +125,17 @@ void ContactsWidget::newContact(QString address, QString name)
     address = dialog.getAddress();
     name = dialog.getName();
 
-    bool addressValid = WalletManager::addressValid(address, m_ctx->wallet->nettype());
+    bool addressValid = WalletManager::addressValid(address, m_wallet->nettype());
     if (!addressValid) {
         QMessageBox::warning(this, "Invalid address", "Invalid address");
         return;
     }
 
-    int num_addresses = m_ctx->wallet->addressBook()->count();
+    int num_addresses = m_wallet->addressBook()->count();
     QString address_entry;
     QString name_entry;
     for (int i=0; i<num_addresses; i++) {
-        m_ctx->wallet->addressBook()->getRow(i, [&address_entry, &name_entry](const AddressBookInfo &entry){
+        m_wallet->addressBook()->getRow(i, [&address_entry, &name_entry](const AddressBookInfo &entry){
             address_entry = entry.address();
             name_entry = entry.description();
         });
@@ -151,7 +152,7 @@ void ContactsWidget::newContact(QString address, QString name)
         }
     }
 
-    m_ctx->wallet->addressBook()->addRow(address, "", name);
+    m_wallet->addressBook()->addRow(address, "", name);
 }
 
 void ContactsWidget::deleteContact()
index 704a9efb850c75e269825d3100dc3fbf0cfe8176..27e743a11c39283a73407a96d5144672c7b9a3b8 100644 (file)
@@ -8,9 +8,9 @@
 #include <QWidget>
 #include <QMenu>
 
-#include "appcontext.h"
 #include "model/AddressBookModel.h"
 #include "model/AddressBookProxyModel.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
 class ContactsWidget;
@@ -21,7 +21,7 @@ class ContactsWidget : public QWidget
     Q_OBJECT
 
 public:
-    explicit ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit ContactsWidget(Wallet *wallet, QWidget *parent = nullptr);
     ~ContactsWidget() override;
 
     void setSearchbarVisible(bool visible);
@@ -44,7 +44,7 @@ private slots:
 
 private:
     QScopedPointer<Ui::ContactsWidget> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 
     QAction *m_showFullAddressesAction;
     QMenu *m_rowMenu;
index e2728940bb98777f4bf42646e37acb1acaae75c4..d314563810a8451d7fe583c86bbbd54973d53986 100644 (file)
@@ -6,20 +6,20 @@
 
 #include <QMessageBox>
 
-#include "appcontext.h"
 #include "dialog/TxInfoDialog.h"
 #include "dialog/TxProofDialog.h"
+#include "libwalletqt/WalletManager.h"
 #include "utils/config.h"
 #include "utils/Icons.h"
 #include "WebsocketNotifier.h"
 
-HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
+HistoryWidget::HistoryWidget(Wallet *wallet, QWidget *parent)
         : QWidget(parent)
         , ui(new Ui::HistoryWidget)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
         , m_contextMenu(new QMenu(this))
         , m_copyMenu(new QMenu("Copy", this))
-        , m_model(m_ctx->wallet->historyModel())
+        , m_model(wallet->historyModel())
 {
     ui->setupUi(this);
     m_contextMenu->addMenu(m_copyMenu);
@@ -49,7 +49,7 @@ HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
         ui->syncNotice->hide();
     });
 
-    connect(m_ctx.get(), &AppContext::walletRefreshed, this, &HistoryWidget::onWalletRefreshed);
+    connect(m_wallet, &Wallet::walletRefreshed, this, &HistoryWidget::onWalletRefreshed);
 
     ui->syncNotice->setVisible(config()->get(Config::showHistorySyncNotice).toBool());
     ui->history->setHistoryModel(m_model);
@@ -119,7 +119,7 @@ void HistoryWidget::showTxDetails() {
     auto *tx = ui->history->currentEntry();
     if (!tx) return;
 
-    auto *dialog = new TxInfoDialog(m_ctx, tx, this);
+    auto *dialog = new TxInfoDialog(m_wallet, tx, this);
     connect(dialog, &TxInfoDialog::resendTranscation, [this](const QString &txid){
        emit resendTransaction(txid);
     });
@@ -148,7 +148,7 @@ void HistoryWidget::createTxProof() {
     auto *tx = ui->history->currentEntry();
     if (!tx) return;
 
-    TxProofDialog dialog{this, m_ctx, tx};
+    TxProofDialog dialog{this, m_wallet, tx};
     dialog.getTxKey();
     dialog.exec();
 }
index 6399dd9d3ee3d53bd0356a9febf8d352ad599b71..0ac765ba9356c519707efee748cf0cb445931564 100644 (file)
@@ -7,7 +7,6 @@
 #include <QWidget>
 #include <QMenu>
 
-#include "appcontext.h"
 #include "libwalletqt/Coins.h"
 #include "libwalletqt/Wallet.h"
 #include "model/TransactionHistoryModel.h"
@@ -22,7 +21,7 @@ class HistoryWidget : public QWidget
 Q_OBJECT
 
 public:
-    explicit HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit HistoryWidget(Wallet *wallet, QWidget *parent = nullptr);
     ~HistoryWidget() override;
 
     void setSearchbarVisible(bool visible);
@@ -58,7 +57,7 @@ private:
     void showSyncNoticeMsg();
 
     QScopedPointer<Ui::HistoryWidget> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     QMenu *m_contextMenu;
     QMenu *m_copyMenu;
     TransactionHistoryProxyModel *m_model;
index 1ea4e5167f4debf41c52bba436b5912de11345ce..2b6385113372b2e966838368796783c1a17aca86 100644 (file)
@@ -43,7 +43,9 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
     : QMainWindow(parent)
     , ui(new Ui::MainWindow)
     , m_windowManager(windowManager)
-    , m_ctx(new AppContext(wallet))
+    , m_wallet(wallet)
+    , m_nodes(new Nodes(this, wallet))
+    , m_rpc(new DaemonRpc(this, ""))
 {
     ui->setupUi(this);
 
@@ -55,7 +57,7 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
 
     m_windowCalc = new CalcWindow(this);
     m_splashDialog = new SplashDialog(this);
-    m_accountSwitcherDialog = new AccountSwitcherDialog(m_ctx, this);
+    m_accountSwitcherDialog = new AccountSwitcherDialog(m_wallet, this);
 
     m_updater = QSharedPointer<Updater>(new Updater(this));
 
@@ -81,18 +83,9 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
     connect(m_windowManager, &WindowManager::websocketStatusChanged, this, &MainWindow::onWebsocketStatusChanged);
     this->onWebsocketStatusChanged(!config()->get(Config::disableWebsocket).toBool());
 
-    connect(m_windowManager, &WindowManager::proxySettingsChanged, [this]{
-        m_ctx->onProxySettingsChanged();
-        this->onProxySettingsChanged();
-    });
-    connect(m_windowManager, &WindowManager::updateBalance, m_ctx.data(), &AppContext::updateBalance);
-    connect(m_windowManager, &WindowManager::offlineMode, [this](bool offline){
-       if (!m_ctx->wallet) {
-           return;
-       }
-       m_ctx->wallet->setOffline(offline);
-       this->onConnectionStatusChanged(Wallet::ConnectionStatus_Disconnected);
-    });
+    connect(m_windowManager, &WindowManager::proxySettingsChanged, this, &MainWindow::onProxySettingsChanged);
+    connect(m_windowManager, &WindowManager::updateBalance, m_wallet, &Wallet::updateBalance);
+    connect(m_windowManager, &WindowManager::offlineMode, this, &MainWindow::onOfflineMode);
 
     connect(torManager(), &TorManager::connectionStateChanged, this, &MainWindow::onTorConnectionStateChanged);
     this->onTorConnectionStateChanged(torManager()->torConnected);
@@ -191,20 +184,20 @@ void MainWindow::initWidgets() {
     ui->tabHomeWidget->setCurrentIndex(TabsHome(homeWidget));
 
     // [History]
-    m_historyWidget = new HistoryWidget(m_ctx, this);
+    m_historyWidget = new HistoryWidget(m_wallet, this);
     ui->historyWidgetLayout->addWidget(m_historyWidget);
     connect(m_historyWidget, &HistoryWidget::viewOnBlockExplorer, this, &MainWindow::onViewOnBlockExplorer);
     connect(m_historyWidget, &HistoryWidget::resendTransaction, this, &MainWindow::onResendTransaction);
 
     // [Send]
-    m_sendWidget = new SendWidget(m_ctx, this);
+    m_sendWidget = new SendWidget(m_wallet, this);
     ui->sendWidgetLayout->addWidget(m_sendWidget);
     // --------------
-    m_contactsWidget = new ContactsWidget(m_ctx, this);
+    m_contactsWidget = new ContactsWidget(m_wallet, this);
     ui->contactsWidgetLayout->addWidget(m_contactsWidget);
 
     // [Receive]
-    m_receiveWidget = new ReceiveWidget(m_ctx, this);
+    m_receiveWidget = new ReceiveWidget(m_wallet, this);
     ui->receiveWidgetLayout->addWidget(m_receiveWidget);
     connect(m_receiveWidget, &ReceiveWidget::showTransactions, [this](const QString &text) {
         m_historyWidget->setSearchText(text);
@@ -213,18 +206,18 @@ void MainWindow::initWidgets() {
     connect(m_contactsWidget, &ContactsWidget::fillAddress, m_sendWidget, &SendWidget::fillAddress);
 
     // [Coins]
-    m_coinsWidget = new CoinsWidget(m_ctx, this);
+    m_coinsWidget = new CoinsWidget(m_wallet, this);
     ui->coinsWidgetLayout->addWidget(m_coinsWidget);
 
 #ifdef HAS_LOCALMONERO
-    m_localMoneroWidget = new LocalMoneroWidget(this, m_ctx);
+    m_localMoneroWidget = new LocalMoneroWidget(this, m_wallet);
     ui->localMoneroLayout->addWidget(m_localMoneroWidget);
 #else
     ui->tabWidgetExchanges->setTabVisible(0, false);
 #endif
 
 #ifdef HAS_XMRIG
-    m_xmrig = new XMRigWidget(m_ctx, this);
+    m_xmrig = new XMRigWidget(m_wallet, this);
     ui->xmrRigLayout->addWidget(m_xmrig);
 
     connect(m_xmrig, &XMRigWidget::miningStarted, [this]{ this->updateTitle(); });
@@ -239,7 +232,7 @@ void MainWindow::initWidgets() {
 
     ui->frame_coinControl->setVisible(false);
     connect(ui->btn_resetCoinControl, &QPushButton::clicked, [this]{
-       m_ctx->setSelectedInputs({});
+       m_wallet->setSelectedInputs({});
     });
 
     m_walletUnlockWidget = new WalletUnlockWidget(this);
@@ -276,8 +269,8 @@ void MainWindow::initMenu() {
 
     // [Wallet] -> [Advanced]
     connect(ui->actionStore_wallet,          &QAction::triggered, this, &MainWindow::tryStoreWallet);
-    connect(ui->actionUpdate_balance,        &QAction::triggered, [this]{m_ctx->updateBalance();});
-    connect(ui->actionRefresh_tabs,          &QAction::triggered, [this]{m_ctx->refreshModels();});
+    connect(ui->actionUpdate_balance,        &QAction::triggered, [this]{m_wallet->updateBalance();});
+    connect(ui->actionRefresh_tabs,          &QAction::triggered, [this]{m_wallet->refreshModels();});
     connect(ui->actionRescan_spent,          &QAction::triggered, this, &MainWindow::rescanSpent);
     connect(ui->actionWallet_cache_debug,    &QAction::triggered, this, &MainWindow::showWalletCacheDebugDialog);
 
@@ -399,14 +392,14 @@ void MainWindow::initMenu() {
 
 void MainWindow::initHome() {
     // Ticker widgets
-    m_tickerWidgets.append(new PriceTickerWidget(this, m_ctx, "XMR"));
-    m_tickerWidgets.append(new PriceTickerWidget(this, m_ctx, "BTC"));
-    m_tickerWidgets.append(new RatioTickerWidget(this, m_ctx, "XMR", "BTC"));
+    m_tickerWidgets.append(new PriceTickerWidget(this, m_wallet, "XMR"));
+    m_tickerWidgets.append(new PriceTickerWidget(this, m_wallet, "BTC"));
+    m_tickerWidgets.append(new RatioTickerWidget(this, m_wallet, "XMR", "BTC"));
     for (const auto &widget : m_tickerWidgets) {
         ui->tickerLayout->addWidget(widget);
     }
 
-    m_balanceTickerWidget = new BalanceTickerWidget(this, m_ctx, false);
+    m_balanceTickerWidget = new BalanceTickerWidget(this, m_wallet, false);
     ui->fiatTickerLayout->addWidget(m_balanceTickerWidget);
 
     connect(ui->ccsWidget, &CCSWidget::selected, this, &MainWindow::showSendScreen);
@@ -419,29 +412,56 @@ void MainWindow::initHome() {
 }
 
 void MainWindow::initWalletContext() {
-    connect(m_ctx.get(), &AppContext::balanceUpdated,           this, &MainWindow::onBalanceUpdated);
-    connect(m_ctx.get(), &AppContext::synchronized,             this, &MainWindow::onSynchronized);
-    connect(m_ctx.get(), &AppContext::blockchainSync,           this, &MainWindow::onBlockchainSync);
-    connect(m_ctx.get(), &AppContext::refreshSync,              this, &MainWindow::onRefreshSync);
-    connect(m_ctx.get(), &AppContext::createTransactionError,   this, &MainWindow::onCreateTransactionError);
-    connect(m_ctx.get(), &AppContext::createTransactionSuccess, this, &MainWindow::onCreateTransactionSuccess);
-    connect(m_ctx.get(), &AppContext::transactionCommitted,     this, &MainWindow::onTransactionCommitted);
-    connect(m_ctx.get(), &AppContext::deviceError,              this, &MainWindow::onDeviceError);
-    connect(m_ctx.get(), &AppContext::deviceButtonRequest,      this, &MainWindow::onDeviceButtonRequest);
-    connect(m_ctx.get(), &AppContext::deviceButtonPressed,      this, &MainWindow::onDeviceButtonPressed);
-    connect(m_ctx.get(), &AppContext::initiateTransaction,      this, &MainWindow::onInitiateTransaction);
-    connect(m_ctx.get(), &AppContext::endTransaction,           this, &MainWindow::onEndTransaction);
-    connect(m_ctx.get(), &AppContext::keysCorrupted,            this, &MainWindow::onKeysCorrupted);
-    connect(m_ctx.get(), &AppContext::selectedInputsChanged,    this, &MainWindow::onSelectedInputsChanged);
+    connect(m_wallet, &Wallet::balanceUpdated,           this, &MainWindow::onBalanceUpdated);
+    connect(m_wallet, &Wallet::synchronized,             this, &MainWindow::onSynchronized); //TODO
+    connect(m_wallet, &Wallet::blockchainSync,           this, &MainWindow::onBlockchainSync);
+    connect(m_wallet, &Wallet::refreshSync,              this, &MainWindow::onRefreshSync);
+    connect(m_wallet, &Wallet::createTransactionError,   this, &MainWindow::onCreateTransactionError);
+    connect(m_wallet, &Wallet::createTransactionSuccess, this, &MainWindow::onCreateTransactionSuccess);
+    connect(m_wallet, &Wallet::transactionCommitted,     this, &MainWindow::onTransactionCommitted);
+    connect(m_wallet, &Wallet::initiateTransaction,      this, &MainWindow::onInitiateTransaction);
+    connect(m_wallet, &Wallet::endTransaction,           this, &MainWindow::onEndTransaction);
+    connect(m_wallet, &Wallet::keysCorrupted,            this, &MainWindow::onKeysCorrupted);
+    connect(m_wallet, &Wallet::selectedInputsChanged,    this, &MainWindow::onSelectedInputsChanged);
 
     // Wallet
-    connect(m_ctx->wallet, &Wallet::connectionStatusChanged, [this](int status){
+    connect(m_wallet, &Wallet::connectionStatusChanged, [this](int status){
         // Order is important, first inform UI about a potential disconnect, then reconnect
         this->onConnectionStatusChanged(status);
-        this->m_ctx->nodes->autoConnect();
+        m_nodes->autoConnect();
+    });
+    connect(m_wallet, &Wallet::currentSubaddressAccountChanged, this, &MainWindow::updateTitle);
+    connect(m_wallet, &Wallet::walletPassphraseNeeded, this, &MainWindow::onWalletPassphraseNeeded);
+
+    connect(m_wallet, &Wallet::unconfirmedMoneyReceived, this, [this](const QString &txId, uint64_t amount){
+       if (m_wallet->isSynchronized()) {
+           auto notify = QString("%1 XMR (pending)").arg(WalletManager::displayAmount(amount, false));
+           Utils::desktopNotify("Payment received", notify, 5000);
+       }
+    });
+
+    // Device
+    connect(m_wallet, &Wallet::deviceButtonRequest, this, &MainWindow::onDeviceButtonRequest);
+    connect(m_wallet, &Wallet::deviceButtonPressed, this, &MainWindow::onDeviceButtonPressed);
+    connect(m_wallet, &Wallet::deviceError,         this, &MainWindow::onDeviceError);
+
+    connect(m_wallet, &Wallet::donationSent,        this, []{
+        config()->set(Config::donateBeg, -1);
+    });
+    
+    connect(m_wallet, &Wallet::multiBroadcast,      this, [this](PendingTransaction *tx){
+        quint64 count = tx->txCount();
+        for (quint64 i = 0; i < count; i++) {
+            QString txData = tx->signedTxToHex(i);
+
+            for (const auto& node: m_nodes->nodes()) {
+                QString address = node.toURL();
+                qDebug() << QString("Relaying %1 to: %2").arg(tx->txid()[i], address);
+                m_rpc->setDaemonAddress(address);
+                m_rpc->sendRawTransaction(txData);
+            }
+        }
     });
-    connect(m_ctx->wallet, &Wallet::currentSubaddressAccountChanged, this, &MainWindow::updateTitle);
-    connect(m_ctx->wallet, &Wallet::walletPassphraseNeeded, this, &MainWindow::onWalletPassphraseNeeded);
 }
 
 void MainWindow::menuToggleTabVisible(const QString &key){
@@ -459,15 +479,15 @@ void MainWindow::menuClearHistoryClicked() {
 }
 
 QString MainWindow::walletName() {
-    return QFileInfo(m_ctx->wallet->cachePath()).fileName();
+    return QFileInfo(m_wallet->cachePath()).fileName();
 }
 
 QString MainWindow::walletCachePath() {
-    return m_ctx->wallet->cachePath();
+    return m_wallet->cachePath();
 }
 
 QString MainWindow::walletKeysPath() {
-    return m_ctx->wallet->keysPath();
+    return m_wallet->keysPath();
 }
 
 void MainWindow::displayWalletErrorMsg(const QString &err) {
@@ -497,10 +517,10 @@ void MainWindow::onWalletOpened() {
     qDebug() << Q_FUNC_INFO;
     m_splashDialog->hide();
 
-    m_ctx->wallet->setRingDatabase(Utils::ringDatabasePath());
+    m_wallet->setRingDatabase(Utils::ringDatabasePath());
 
-    m_ctx->updateBalance();
-    if (m_ctx->wallet->isHwBacked()) {
+    m_wallet->updateBalance();
+    if (m_wallet->isHwBacked()) {
         m_statusBtnHwDevice->show();
     }
 
@@ -508,38 +528,39 @@ void MainWindow::onWalletOpened() {
     this->setEnabled(true);
 
     // receive page
-    m_ctx->wallet->subaddress()->refresh(m_ctx->wallet->currentSubaddressAccount());
-    if (m_ctx->wallet->subaddress()->count() == 1) {
+    m_wallet->subaddress()->refresh(m_wallet->currentSubaddressAccount());
+    if (m_wallet->subaddress()->count() == 1) {
         for (int i = 0; i < 10; i++) {
-            m_ctx->wallet->subaddress()->addRow(m_ctx->wallet->currentSubaddressAccount(), "");
+            m_wallet->subaddress()->addRow(m_wallet->currentSubaddressAccount(), "");
         }
     }
-    m_ctx->wallet->subaddressModel()->setCurrentSubaddressAccount(m_ctx->wallet->currentSubaddressAccount());
+    m_wallet->subaddressModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
 
     // history page
-    m_ctx->wallet->history()->refresh(m_ctx->wallet->currentSubaddressAccount());
+    m_wallet->history()->refresh(m_wallet->currentSubaddressAccount());
 
     // coins page
-    m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
-    m_coinsWidget->setModel(m_ctx->wallet->coinsModel(), m_ctx->wallet->coins());
-    m_ctx->wallet->coinsModel()->setCurrentSubaddressAccount(m_ctx->wallet->currentSubaddressAccount());
+    m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
+    m_coinsWidget->setModel(m_wallet->coinsModel(), m_wallet->coins());
+    m_wallet->coinsModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
 
     // Coin labeling uses set_tx_note, so we need to refresh history too
-    connect(m_ctx->wallet->coins(), &Coins::descriptionChanged, [this] {
-        m_ctx->wallet->history()->refresh(m_ctx->wallet->currentSubaddressAccount());
+    connect(m_wallet->coins(), &Coins::descriptionChanged, [this] {
+        m_wallet->history()->refresh(m_wallet->currentSubaddressAccount());
     });
     // Vice versa
-    connect(m_ctx->wallet->history(), &TransactionHistory::txNoteChanged, [this] {
-        m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount());
+    connect(m_wallet->history(), &TransactionHistory::txNoteChanged, [this] {
+        m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
     });
 
     this->updatePasswordIcon();
     this->updateTitle();
-    m_ctx->nodes->connectToNode();
+    m_nodes->allowConnection();
+    m_nodes->connectToNode();
     m_updateBytes.start(250);
 
     if (config()->get(Config::writeRecentlyOpenedWallets).toBool()) {
-        this->addToRecentlyOpened(m_ctx->wallet->cachePath());
+        this->addToRecentlyOpened(m_wallet->cachePath());
     }
 }
 
@@ -587,13 +608,13 @@ void MainWindow::setStatusText(const QString &text, bool override, int timeout)
 }
 
 void MainWindow::tryStoreWallet() {
-    if (m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus::ConnectionStatus_Synchronizing) {
+    if (m_wallet->connectionStatus() == Wallet::ConnectionStatus::ConnectionStatus_Synchronizing) {
         QMessageBox::warning(this, "Save wallet", "Unable to save wallet during synchronization.\n\n"
                                                   "Wait until synchronization is finished and try again.");
         return;
     }
 
-    m_ctx->wallet->store();
+    m_wallet->store();
 }
 
 void MainWindow::onWebsocketStatusChanged(bool enabled) {
@@ -614,6 +635,8 @@ void MainWindow::onWebsocketStatusChanged(bool enabled) {
 }
 
 void MainWindow::onProxySettingsChanged() {
+    m_nodes->connectToNode();
+
     int proxy = config()->get(Config::proxy).toInt();
 
     if (proxy == Config::Proxy::Tor) {
@@ -631,6 +654,14 @@ void MainWindow::onProxySettingsChanged() {
     m_statusBtnProxySettings->hide();
 }
 
+void MainWindow::onOfflineMode(bool offline) {
+    if (!m_wallet) {
+        return;
+    }
+    m_wallet->setOffline(offline);
+    this->onConnectionStatusChanged(Wallet::ConnectionStatus_Disconnected);
+}
+
 void MainWindow::onSynchronized() {
     this->updateNetStats();
     this->setStatusText("Synchronized");
@@ -693,13 +724,13 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
         QString tx_err = tx->errorString();
         qCritical() << tx_err;
 
-        if (m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_WrongVersion)
+        if (m_wallet->connectionStatus() == Wallet::ConnectionStatus_WrongVersion)
             err = QString("%1 Wrong node version: %2").arg(err, tx_err);
         else
             err = QString("%1 %2").arg(err, tx_err);
 
         if (tx_err.contains("Node response did not include the requested real output")) {
-            QString currentNode = m_ctx->nodes->connection().toAddress();
+            QString currentNode = m_nodes->connection().toAddress();
 
             err += QString("\nYou are currently connected to: %1\n\n"
                            "This node may be acting maliciously. You are strongly recommended to disconnect from this node."
@@ -708,21 +739,21 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
 
         qDebug() << Q_FUNC_INFO << err;
         this->displayWalletErrorMsg(err);
-        m_ctx->wallet->disposeTransaction(tx);
+        m_wallet->disposeTransaction(tx);
         return;
     }
     else if (tx->txCount() == 0) {
         err = QString("%1 %2").arg(err, "No unmixable outputs to sweep.");
         qDebug() << Q_FUNC_INFO << err;
         this->displayWalletErrorMsg(err);
-        m_ctx->wallet->disposeTransaction(tx);
+        m_wallet->disposeTransaction(tx);
         return;
     }
     else if (tx->txCount() > 1) {
         err = QString("%1 %2").arg(err, "Split transactions are not supported. Try sending a smaller amount.");
         qDebug() << Q_FUNC_INFO << err;
         this->displayWalletErrorMsg(err);
-        m_ctx->wallet->disposeTransaction(tx);
+        m_wallet->disposeTransaction(tx);
         return;
     }
 
@@ -743,35 +774,36 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
         err = QString("%1 %2").arg(err, "Constructed transaction doesn't appear to send to (all) specified destination address(es). Try creating the transaction again.");
         qDebug() << Q_FUNC_INFO << err;
         this->displayWalletErrorMsg(err);
-        m_ctx->wallet->disposeTransaction(tx);
+        m_wallet->disposeTransaction(tx);
         return;
     }
 
-    m_ctx->addCacheTransaction(tx->txid()[0], tx->signedTxToHex(0));
+    m_wallet->addCacheTransaction(tx->txid()[0], tx->signedTxToHex(0));
 
     // Show advanced dialog on multi-destination transactions
-    if (address.size() > 1 || m_ctx->wallet->viewOnly()) {
-        TxConfAdvDialog dialog_adv{m_ctx, m_ctx->tmpTxDescription, this};
-        dialog_adv.setTransaction(tx, !m_ctx->wallet->viewOnly());
+    if (address.size() > 1 || m_wallet->viewOnly()) {
+        TxConfAdvDialog dialog_adv{m_wallet, m_wallet->tmpTxDescription, this};
+        dialog_adv.setTransaction(tx, !m_wallet->viewOnly());
         dialog_adv.exec();
         return;
     }
 
-    TxConfDialog dialog{m_ctx, tx, address[0], m_ctx->tmpTxDescription, this};
+    TxConfDialog dialog{m_wallet, tx, address[0], m_wallet->tmpTxDescription, this};
     switch (dialog.exec()) {
         case QDialog::Rejected:
         {
-            if (!dialog.showAdvanced)
-                m_ctx->onCancelTransaction(tx, address);
+            if (!dialog.showAdvanced) {
+                m_wallet->disposeTransaction(tx);
+            }
             break;
         }
         case QDialog::Accepted:
-            m_ctx->commitTransaction(tx, m_ctx->tmpTxDescription);
+            m_wallet->commitTransaction(tx, m_wallet->tmpTxDescription);
             break;
     }
 
     if (dialog.showAdvanced) {
-        TxConfAdvDialog dialog_adv{m_ctx, m_ctx->tmpTxDescription, this};
+        TxConfAdvDialog dialog_adv{m_wallet, m_wallet->tmpTxDescription, this};
         dialog_adv.setTransaction(tx);
         dialog_adv.exec();
     }
@@ -789,8 +821,8 @@ void MainWindow::onTransactionCommitted(bool status, PendingTransaction *tx, con
         msgBox.exec();
         if (msgBox.clickedButton() == showDetailsButton) {
             this->showHistoryTab();
-            TransactionInfo *txInfo = m_ctx->wallet->history()->transaction(txid.first());
-            auto *dialog = new TxInfoDialog(m_ctx, txInfo, this);
+            TransactionInfo *txInfo = m_wallet->history()->transaction(txid.first());
+            auto *dialog = new TxInfoDialog(m_wallet, txInfo, this);
             connect(dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction);
             dialog->show();
             dialog->setAttribute(Qt::WA_DeleteOnClose);
@@ -815,22 +847,22 @@ void MainWindow::onCreateTransactionError(const QString &message) {
 }
 
 void MainWindow::showWalletInfoDialog() {
-    WalletInfoDialog dialog{m_ctx, this};
+    WalletInfoDialog dialog{m_wallet, this};
     dialog.exec();
 }
 
 void MainWindow::showSeedDialog() {
-    if (m_ctx->wallet->isHwBacked()) {
+    if (m_wallet->isHwBacked()) {
         QMessageBox::information(this, "Information", "Seed unavailable: Wallet keys are stored on hardware device.");
         return;
     }
 
-    if (m_ctx->wallet->viewOnly()) {
+    if (m_wallet->viewOnly()) {
         QMessageBox::information(this, "Information", "Wallet is view-only and has no seed.\n\nTo obtain wallet keys go to Wallet -> View-Only");
         return;
     }
 
-    if (!m_ctx->wallet->isDeterministic()) {
+    if (!m_wallet->isDeterministic()) {
         QMessageBox::information(this, "Information", "Wallet is non-deterministic and has no seed.\n\nTo obtain wallet keys go to Wallet -> Keys");
         return;
     }
@@ -839,18 +871,18 @@ void MainWindow::showSeedDialog() {
         return;
     }
 
-    SeedDialog dialog{m_ctx, this};
+    SeedDialog dialog{m_wallet, this};
     dialog.exec();
 }
 
 void MainWindow::showPasswordDialog() {
-    PasswordChangeDialog dialog{this, m_ctx->wallet};
+    PasswordChangeDialog dialog{this, m_wallet};
     dialog.exec();
     this->updatePasswordIcon();
 }
 
 void MainWindow::updatePasswordIcon() {
-    bool emptyPassword = m_ctx->wallet->verifyPassword("");
+    bool emptyPassword = m_wallet->verifyPassword("");
     QIcon icon = emptyPassword ? icons()->icon("unlock.svg") : icons()->icon("lock.svg");
     m_statusBtnPassword->setIcon(icon);
 }
@@ -860,12 +892,12 @@ void MainWindow::showKeysDialog() {
         return;
     }
 
-    KeysDialog dialog{m_ctx, this};
+    KeysDialog dialog{m_wallet, this};
     dialog.exec();
 }
 
 void MainWindow::showViewOnlyDialog() {
-    ViewOnlyDialog dialog{m_ctx, this};
+    ViewOnlyDialog dialog{m_wallet, this};
     dialog.exec();
 }
 
@@ -900,16 +932,16 @@ void MainWindow::menuAboutClicked() {
 }
 
 void MainWindow::menuSettingsClicked(bool showProxyTab) {
-    m_windowManager->showSettings(m_ctx, this, showProxyTab);
+    m_windowManager->showSettings(m_nodes, this, showProxyTab);
 }
 
 void MainWindow::menuSignVerifyClicked() {
-    SignVerifyDialog dialog{m_ctx->wallet, this};
+    SignVerifyDialog dialog{m_wallet, this};
     dialog.exec();
 }
 
 void MainWindow::menuVerifyTxProof() {
-    VerifyProofDialog dialog{m_ctx->wallet, this};
+    VerifyProofDialog dialog{m_wallet, this};
     dialog.exec();
 }
 
@@ -936,18 +968,18 @@ void MainWindow::updateWidgetIcons() {
 
 QIcon MainWindow::hardwareDevicePairedIcon() {
     QString filename;
-    if (m_ctx->wallet->isLedger())
+    if (m_wallet->isLedger())
         filename = "ledger.png";
-    else if (m_ctx->wallet->isTrezor())
+    else if (m_wallet->isTrezor())
         filename = ColorScheme::darkScheme ? "trezor_white.png" : "trezor.png";
     return icons()->icon(filename);
 }
 
 QIcon MainWindow::hardwareDeviceUnpairedIcon() {
     QString filename;
-    if (m_ctx->wallet->isLedger())
+    if (m_wallet->isLedger())
         filename = "ledger_unpaired.png";
-    else if (m_ctx->wallet->isTrezor())
+    else if (m_wallet->isTrezor())
         filename = ColorScheme::darkScheme ? "trezor_unpaired_white.png" : "trezor_unpaired.png";
     return icons()->icon(filename);
 }
@@ -964,10 +996,10 @@ void MainWindow::closeEvent(QCloseEvent *event) {
 
         m_updateBytes.stop();
         m_txTimer.stop();
-        m_ctx->stopTimers();
 
         // Wallet signal may fire after AppContext is gone, causing segv
-        m_ctx->wallet->disconnect();
+        m_wallet->disconnect();
+        this->disconnect();
 
         this->saveGeo();
         m_windowManager->closeWindow(this);
@@ -1031,16 +1063,16 @@ void MainWindow::onViewOnBlockExplorer(const QString &txid) {
 }
 
 void MainWindow::onResendTransaction(const QString &txid) {
-    QString txHex = m_ctx->getCacheTransaction(txid);
+    QString txHex = m_wallet->getCacheTransaction(txid);
     if (txHex.isEmpty()) {
         QMessageBox::warning(this, "Unable to resend transaction", "Transaction was not found in transaction cache. Unable to resend.");
         return;
     }
 
     // Connect to a different node so chances of successful relay are higher
-    m_ctx->nodes->autoConnect(true);
+    m_nodes->autoConnect(true);
 
-    TxBroadcastDialog dialog{this, m_ctx, txHex};
+    TxBroadcastDialog dialog{this, m_nodes, txHex};
     dialog.exec();
 }
 
@@ -1048,14 +1080,14 @@ void MainWindow::importContacts() {
     const QString targetFile = QFileDialog::getOpenFileName(this, "Import CSV file", QDir::homePath(), "CSV Files (*.csv)");
     if(targetFile.isEmpty()) return;
 
-    auto *model = m_ctx->wallet->addressBookModel();
+    auto *model = m_wallet->addressBookModel();
     QMapIterator<QString, QString> i(model->readCSV(targetFile));
     int inserts = 0;
     while (i.hasNext()) {
         i.next();
-        bool addressValid = WalletManager::addressValid(i.value(), m_ctx->wallet->nettype());
+        bool addressValid = WalletManager::addressValid(i.value(), m_wallet->nettype());
         if(addressValid) {
-            m_ctx->wallet->addressBook()->addRow(i.value(), "", i.key());
+            m_wallet->addressBook()->addRow(i.value(), "", i.key());
             inserts++;
         }
     }
@@ -1075,7 +1107,7 @@ void MainWindow::restoreGeo() {
 }
 
 void MainWindow::showDebugInfo() {
-    DebugInfoDialog dialog{m_ctx, this};
+    DebugInfoDialog dialog{m_wallet, m_nodes, this};
     dialog.exec();
 }
 
@@ -1084,7 +1116,7 @@ void MainWindow::showWalletCacheDebugDialog() {
         return;
     }
 
-    WalletCacheDebugDialog dialog{m_ctx, this};
+    WalletCacheDebugDialog dialog{m_wallet, this};
     dialog.exec();
 }
 
@@ -1103,7 +1135,7 @@ void MainWindow::showAddressChecker() {
         return;
     }
 
-    SubaddressIndex index = m_ctx->wallet->subaddressIndex(address);
+    SubaddressIndex index = m_wallet->subaddressIndex(address);
     if (!index.isValid()) {
         // TODO: probably mention lookahead here
         QMessageBox::warning(this, "Address Checker", "This address does not belong to this wallet.");
@@ -1117,9 +1149,9 @@ void MainWindow::exportKeyImages() {
     QString fn = QFileDialog::getSaveFileName(this, "Save key images to file", QString("%1/%2_%3").arg(QDir::homePath(), this->walletName(), QString::number(QDateTime::currentSecsSinceEpoch())), "Key Images (*_keyImages)");
     if (fn.isEmpty()) return;
     if (!fn.endsWith("_keyImages")) fn += "_keyImages";
-    bool r = m_ctx->wallet->exportKeyImages(fn, true);
+    bool r = m_wallet->exportKeyImages(fn, true);
     if (!r) {
-        QMessageBox::warning(this, "Key image export", QString("Failed to export key images.\nReason: %1").arg(m_ctx->wallet->errorString()));
+        QMessageBox::warning(this, "Key image export", QString("Failed to export key images.\nReason: %1").arg(m_wallet->errorString()));
     } else {
         QMessageBox::information(this, "Key image export", "Successfully exported key images.");
     }
@@ -1128,12 +1160,12 @@ void MainWindow::exportKeyImages() {
 void MainWindow::importKeyImages() {
     QString fn = QFileDialog::getOpenFileName(this, "Import key image file", QDir::homePath(), "Key Images (*_keyImages)");
     if (fn.isEmpty()) return;
-    bool r = m_ctx->wallet->importKeyImages(fn);
+    bool r = m_wallet->importKeyImages(fn);
     if (!r) {
-        QMessageBox::warning(this, "Key image import", QString("Failed to import key images.\n\n%1").arg(m_ctx->wallet->errorString()));
+        QMessageBox::warning(this, "Key image import", QString("Failed to import key images.\n\n%1").arg(m_wallet->errorString()));
     } else {
         QMessageBox::information(this, "Key image import", "Successfully imported key images");
-        m_ctx->refreshModels();
+        m_wallet->refreshModels();
     }
 }
 
@@ -1141,9 +1173,9 @@ void MainWindow::exportOutputs() {
     QString fn = QFileDialog::getSaveFileName(this, "Save outputs to file", QString("%1/%2_%3").arg(QDir::homePath(), this->walletName(), QString::number(QDateTime::currentSecsSinceEpoch())), "Outputs (*_outputs)");
     if (fn.isEmpty()) return;
     if (!fn.endsWith("_outputs")) fn += "_outputs";
-    bool r = m_ctx->wallet->exportOutputs(fn, true);
+    bool r = m_wallet->exportOutputs(fn, true);
     if (!r) {
-        QMessageBox::warning(this, "Outputs export", QString("Failed to export outputs.\nReason: %1").arg(m_ctx->wallet->errorString()));
+        QMessageBox::warning(this, "Outputs export", QString("Failed to export outputs.\nReason: %1").arg(m_wallet->errorString()));
     } else {
         QMessageBox::information(this, "Outputs export", "Successfully exported outputs.");
     }
@@ -1152,20 +1184,20 @@ void MainWindow::exportOutputs() {
 void MainWindow::importOutputs() {
     QString fn = QFileDialog::getOpenFileName(this, "Import outputs file", QDir::homePath(), "Outputs (*_outputs)");
     if (fn.isEmpty()) return;
-    bool r = m_ctx->wallet->importOutputs(fn);
+    bool r = m_wallet->importOutputs(fn);
     if (!r) {
-        QMessageBox::warning(this, "Outputs import", QString("Failed to import outputs.\n\n%1").arg(m_ctx->wallet->errorString()));
+        QMessageBox::warning(this, "Outputs import", QString("Failed to import outputs.\n\n%1").arg(m_wallet->errorString()));
     } else {
         QMessageBox::information(this, "Outputs import", "Successfully imported outputs");
-        m_ctx->refreshModels();
+        m_wallet->refreshModels();
     }
 }
 
 void MainWindow::loadUnsignedTx() {
     QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*unsigned_monero_tx)");
     if (fn.isEmpty()) return;
-    UnsignedTransaction *tx = m_ctx->wallet->loadTxFile(fn);
-    auto err = m_ctx->wallet->errorString();
+    UnsignedTransaction *tx = m_wallet->loadTxFile(fn);
+    auto err = m_wallet->errorString();
     if (!err.isEmpty()) {
         QMessageBox::warning(this, "Load transaction from file", QString("Failed to load transaction.\n\n%1").arg(err));
         return;
@@ -1180,8 +1212,8 @@ void MainWindow::loadUnsignedTxFromClipboard() {
         QMessageBox::warning(this, "Load unsigned transaction from clipboard", "Clipboard is empty");
         return;
     }
-    UnsignedTransaction *tx = m_ctx->wallet->loadTxFromBase64Str(unsigned_tx);
-    auto err = m_ctx->wallet->errorString();
+    UnsignedTransaction *tx = m_wallet->loadTxFromBase64Str(unsigned_tx);
+    auto err = m_wallet->errorString();
     if (!err.isEmpty()) {
         QMessageBox::warning(this, "Load unsigned transaction from clipboard", QString("Failed to load transaction.\n\n%1").arg(err));
         return;
@@ -1193,25 +1225,25 @@ void MainWindow::loadUnsignedTxFromClipboard() {
 void MainWindow::loadSignedTx() {
     QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*signed_monero_tx)");
     if (fn.isEmpty()) return;
-    PendingTransaction *tx = m_ctx->wallet->loadSignedTxFile(fn);
-    auto err = m_ctx->wallet->errorString();
+    PendingTransaction *tx = m_wallet->loadSignedTxFile(fn);
+    auto err = m_wallet->errorString();
     if (!err.isEmpty()) {
         QMessageBox::warning(this, "Load signed transaction from file", err);
         return;
     }
 
-    TxConfAdvDialog dialog{m_ctx, "", this};
+    TxConfAdvDialog dialog{m_wallet, "", this};
     dialog.setTransaction(tx);
     dialog.exec();
 }
 
 void MainWindow::loadSignedTxFromText() {
-    TxBroadcastDialog dialog{this, m_ctx};
+    TxBroadcastDialog dialog{this, m_nodes};
     dialog.exec();
 }
 
 void MainWindow::createUnsignedTxDialog(UnsignedTransaction *tx) {
-    TxConfAdvDialog dialog{m_ctx, "", this};
+    TxConfAdvDialog dialog{m_wallet, "", this};
     dialog.setUnsignedTransaction(tx);
     dialog.exec();
 }
@@ -1229,11 +1261,13 @@ void MainWindow::importTransaction() {
         }
     }
 
-    TxImportDialog dialog(this, m_ctx);
+    TxImportDialog dialog(this, m_wallet);
     dialog.exec();
 }
 
 void MainWindow::onDeviceError(const QString &error) {
+    qCritical() << "Device error: " << error;
+
     if (m_showDeviceError) {
         return;
     }
@@ -1243,7 +1277,7 @@ void MainWindow::onDeviceError(const QString &error) {
         m_showDeviceError = true;
         auto result = QMessageBox::question(this, "Hardware device", "Lost connection to hardware device. Attempt to reconnect?");
         if (result == QMessageBox::Yes) {
-            bool r = m_ctx->wallet->reconnectDevice();
+            bool r = m_wallet->reconnectDevice();
             if (r) {
                 break;
             }
@@ -1254,14 +1288,14 @@ void MainWindow::onDeviceError(const QString &error) {
         }
     }
     m_statusBtnHwDevice->setIcon(this->hardwareDevicePairedIcon());
-    m_ctx->wallet->startRefresh();
+    m_wallet->startRefresh();
     m_showDeviceError = false;
 }
 
 void MainWindow::onDeviceButtonRequest(quint64 code) {
     qDebug() << "DeviceButtonRequest, code: " << code;
 
-    if (m_ctx->wallet->isTrezor()) {
+    if (m_wallet->isTrezor()) {
         switch (code) {
             case 1:
             {
@@ -1306,41 +1340,41 @@ void MainWindow::onWalletPassphraseNeeded(bool on_device) {
                                                                              "the hardware wallet for better security.",
                                         QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
     if (button == QMessageBox::Yes) {
-        m_ctx->wallet->onPassphraseEntered("", true, false);
+        m_wallet->onPassphraseEntered("", true, false);
         return;
     }
 
     bool ok;
     QString passphrase = QInputDialog::getText(nullptr, "Wallet Passphrase Needed", "Enter passphrase:", QLineEdit::EchoMode::Password, "", &ok);
     if (ok) {
-        m_ctx->wallet->onPassphraseEntered(passphrase, false, false);
+        m_wallet->onPassphraseEntered(passphrase, false, false);
     } else {
-        m_ctx->wallet->onPassphraseEntered(passphrase, false, true);
+        m_wallet->onPassphraseEntered(passphrase, false, true);
     }
 }
 
 void MainWindow::updateNetStats() {
-    if (!m_ctx->wallet || m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected
-                       || m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Synchronized)
+    if (!m_wallet || m_wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected
+                       || m_wallet->connectionStatus() == Wallet::ConnectionStatus_Synchronized)
     {
         m_statusLabelNetStats->hide();
         return;
     }
 
     m_statusLabelNetStats->show();
-    m_statusLabelNetStats->setText(QString("(D: %1)").arg(Utils::formatBytes(m_ctx->wallet->getBytesReceived())));
+    m_statusLabelNetStats->setText(QString("(D: %1)").arg(Utils::formatBytes(m_wallet->getBytesReceived())));
 }
 
 void MainWindow::rescanSpent() {
-    if (!m_ctx->wallet->rescanSpent()) {
-        QMessageBox::warning(this, "Rescan spent", m_ctx->wallet->errorString());
+    if (!m_wallet->rescanSpent()) {
+        QMessageBox::warning(this, "Rescan spent", m_wallet->errorString());
     } else {
         QMessageBox::information(this, "Rescan spent", "Successfully rescanned spent outputs.");
     }
 }
 
 void MainWindow::showBalanceDialog() {
-    BalanceDialog dialog{this, m_ctx->wallet};
+    BalanceDialog dialog{this, m_wallet};
     dialog.exec();
 }
 
@@ -1420,7 +1454,7 @@ void MainWindow::onInitiateTransaction() {
     m_constructingTransaction = true;
     m_txTimer.start(1000);
 
-    if (m_ctx->wallet->isHwBacked()) {
+    if (m_wallet->isHwBacked()) {
         QString message = "Constructing transaction: action may be required on device.";
         m_splashDialog->setMessage(message);
         m_splashDialog->setIcon(QPixmap(":/assets/images/unconfirmed.png"));
@@ -1435,7 +1469,7 @@ void MainWindow::onEndTransaction() {
     m_txTimer.stop();
     this->setStatusText(m_statusText);
 
-    if (m_ctx->wallet->isHwBacked()) {
+    if (m_wallet->isHwBacked()) {
         m_splashDialog->hide();
     }
 }
@@ -1456,7 +1490,7 @@ void MainWindow::onSelectedInputsChanged(const QStringList &selectedInputs) {
 
     if (numInputs > 0) {
         quint64 totalAmount = 0;
-        auto coins = m_ctx->wallet->coins()->coinsFromKeyImage(selectedInputs);
+        auto coins = m_wallet->coins()->coinsFromKeyImage(selectedInputs);
         for (const auto coin : coins) {
             totalAmount += coin->amount();
         }
@@ -1467,20 +1501,20 @@ void MainWindow::onSelectedInputsChanged(const QStringList &selectedInputs) {
 }
 
 void MainWindow::onExportHistoryCSV(bool checked) {
-    if (m_ctx->wallet == nullptr)
+    if (m_wallet == nullptr)
         return;
     QString fn = QFileDialog::getSaveFileName(this, "Save CSV file", QDir::homePath(), "CSV (*.csv)");
     if (fn.isEmpty())
         return;
     if (!fn.endsWith(".csv"))
         fn += ".csv";
-    m_ctx->wallet->history()->writeCSV(fn);
+    m_wallet->history()->writeCSV(fn);
     QMessageBox::information(this, "CSV export", QString("Transaction history exported to %1").arg(fn));
 }
 
 void MainWindow::onExportContactsCSV(bool checked) {
-    if (m_ctx->wallet == nullptr) return;
-    auto *model = m_ctx->wallet->addressBookModel();
+    if (m_wallet == nullptr) return;
+    auto *model = m_wallet->addressBookModel();
     if (model->rowCount() <= 0){
         QMessageBox::warning(this, "Error", "Addressbook empty");
         return;
@@ -1540,19 +1574,19 @@ QString MainWindow::getPlatformTag() {
 }
 
 QString MainWindow::getHardwareDevice() {
-    if (!m_ctx->wallet->isHwBacked())
+    if (!m_wallet->isHwBacked())
         return "";
-    if (m_ctx->wallet->isTrezor())
+    if (m_wallet->isTrezor())
         return "Trezor";
-    if (m_ctx->wallet->isLedger())
+    if (m_wallet->isLedger())
         return "Ledger";
     return "Unknown";
 }
 
 void MainWindow::updateTitle() {
-    QString title = QString("%1 (#%2)").arg(this->walletName(), QString::number(m_ctx->wallet->currentSubaddressAccount()));
+    QString title = QString("%1 (#%2)").arg(this->walletName(), QString::number(m_wallet->currentSubaddressAccount()));
 
-    if (m_ctx->wallet->viewOnly())
+    if (m_wallet->viewOnly())
         title += " [view-only]";
 #ifdef HAS_XMRIG
     if (m_xmrig->isMining())
@@ -1565,13 +1599,13 @@ void MainWindow::updateTitle() {
 }
 
 void MainWindow::donationNag() {
-    if (m_ctx->networkType != NetworkType::Type::MAINNET)
+    if (m_wallet->nettype() != NetworkType::Type::MAINNET)
         return;
 
-    if (m_ctx->wallet->viewOnly())
+    if (m_wallet->viewOnly())
         return;
 
-    if (m_ctx->wallet->balanceAll() == 0)
+    if (m_wallet->balanceAll() == 0)
         return;
 
     auto donationCounter = config()->get(Config::donateBeg).toInt();
@@ -1640,7 +1674,7 @@ bool MainWindow::verifyPassword(bool sensitive) {
             return false;
         }
 
-        if (!m_ctx->wallet->verifyPassword(passwordDialog.password)) {
+        if (!m_wallet->verifyPassword(passwordDialog.password)) {
             incorrectPassword = true;
             continue;
         }
@@ -1707,7 +1741,7 @@ void MainWindow::unlockWallet(const QString &password) {
         return;
     }
 
-    if (!m_ctx->wallet->verifyPassword(password)) {
+    if (!m_wallet->verifyPassword(password)) {
         m_walletUnlockWidget->incorrectPassword();
         return;
     }
@@ -1742,4 +1776,6 @@ void MainWindow::toggleSearchbar(bool visible) {
         m_coinsWidget->focusSearchbar();
 }
 
-MainWindow::~MainWindow() = default;
\ No newline at end of file
+MainWindow::~MainWindow() {
+    qDebug() << "~MainWindow";
+};
\ No newline at end of file
index 64c0ae22a91eb767bb0c32dc2af472264f26ec93..4b27075f92d38ef192f4990da9b8e485bb492175 100644 (file)
@@ -8,7 +8,6 @@
 #include <QSystemTrayIcon>
 #include <QMenu>
 
-#include "appcontext.h"
 #include "components.h"
 #include "CalcWindow.h"
 #include "SettingsDialog.h"
@@ -30,6 +29,7 @@
 #include "model/CoinsProxyModel.h"
 #include "utils/networking.h"
 #include "utils/config.h"
+#include "utils/daemonrpc.h"
 #include "utils/EventFilter.h"
 #include "utils/Updater.h"
 #include "widgets/CCSWidget.h"
@@ -192,6 +192,7 @@ private slots:
     void onWebsocketStatusChanged(bool enabled);
     void showUpdateNotification();
     void onProxySettingsChanged();
+    void onOfflineMode(bool offline);
 
 private:
     friend WindowManager;
@@ -235,7 +236,9 @@ private:
 
     QScopedPointer<Ui::MainWindow> ui;
     WindowManager *m_windowManager;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet = nullptr;
+    Nodes *m_nodes;
+    DaemonRpc *m_rpc;
 
     CalcWindow *m_windowCalc = nullptr;
     SplashDialog *m_splashDialog = nullptr;
index 6d9a0583191175478a700759ce0925bd874ebea8..0bc180d4ad024211a7bf70792037791212b742dc 100644 (file)
 #include "model/ModelUtils.h"
 #include "utils/Icons.h"
 
-ReceiveWidget::ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
+ReceiveWidget::ReceiveWidget(Wallet *wallet, QWidget *parent)
         : QWidget(parent)
         , ui(new Ui::ReceiveWidget)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
 {
     ui->setupUi(this);
 
-    m_model = m_ctx->wallet->subaddressModel();
-    m_proxyModel = new SubaddressProxyModel(this, m_ctx->wallet->subaddress());
+    m_model = m_wallet->subaddressModel();
+    m_proxyModel = new SubaddressProxyModel(this, m_wallet->subaddress());
     m_proxyModel->setSourceModel(m_model);
     m_proxyModel->setHiddenAddresses(this->getHiddenAddresses());
 
@@ -112,7 +112,7 @@ void ReceiveWidget::showContextMenu(const QPoint &point) {
         menu->addAction("Hide address", this, &ReceiveWidget::hideAddress);
     }
 
-    if (m_ctx->wallet->isHwBacked()) {
+    if (m_wallet->isHwBacked()) {
         menu->addAction("Show on device", this, &ReceiveWidget::showOnDevice);
     }
 
@@ -127,7 +127,7 @@ void ReceiveWidget::createPaymentRequest() {
 
     QString address = index.model()->data(index.siblingAtColumn(SubaddressModel::Address), Qt::UserRole).toString();
 
-    PaymentRequestDialog dialog{this, m_ctx, address};
+    PaymentRequestDialog dialog{this, m_wallet, address};
     dialog.exec();
 }
 
@@ -189,13 +189,13 @@ void ReceiveWidget::showAddress()
 void ReceiveWidget::showOnDevice() {
     Monero::SubaddressRow* row = this->currentEntry();
     if (!row) return;
-    m_ctx->wallet->deviceShowAddressAsync(m_ctx->wallet->currentSubaddressAccount(), row->getRowId(), "");
+    m_wallet->deviceShowAddressAsync(m_wallet->currentSubaddressAccount(), row->getRowId(), "");
 }
 
 void ReceiveWidget::generateSubaddress() {
-    bool r = m_ctx->wallet->subaddress()->addRow(m_ctx->wallet->currentSubaddressAccount(), "");
+    bool r = m_wallet->subaddress()->addRow(m_wallet->currentSubaddressAccount(), "");
     if (!r) {
-        QMessageBox::warning(this, "Warning", QString("Failed to generate subaddress:\n\n%1").arg(m_ctx->wallet->subaddress()->errorString()));
+        QMessageBox::warning(this, "Warning", QString("Failed to generate subaddress:\n\n%1").arg(m_wallet->subaddress()->errorString()));
     }
 }
 
@@ -229,7 +229,7 @@ void ReceiveWidget::showQrCodeDialog() {
 }
 
 QStringList ReceiveWidget::getHiddenAddresses() {
-    QString data = m_ctx->wallet->getCacheAttribute("feather.hiddenaddresses");
+    QString data = m_wallet->getCacheAttribute("feather.hiddenaddresses");
     return data.split(",");
 }
 
@@ -239,14 +239,14 @@ void ReceiveWidget::addHiddenAddress(const QString& address) {
         hiddenAddresses.append(address);
     }
     QString data = hiddenAddresses.join(",");
-    m_ctx->wallet->setCacheAttribute("feather.hiddenaddresses", data);
+    m_wallet->setCacheAttribute("feather.hiddenaddresses", data);
 }
 
 void ReceiveWidget::removeHiddenAddress(const QString &address) {
     QStringList hiddenAddresses = this->getHiddenAddresses();
     hiddenAddresses.removeAll(address);
     QString data = hiddenAddresses.join(",");
-    m_ctx->wallet->setCacheAttribute("feather.hiddenaddresses", data);
+    m_wallet->setCacheAttribute("feather.hiddenaddresses", data);
 }
 
 Monero::SubaddressRow* ReceiveWidget::currentEntry() {
index 969863ddaa3262c75459ef714d794211a91002dd..aefed1af89d4604373f4d41c1b0742bdf72ab7cc 100644 (file)
@@ -8,8 +8,8 @@
 #include <QWidget>
 #include <QSvgWidget>
 
-#include "appcontext.h"
 #include "libwalletqt/Subaddress.h"
+#include "libwalletqt/Wallet.h"
 #include "model/SubaddressProxyModel.h"
 #include "model/SubaddressModel.h"
 #include "qrcode/QrCode.h"
@@ -23,7 +23,7 @@ class ReceiveWidget : public QWidget
 Q_OBJECT
 
 public:
-    explicit ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit ReceiveWidget(Wallet *wallet, QWidget *parent = nullptr);
     ~ReceiveWidget() override;
 
     void setSearchbarVisible(bool visible);
@@ -53,7 +53,7 @@ private slots:
 
 private:
     QScopedPointer<Ui::ReceiveWidget> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     QMenu *m_headerMenu;
     QAction *m_showFullAddressesAction;
     QAction *m_showUsedAddressesAction;
index 205db7505692628f3cfce4ca41e6fa83c789f1a8..6554e51bde0e0991e65f0dbba71c4b189bd36035 100644 (file)
@@ -9,7 +9,9 @@
 #include "ColorScheme.h"
 #include "constants.h"
 #include "utils/AppData.h"
+#include "utils/config.h"
 #include "Icons.h"
+#include "libwalletqt/WalletManager.h"
 
 #if defined(WITH_SCANNER) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
 #include "qrcode_scanner/QrCodeScanDialog.h"
 #include <QMediaDevices>
 #endif
 
-SendWidget::SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
+SendWidget::SendWidget(Wallet *wallet, QWidget *parent)
     : QWidget(parent)
     , ui(new Ui::SendWidget)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
 {
     ui->setupUi(this);
 
@@ -32,8 +34,8 @@ SendWidget::SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
     QValidator *validator = new QRegularExpressionValidator(rx, this);
     ui->lineAmount->setValidator(validator);
 
-    connect(m_ctx.get(), &AppContext::initiateTransaction, this, &SendWidget::onInitiateTransaction);
-    connect(m_ctx.get(), &AppContext::endTransaction, this, &SendWidget::onEndTransaction);
+    connect(m_wallet, &Wallet::initiateTransaction, this, &SendWidget::onInitiateTransaction);
+    connect(m_wallet, &Wallet::endTransaction, this, &SendWidget::onEndTransaction);
 
     connect(WalletManager::instance(), &WalletManager::openAliasResolved, this, &SendWidget::onOpenAliasResolved);
 
@@ -143,14 +145,14 @@ void SendWidget::scanClicked() {
 }
 
 void SendWidget::sendClicked() {
-    if (!m_ctx->wallet->isConnected()) {
+    if (!m_wallet->isConnected()) {
         QMessageBox::warning(this, "Error", "Unable to create transaction:\n\n"
                                             "Wallet is not connected to a node.\n"
                                             "Go to File -> Settings -> Node to manually connect to a node.");
         return;
     }
 
-    if (!m_ctx->wallet->isSynchronized()) {
+    if (!m_wallet->isSynchronized()) {
         QMessageBox::warning(this, "Error", "Wallet is not synchronized, unable to create transaction.\n\n"
                                             "Wait for synchronization to complete.");
         return;
@@ -189,7 +191,7 @@ void SendWidget::sendClicked() {
             amounts.push_back(output.amount);
         }
 
-        m_ctx->onCreateTransactionMultiDest(addresses, amounts, description);
+        m_wallet->createTransactionMultiDest(addresses, amounts, description);
         return;
     }
 
@@ -207,7 +209,7 @@ void SendWidget::sendClicked() {
         amount = WalletManager::amountFromDouble(this->conversionAmount());
     }
 
-    m_ctx->onCreateTransaction(recipient, amount, description, sendAll);
+    m_wallet->createTransaction(recipient, amount, description, sendAll);
 }
 
 void SendWidget::aliasClicked() {
@@ -347,7 +349,7 @@ void SendWidget::setWebsocketEnabled(bool enabled) {
 
 void SendWidget::onDataPasted(const QString &data) {
     if (!data.isEmpty()) {
-        QVariantMap uriData = m_ctx->wallet->parse_uri_to_object(data);
+        QVariantMap uriData = m_wallet->parse_uri_to_object(data);
         if (!uriData.contains("error")) {
             ui->lineAddress->setText(uriData.value("address").toString());
             ui->lineDescription->setText(uriData.value("tx_description").toString());
index 5369ac7dce1bbea5aa2a78897694fa37a6a08189..ca1375937e5831886f6a26c01b31c6c25c7fcf0a 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <QWidget>
 
-#include "appcontext.h"
+#include "libwalletqt/Wallet.h"
 #include "widgets/CCSWidget.h"
 
 namespace Ui {
@@ -18,7 +18,7 @@ class SendWidget : public QWidget
 Q_OBJECT
 
 public:
-    explicit SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit SendWidget(Wallet *wallet, QWidget *parent = nullptr);
     void fill(const QString &address, const QString &description, double amount = 0);
     void fill(double amount);
     void clearFields();
@@ -57,7 +57,7 @@ private:
     double conversionAmount();
 
     QScopedPointer<Ui::SendWidget> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     bool m_sendDisabled = false;
 };
 
index e5fe82e4139fc183cc27cb71bac9d8d8cd1bd2d6..d97635cef35fbddcfbbefcaaf11e3945e264e93e 100644 (file)
@@ -9,14 +9,16 @@
 #include <QFileDialog>
 #include <QMessageBox>
 
+#include "libwalletqt/WalletManager.h"
+#include "utils/AppData.h"
 #include "utils/Icons.h"
 #include "utils/WebsocketNotifier.h"
 #include "widgets/NetworkProxyWidget.h"
 
-Settings::Settings(QSharedPointer<AppContext> ctx, QWidget *parent)
+Settings::Settings(Nodes *nodes, QWidget *parent)
         : QDialog(parent)
         , ui(new Ui::Settings)
-        , m_ctx(std::move(ctx))
+        , m_nodes(nodes)
 {
     ui->setupUi(this);
 
@@ -150,12 +152,12 @@ void Settings::setupAppearanceTab() {
 
 void Settings::setupNetworkTab() {
     // Node
-    if (m_ctx) {
-        ui->nodeWidget->setupUI(m_ctx->nodes);
-        connect(ui->nodeWidget, &NodeWidget::nodeSourceChanged, m_ctx->nodes, &Nodes::onNodeSourceChanged);
-        connect(ui->nodeWidget, &NodeWidget::connectToNode, m_ctx->nodes, QOverload<const FeatherNode&>::of(&Nodes::connectToNode));
+    if (m_nodes) {
+        ui->nodeWidget->setupUI(m_nodes);
+        connect(ui->nodeWidget, &NodeWidget::nodeSourceChanged, m_nodes, &Nodes::onNodeSourceChanged);
+        connect(ui->nodeWidget, &NodeWidget::connectToNode, m_nodes, QOverload<const FeatherNode&>::of(&Nodes::connectToNode));
     } else {
-        m_nodes = new Nodes(this);
+        m_nodes = new Nodes(this, nullptr);
         ui->nodeWidget->setupUI(m_nodes);
         ui->nodeWidget->setCanConnect(false);
     }
index b8b1f91e6afebbfc8f576565933fff9fe6cf1b40..77809fb1115aade97ebcdc833f2e33510998b25a 100644 (file)
@@ -9,7 +9,6 @@
 #include <QDialog>
 #include <QSettings>
 
-#include "appcontext.h"
 #include "widgets/NodeWidget.h"
 
 namespace Ui {
@@ -21,7 +20,7 @@ class Settings : public QDialog
 Q_OBJECT
 
 public:
-    explicit Settings(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit Settings(Nodes *nodes, QWidget *parent = nullptr);
     ~Settings() override;
 
     void showNetworkProxyTab();
@@ -67,7 +66,6 @@ private:
     void enableWebsocket(bool enabled);
 
     QScopedPointer<Ui::Settings> ui;
-    QSharedPointer<AppContext> m_ctx;
     Nodes *m_nodes = nullptr;
 
     QStringList m_themes{"Native", "QDarkStyle", "Breeze/Dark", "Breeze/Light"};
index bce0f5cdc03e2b6e18974499395fe1e129eed8cd..aea11721d04a0a3ccd8409c265dcf8d6e1731ff5 100644 (file)
 #include "utils/Icons.h"
 #include "utils/NetworkManager.h"
 #include "utils/os/tails.h"
+#include "utils/os/whonix.h"
 #include "utils/TorManager.h"
 #include "utils/WebsocketNotifier.h"
 
-WindowManager::WindowManager(EventFilter *eventFilter)
-    : eventFilter(eventFilter)
+WindowManager::WindowManager(QObject *parent, EventFilter *eventFilter)
+    : QObject(parent)
+    , eventFilter(eventFilter)
 {
     m_walletManager = WalletManager::instance();
     m_splashDialog = new SplashDialog;
@@ -83,12 +85,15 @@ void WindowManager::close() {
 }
 
 void WindowManager::closeWindow(MainWindow *window) {
+    qDebug() << "closing Window";
     m_windows.removeOne(window);
 
-    // Move Wallet to a different thread for cleanup so it doesn't block GUI thread
-    window->m_ctx->wallet->moveToThread(m_cleanupThread);
+    // Move Wallet to a different thread for cleanup, so it doesn't block GUI thread
+    window->m_wallet->moveToThread(m_cleanupThread);
     m_cleanupThread->start();
-    window->m_ctx->wallet->deleteLater();
+    window->m_wallet->deleteLater();
+
+    window->deleteLater();
 }
 
 void WindowManager::restartApplication(const QString &binaryFilename) {
@@ -138,8 +143,8 @@ void WindowManager::raise() {
 
 // ######################## SETTINGS ########################
 
-void WindowManager::showSettings(QSharedPointer<AppContext> ctx, QWidget *parent, bool showProxyTab) {
-    Settings settings{ctx, parent};
+void WindowManager::showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab) {
+    Settings settings{nodes, parent};
 
     connect(&settings, &Settings::preferredFiatCurrencyChanged, [this]{
         for (const auto &window : m_windows) {
@@ -301,6 +306,7 @@ void WindowManager::tryCreateWallet(Seed seed, const QString &path, const QStrin
 
     wallet->setCacheAttribute("feather.seed", seed.mnemonic.join(" "));
     wallet->setCacheAttribute("feather.seedoffset", seedOffset);
+    wallet->setNewWallet();
 
     this->onWalletOpened(wallet);
 }
@@ -359,6 +365,7 @@ void WindowManager::onWalletCreated(Wallet *wallet) {
     // Currently only called when a wallet is created from device.
     auto state = wallet->status();
     if (state != Wallet::Status_Ok) {
+        wallet->setNewWallet();
         qDebug() << Q_FUNC_INFO << QString("Wallet open error: %1").arg(wallet->errorString());
         this->displayWalletErrorMessage(wallet->errorString());
         m_splashDialog->hide();
index 9c5fbd25d6d0e7c95a130763673dd4f28983c728..d8dc074c4ba8c9253d84bf9359b3b790c67384b7 100644 (file)
@@ -10,6 +10,7 @@
 #include "libwalletqt/WalletManager.h"
 #include "libwalletqt/Wallet.h"
 #include "MainWindow.h"
+#include "utils/nodes.h"
 #include "wizard/WalletWizard.h"
 
 class MainWindow;
@@ -17,7 +18,7 @@ class WindowManager : public QObject {
 Q_OBJECT
 
 public:
-    explicit WindowManager(EventFilter *eventFilter);
+    explicit WindowManager(QObject *parent, EventFilter *eventFilter);
     ~WindowManager() override;
 
     void wizardOpenWallet();
@@ -27,7 +28,7 @@ public:
     void restartApplication(const QString &binaryFilename);
     void raise();
 
-    void showSettings(QSharedPointer<AppContext> ctx, QWidget *parent, bool showProxyTab = false);
+    void showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab = false);
 
     EventFilter *eventFilter;
 
diff --git a/src/appcontext.cpp b/src/appcontext.cpp
deleted file mode 100644 (file)
index efad102..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-// SPDX-FileCopyrightText: 2020-2023 The Monero Project
-
-#include <QDir>
-
-#include "appcontext.h"
-#include "constants.h"
-
-// libwalletqt
-#include "libwalletqt/TransactionHistory.h"
-#include "libwalletqt/Subaddress.h"
-#include "libwalletqt/Coins.h"
-#include "model/TransactionHistoryModel.h"
-#include "model/SubaddressModel.h"
-#include "utils/NetworkManager.h"
-#include "utils/WebsocketClient.h"
-#include "utils/WebsocketNotifier.h"
-
-// This class serves as a business logic layer between MainWindow and libwalletqt.
-// This way we don't clutter the GUI with wallet logic,
-// and keep libwalletqt (mostly) clean of Feather specific implementation details
-
-AppContext::AppContext(Wallet *wallet)
-    : wallet(wallet)
-    , nodes(new Nodes(this))
-    , networkType(constants::networkType)
-    , m_rpc(new DaemonRpc{this, ""})
-{
-    connect(this->wallet, &Wallet::moneySpent,               this, &AppContext::onMoneySpent);
-    connect(this->wallet, &Wallet::moneyReceived,            this, &AppContext::onMoneyReceived);
-    connect(this->wallet, &Wallet::unconfirmedMoneyReceived, this, &AppContext::onUnconfirmedMoneyReceived);
-    connect(this->wallet, &Wallet::newBlock,                 this, &AppContext::onWalletNewBlock);
-    connect(this->wallet, &Wallet::updated,                  this, &AppContext::onWalletUpdate);
-    connect(this->wallet, &Wallet::refreshed,                this, &AppContext::onWalletRefreshed);
-    connect(this->wallet, &Wallet::transactionCommitted,     this, &AppContext::onTransactionCommitted);
-    connect(this->wallet, &Wallet::heightRefreshed,          this, &AppContext::onHeightRefreshed);
-    connect(this->wallet, &Wallet::transactionCreated,       this, &AppContext::onTransactionCreated);
-    connect(this->wallet, &Wallet::deviceError,              this, &AppContext::onDeviceError);
-    connect(this->wallet, &Wallet::deviceButtonRequest,      this, &AppContext::onDeviceButtonRequest);
-    connect(this->wallet, &Wallet::deviceButtonPressed,      this, &AppContext::onDeviceButtonPressed);
-    connect(this->wallet, &Wallet::currentSubaddressAccountChanged, [this]{
-        this->updateBalance();
-    });
-
-    connect(this, &AppContext::createTransactionError, this, &AppContext::onCreateTransactionError);
-
-    nodes->setContext(this);
-
-    // Store the wallet every 2 minutes
-    m_storeTimer.start(2 * 60 * 1000);
-    connect(&m_storeTimer, &QTimer::timeout, [this](){
-        this->storeWallet();
-    });
-
-    this->updateBalance();
-
-    connect(this->wallet->history(), &TransactionHistory::txNoteChanged, [this]{
-        this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
-    });
-}
-
-// ################## Transaction creation ##################
-
-void AppContext::onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all) {
-    this->tmpTxDescription = description;
-
-    if (!all && amount == 0) {
-        emit createTransactionError("Cannot send nothing");
-        return;
-    }
-
-    quint64 unlocked_balance = this->wallet->unlockedBalance();
-    if (!all && amount > unlocked_balance) {
-        emit createTransactionError(QString("Not enough money to spend.\n\n"
-                                            "Spendable balance: %1").arg(WalletManager::displayAmount(unlocked_balance)));
-        return;
-    } else if (unlocked_balance == 0) {
-        emit createTransactionError("No money to spend");
-        return;
-    }
-
-    qInfo() << "Creating transaction";
-    if (all)
-        this->wallet->createTransactionAllAsync(address, "", constants::mixin, this->tx_priority, m_selectedInputs);
-    else
-        this->wallet->createTransactionAsync(address, "", amount, constants::mixin, this->tx_priority, m_selectedInputs);
-
-    emit initiateTransaction();
-}
-
-void AppContext::onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description) {
-    this->tmpTxDescription = description;
-
-    quint64 total_amount = 0;
-    for (auto &amount : amounts) {
-        total_amount += amount;
-    }
-
-    auto unlocked_balance = this->wallet->unlockedBalance();
-    if (total_amount > unlocked_balance) {
-        emit createTransactionError("Not enough money to spend");
-    }
-
-    qInfo() << "Creating transaction";
-    this->wallet->createTransactionMultiDestAsync(addresses, amounts, this->tx_priority, m_selectedInputs);
-
-    emit initiateTransaction();
-}
-
-void AppContext::onSweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs) {
-    if (churn) {
-        address = this->wallet->address(0, 0);
-    }
-
-    qInfo() << "Creating transaction";
-    this->wallet->createTransactionSelectedAsync(keyImages, address, outputs, this->tx_priority);
-
-    emit initiateTransaction();
-}
-
-void AppContext::onCreateTransactionError(const QString &msg) {
-    this->tmpTxDescription = "";
-    emit endTransaction();
-}
-
-void AppContext::onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address) {
-    // tx cancelled by user
-    emit createTransactionCancelled(address, tx->amount());
-    this->wallet->disposeTransaction(tx);
-}
-
-void AppContext::commitTransaction(PendingTransaction *tx, const QString &description) {
-    // Clear list of selected transfers
-    this->setSelectedInputs({});
-
-    // Nodes - even well-connected, properly configured ones - consistently fail to relay transactions
-    // To mitigate transactions failing we just send the transaction to every node we know about over Tor
-    if (config()->get(Config::multiBroadcast).toBool()) {
-        this->onMultiBroadcast(tx);
-    }
-
-    this->wallet->commitTransactionAsync(tx, description);
-}
-
-void AppContext::onMultiBroadcast(PendingTransaction *tx) {
-    quint64 count = tx->txCount();
-    for (quint64 i = 0; i < count; i++) {
-        QString txData = tx->signedTxToHex(i);
-
-        for (const auto& node: this->nodes->nodes()) {
-            QString address = node.toURL();
-            qDebug() << QString("Relaying %1 to: %2").arg(tx->txid()[i], address);
-            m_rpc->setDaemonAddress(address);
-            m_rpc->sendRawTransaction(txData);
-        }
-    }
-}
-
-void AppContext::addCacheTransaction(const QString &txid, const QString &txHex) const {
-    this->wallet->setCacheAttribute(QString("tx:%1").arg(txid), txHex);
-}
-
-QString AppContext::getCacheTransaction(const QString &txid) const {
-    QString txHex = this->wallet->getCacheAttribute(QString("tx:%1").arg(txid));
-    return txHex;
-}
-
-// ################## Device ##################
-
-void AppContext::onDeviceButtonRequest(quint64 code) {
-    emit deviceButtonRequest(code);
-}
-
-void AppContext::onDeviceButtonPressed() {
-    emit deviceButtonPressed();
-}
-
-void AppContext::onDeviceError(const QString &message) {
-    qCritical() << "Device error: " << message;
-    emit deviceError(message);
-}
-
-// ################## Misc ##################
-
-void AppContext::setSelectedInputs(const QStringList &selectedInputs) {
-    m_selectedInputs = selectedInputs;
-    emit selectedInputsChanged(selectedInputs);
-}
-
-void AppContext::onProxySettingsChanged() {
-    if (Utils::isTorsocks()) {
-        return;
-    }
-
-    this->nodes->connectToNode();
-}
-
-void AppContext::stopTimers() {
-    m_storeTimer.stop();
-}
-
-// ########################################## LIBWALLET QT SIGNALS ####################################################
-
-void AppContext::onMoneySpent(const QString &txId, quint64 amount) {
-    // Outgoing tx included in a block
-    qDebug() << Q_FUNC_INFO << txId << " " << WalletManager::displayAmount(amount);
-}
-
-void AppContext::onMoneyReceived(const QString &txId, quint64 amount) {
-    // Incoming tx included in a block.
-    qDebug() << Q_FUNC_INFO << txId << " " << WalletManager::displayAmount(amount);
-}
-
-void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) {
-    // Incoming tx in pool
-    qDebug() << Q_FUNC_INFO << txId << " " << WalletManager::displayAmount(amount);
-
-    if (this->wallet->synchronized()) {
-        auto notify = QString("%1 XMR (pending)").arg(WalletManager::displayAmount(amount, false));
-        Utils::desktopNotify("Payment received", notify, 5000);
-    }
-}
-
-void AppContext::onWalletUpdate() {
-    if (this->wallet->synchronized()) {
-        this->refreshModels();
-        this->storeWallet();
-    }
-
-    this->updateBalance();
-}
-
-void AppContext::onWalletRefreshed(bool success, const QString &message) {
-    if (!success) {
-        // Something went wrong during refresh, in some cases we need to notify the user
-        qCritical() << "Exception during refresh: " << message; // Can't use ->errorString() here, other SLOT might snipe it first
-        return;
-    }
-
-    if (!this->refreshed) {
-        refreshModels();
-        this->refreshed = true;
-        emit walletRefreshed();
-        // store wallet immediately upon finishing synchronization
-        this->wallet->store();
-    }
-}
-
-void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
-    // Called whenever a new block gets scanned by the wallet
-    this->syncStatusUpdated(blockheight, targetHeight);
-
-    if (this->wallet->isSynchronized()) {
-        this->wallet->coins()->refreshUnlocked();
-        this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
-        // Todo: only refresh tx confirmations
-    }
-}
-
-void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) {
-    if (this->wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected)
-        return;
-
-    if (daemonHeight < targetHeight) {
-        emit blockchainSync(daemonHeight, targetHeight);
-    }
-    else {
-        this->syncStatusUpdated(walletHeight, daemonHeight);
-    }
-}
-
-void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address) {
-    qDebug() << Q_FUNC_INFO;
-
-    for (auto &addr : address) {
-        if (addr == constants::donationAddress) {
-            this->donationSending = true;
-        }
-    }
-
-    // Let UI know that the transaction was constructed
-    emit endTransaction();
-
-    // tx created, but not sent yet. ask user to verify first.
-    emit createTransactionSuccess(tx, address);
-}
-
-void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
-    // Store wallet immediately so we don't risk losing tx key if wallet crashes
-    this->wallet->store();
-
-    this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
-    this->wallet->coins()->refresh(this->wallet->currentSubaddressAccount());
-
-    this->updateBalance();
-
-    // this tx was a donation to Feather, stop our nagging
-    if (this->donationSending) {
-        this->donationSending = false;
-        config()->set(Config::donateBeg, -1);
-    }
-
-    emit transactionCommitted(status, tx, txid);
-}
-
-void AppContext::storeWallet() {
-    // Do not store a synchronizing wallet: store() is NOT thread safe and may crash the wallet
-    if (!this->wallet->isSynchronized())
-        return;
-
-    qDebug() << "Storing wallet";
-    this->wallet->store();
-}
-
-void AppContext::updateBalance() {
-    quint64 balance = this->wallet->balance();
-    quint64 spendable = this->wallet->unlockedBalance();
-
-    emit balanceUpdated(balance, spendable);
-}
-
-void AppContext::syncStatusUpdated(quint64 height, quint64 target) {
-    if (height < (target - 1)) {
-        emit refreshSync(height, target);
-    }
-    else {
-        this->updateBalance();
-        emit synchronized();
-    }
-}
-
-void AppContext::refreshModels() {
-    this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
-    this->wallet->coins()->refresh(this->wallet->currentSubaddressAccount());
-    bool r = this->wallet->subaddress()->refresh(this->wallet->currentSubaddressAccount());
-
-    if (!r) {
-        // This should only happen if wallet keys got corrupted or were tampered with
-        // The list of subaddresses is wiped to prevent loss of funds
-        // Notify MainWindow to display an error message
-        emit keysCorrupted();
-    }
-}
diff --git a/src/appcontext.h b/src/appcontext.h
deleted file mode 100644 (file)
index 4b11983..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-// SPDX-FileCopyrightText: 2020-2023 The Monero Project
-
-#ifndef FEATHER_APPCONTEXT_H
-#define FEATHER_APPCONTEXT_H
-
-#include <QObject>
-#include <QTimer>
-
-#include "utils/os/whonix.h"
-#include "utils/networking.h"
-#include "utils/Seed.h"
-#include "utils/daemonrpc.h"
-#include "utils/RestoreHeightLookup.h"
-#include "utils/nodes.h"
-
-#include "libwalletqt/WalletManager.h"
-#include "PendingTransaction.h"
-
-class AppContext : public QObject
-{
-Q_OBJECT
-
-public:
-    explicit AppContext(Wallet *wallet);
-
-    Wallet *wallet;
-    Nodes *nodes;
-
-    bool donationSending = false;
-
-    QString tmpTxDescription; // TODO: remove the need for this var
-
-    NetworkType::Type networkType;
-    PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
-
-    // libwalletqt
-    bool refreshed = false;
-
-    void commitTransaction(PendingTransaction *tx, const QString &description="");
-    void syncStatusUpdated(quint64 height, quint64 target);
-    void updateBalance();
-    void refreshModels();
-
-    void storeWallet();
-
-    void stopTimers();
-
-    void addCacheTransaction(const QString &txid, const QString &txHex) const;
-    QString getCacheTransaction(const QString &txid) const;
-
-    void setSelectedInputs(const QStringList &selectedInputs);
-
-public slots:
-    void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all);
-    void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
-    void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address);
-    void onSweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs);
-    void onCreateTransactionError(const QString &msg);
-    void onMultiBroadcast(PendingTransaction *tx);
-    void onDeviceButtonRequest(quint64 code);
-    void onDeviceButtonPressed();
-    void onDeviceError(const QString &message);
-
-    void onProxySettingsChanged(); // should not be here
-
-private slots:
-    void onMoneySpent(const QString &txId, quint64 amount);
-    void onMoneyReceived(const QString &txId, quint64 amount);
-    void onUnconfirmedMoneyReceived(const QString &txId, quint64 amount);
-    void onWalletUpdate();
-    void onWalletRefreshed(bool success, const QString &message);
-
-    void onWalletNewBlock(quint64 blockheight, quint64 targetHeight);
-    void onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight);
-    void onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address);
-    void onTransactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
-
-signals:
-    void balanceUpdated(quint64 balance, quint64 spendable);
-    void blockchainSync(int height, int target);
-    void refreshSync(int height, int target);
-    void synchronized();
-    void walletRefreshed();
-    void transactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid);
-    void createTransactionError(QString message);
-    void createTransactionCancelled(const QVector<QString> &address, quint64 amount);
-    void createTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address);
-    void initiateTransaction();
-    void endTransaction();
-    void deviceButtonRequest(quint64 code);
-    void deviceButtonPressed();
-    void deviceError(const QString &message);
-    void keysCorrupted();
-    void selectedInputsChanged(const QStringList &selectedInputs);
-
-private:
-    DaemonRpc *m_rpc;
-    QTimer m_storeTimer;
-    QStringList m_selectedInputs;
-};
-
-#endif //FEATHER_APPCONTEXT_H
diff --git a/src/assets/tor2/tor b/src/assets/tor2/tor
new file mode 100755 (executable)
index 0000000..23162a8
Binary files /dev/null and b/src/assets/tor2/tor differ
index ad24c2499e0d4c8ba5be102ce9c5639ccc89f9a1..68fae9194d4320db59ba298b50d1b4d3d1a34381 100644 (file)
@@ -7,23 +7,25 @@
 #include <QMenu>
 
 #include "libwalletqt/SubaddressAccount.h"
+#include "libwalletqt/WalletManager.h"
 #include "model/ModelUtils.h"
 #include "utils/Icons.h"
+#include "utils/Utils.h"
 
-AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
+AccountSwitcherDialog::AccountSwitcherDialog(Wallet *wallet, QWidget *parent)
     : WindowModalDialog(parent)
     , ui(new Ui::AccountSwitcherDialog)
-    , m_ctx(std::move(ctx))
-    , m_model(m_ctx->wallet->subaddressAccountModel())
+    , m_wallet(wallet)
+    , m_model(wallet->subaddressAccountModel())
     , m_proxyModel(new SubaddressAccountProxyModel(this))
 {
     ui->setupUi(this);
 
-    m_ctx->wallet->subaddressAccount()->refresh();
+    m_wallet->subaddressAccount()->refresh();
     m_proxyModel->setSourceModel(m_model);
 
     ui->label_totalBalance->setFont(ModelUtils::getMonospaceFont());
-    ui->label_totalBalance->setText(WalletManager::displayAmount(m_ctx->wallet->balanceAll()));
+    ui->label_totalBalance->setText(WalletManager::displayAmount(m_wallet->balanceAll()));
 
     this->setWindowModality(Qt::WindowModal);
 
@@ -43,12 +45,12 @@ AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWi
     connect(ui->accounts, &QTreeView::customContextMenuRequested, this, &AccountSwitcherDialog::showContextMenu);
 
     connect(ui->btn_newAccount, &QPushButton::clicked, [this]{
-       m_ctx->wallet->addSubaddressAccount("New account");
-       m_ctx->wallet->subaddressAccount()->refresh();
+       m_wallet->addSubaddressAccount("New account");
+       m_wallet->subaddressAccount()->refresh();
     });
 
-    connect(m_ctx->wallet, &Wallet::currentSubaddressAccountChanged, this, &AccountSwitcherDialog::updateSelection);
-    connect(m_ctx->wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection);
+    connect(m_wallet, &Wallet::currentSubaddressAccountChanged, this, &AccountSwitcherDialog::updateSelection);
+    connect(m_wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection);
 
     this->updateSelection();
 }
@@ -59,7 +61,7 @@ void AccountSwitcherDialog::switchAccount() {
         return;
     }
 
-    m_ctx->wallet->switchSubaddressAccount(row->getRowId());
+    m_wallet->switchSubaddressAccount(row->getRowId());
 }
 
 void AccountSwitcherDialog::copyLabel() {
@@ -81,13 +83,13 @@ void AccountSwitcherDialog::copyBalance() {
 }
 
 void AccountSwitcherDialog::editLabel() {
-    QModelIndex index = ui->accounts->currentIndex().siblingAtColumn(m_ctx->wallet->subaddressAccountModel()->Column::Label);
+    QModelIndex index = ui->accounts->currentIndex().siblingAtColumn(m_wallet->subaddressAccountModel()->Column::Label);
     ui->accounts->setCurrentIndex(index);
     ui->accounts->edit(index);
 }
 
 void AccountSwitcherDialog::updateSelection() {
-    QModelIndex index = m_model->index(m_ctx->wallet->currentSubaddressAccount(), 0);
+    QModelIndex index = m_model->index(m_wallet->currentSubaddressAccount(), 0);
     ui->accounts->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
 }
 
@@ -108,7 +110,7 @@ void AccountSwitcherDialog::showContextMenu(const QPoint &point) {
 
 Monero::SubaddressAccountRow* AccountSwitcherDialog::currentEntry() {
     QModelIndex index = m_proxyModel->mapToSource(ui->accounts->currentIndex());
-    return m_ctx->wallet->subaddressAccountModel()->entryFromIndex(index);
+    return m_wallet->subaddressAccountModel()->entryFromIndex(index);
 }
 
 AccountSwitcherDialog::~AccountSwitcherDialog() = default;
index 5fea3deb5d3a0c0ea2abf53119034956bc2116f6..329de74b5add8cd7a408432d2ce4293b8c586102 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
+#include "libwalletqt/Wallet.h"
 #include "components.h"
 #include "model/SubaddressAccountModel.h"
 
@@ -19,7 +19,7 @@ class AccountSwitcherDialog : public WindowModalDialog
     Q_OBJECT
 
 public:
-    explicit AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit AccountSwitcherDialog(Wallet *wallet, QWidget *parent = nullptr);
     ~AccountSwitcherDialog() override;
 
 private slots:
@@ -35,7 +35,7 @@ private:
     Monero::SubaddressAccountRow* currentEntry();
 
     QScopedPointer<Ui::AccountSwitcherDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     SubaddressAccountModel *m_model;
     SubaddressAccountProxyModel *m_proxyModel;
 };
index 915b545e7255e530a14d42bf2b66ecd6a0a54143..05e8382153c6ffe181891a576088a4241f380866 100644 (file)
@@ -5,15 +5,18 @@
 #include "ui_DebugInfoDialog.h"
 
 #include "config-feather.h"
+#include "utils/AppData.h"
 #include "utils/os/tails.h"
+#include "utils/os/whonix.h"
 #include "utils/TorManager.h"
 #include "utils/WebsocketClient.h"
 #include "utils/WebsocketNotifier.h"
 
-DebugInfoDialog::DebugInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
+DebugInfoDialog::DebugInfoDialog(Wallet *wallet, Nodes *nodes, QWidget *parent)
         : WindowModalDialog(parent)
         , ui(new Ui::DebugInfoDialog)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
+        , m_nodes(nodes)
 {
     ui->setupUi(this);
 
@@ -47,16 +50,16 @@ void DebugInfoDialog::updateInfo() {
 
     ui->label_featherVersion->setText(QString("%1-%2").arg(FEATHER_VERSION, FEATHER_COMMIT));
 
-    ui->label_walletHeight->setText(QString::number(m_ctx->wallet->blockChainHeight()));
-    ui->label_daemonHeight->setText(QString::number(m_ctx->wallet->daemonBlockChainHeight()));
-    ui->label_targetHeight->setText(QString::number(m_ctx->wallet->daemonBlockChainTargetHeight()));
-    QDateTime restoreDate = appData()->restoreHeights[constants::networkType]->heightToDate(m_ctx->wallet->getWalletCreationHeight());
-    ui->label_restoreHeight->setText(QString("%1 (%2)").arg(QString::number(m_ctx->wallet->getWalletCreationHeight()), restoreDate.toString("yyyy-MM-dd")));
-    ui->label_synchronized->setText(m_ctx->wallet->isSynchronized() ? "True" : "False");
+    ui->label_walletHeight->setText(QString::number(m_wallet->blockChainHeight()));
+    ui->label_daemonHeight->setText(QString::number(m_wallet->daemonBlockChainHeight()));
+    ui->label_targetHeight->setText(QString::number(m_wallet->daemonBlockChainTargetHeight()));
+    QDateTime restoreDate = appData()->restoreHeights[constants::networkType]->heightToDate(m_wallet->getWalletCreationHeight());
+    ui->label_restoreHeight->setText(QString("%1 (%2)").arg(QString::number(m_wallet->getWalletCreationHeight()), restoreDate.toString("yyyy-MM-dd")));
+    ui->label_synchronized->setText(m_wallet->isSynchronized() ? "True" : "False");
 
-    auto node = m_ctx->nodes->connection();
+    auto node = m_nodes->connection();
     ui->label_remoteNode->setText(node.toAddress());
-    ui->label_walletStatus->setText(this->statusToString(m_ctx->wallet->connectionStatus()));
+    ui->label_walletStatus->setText(this->statusToString(m_wallet->connectionStatus()));
     QString websocketStatus = Utils::QtEnumToString(websocketNotifier()->websocketClient.webSocket.state()).remove("State");
     if (config()->get(Config::disableWebsocket).toBool()) {
         websocketStatus = "Disabled";
@@ -66,16 +69,16 @@ void DebugInfoDialog::updateInfo() {
     ui->label_torLevel->setText(config()->get(Config::torPrivacyLevel).toString());
 
     QString seedType = [this](){
-        if (m_ctx->wallet->isHwBacked())
+        if (m_wallet->isHwBacked())
             return QString("Hardware");
-        return QString("%1 word").arg(m_ctx->wallet->seedLength());
+        return QString("%1 word").arg(m_wallet->seedLength());
     }();
 
     QString deviceType = [this](){
-        if (m_ctx->wallet->isHwBacked()) {
-            if (m_ctx->wallet->isLedger())
+        if (m_wallet->isHwBacked()) {
+            if (m_wallet->isLedger())
                 return "Ledger";
-            else if (m_ctx->wallet->isTrezor())
+            else if (m_wallet->isTrezor())
                 return "Trezor";
             else
                 return "Unknown";
@@ -85,15 +88,15 @@ void DebugInfoDialog::updateInfo() {
         }
     }();
 
-    QString networkType = Utils::QtEnumToString(m_ctx->wallet->nettype());
+    QString networkType = Utils::QtEnumToString(m_wallet->nettype());
     if (config()->get(Config::offlineMode).toBool()) {
         networkType += " (offline)";
     }
     ui->label_netType->setText(networkType);
     ui->label_seedType->setText(seedType);
     ui->label_deviceType->setText(deviceType);
-    ui->label_viewOnly->setText(m_ctx->wallet->viewOnly() ? "True" : "False");
-    ui->label_primaryOnly->setText(m_ctx->wallet->balance(0) == m_ctx->wallet->balanceAll() ? "True" : "False");
+    ui->label_viewOnly->setText(m_wallet->viewOnly() ? "True" : "False");
+    ui->label_primaryOnly->setText(m_wallet->balance(0) == m_wallet->balanceAll() ? "True" : "False");
 
     QString os = QSysInfo::prettyProductName();
     if (TailsOS::detect()) {
index a3224a4a598002b65154e02c2235e965f3d4f6d1..53cb31ff655a29590b0c8d404edcbff9c8d46ea9 100644 (file)
@@ -6,9 +6,9 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
 #include "libwalletqt/Wallet.h"
+#include "utils/nodes.h"
 
 namespace Ui {
     class DebugInfoDialog;
@@ -19,7 +19,7 @@ class DebugInfoDialog : public WindowModalDialog
     Q_OBJECT
 
 public:
-    explicit DebugInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit DebugInfoDialog(Wallet *wallet, Nodes *nodes, QWidget *parent = nullptr);
     ~DebugInfoDialog() override;
 
 private:
@@ -28,7 +28,8 @@ private:
     void updateInfo();
 
     QScopedPointer<Ui::DebugInfoDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
+    Nodes *m_nodes;
 
     QTimer m_updateTimer;
 };
index 149dc7638a9ef6f5aa55541fee6345faee1948f7..1f459a3ff45b55d7a90e6957b9e853e17650cc03 100644 (file)
@@ -4,7 +4,7 @@
 #include "KeysDialog.h"
 #include "ui_KeysDialog.h"
 
-KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
+KeysDialog::KeysDialog(Wallet *wallet, QWidget *parent)
     : WindowModalDialog(parent)
     , ui(new Ui::KeysDialog)
 {
@@ -12,12 +12,12 @@ KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
 
     QString unavailable = "Unavailable: Key is stored on hardware device";
 
-    ui->label_restoreHeight->setText(QString::number(ctx->wallet->getWalletCreationHeight()));
-    ui->label_primaryAddress->setText(ctx->wallet->address(0, 0));
-    ui->label_secretSpendKey->setText(ctx->wallet->isHwBacked() ? unavailable : ctx->wallet->getSecretSpendKey());
-    ui->label_secretViewKey->setText(ctx->wallet->getSecretViewKey());
-    ui->label_publicSpendKey->setText(ctx->wallet->getPublicSpendKey());
-    ui->label_publicViewKey->setText(ctx->wallet->getPublicViewKey());
+    ui->label_restoreHeight->setText(QString::number(wallet->getWalletCreationHeight()));
+    ui->label_primaryAddress->setText(wallet->address(0, 0));
+    ui->label_secretSpendKey->setText(wallet->isHwBacked() ? unavailable : wallet->getSecretSpendKey());
+    ui->label_secretViewKey->setText(wallet->getSecretViewKey());
+    ui->label_publicSpendKey->setText(wallet->getPublicSpendKey());
+    ui->label_publicViewKey->setText(wallet->getPublicViewKey());
 
     this->adjustSize();
 }
index 1a92eaf0e77438080e0df5f09c6494f4f6435002..98b38bee2b4e6c058d5c08f885be3d5eb51258d4 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class KeysDialog;
@@ -18,7 +18,7 @@ class KeysDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit KeysDialog(Wallet *wallet, QWidget *parent = nullptr);
     ~KeysDialog() override;
 
 private:
index 6457676ece7c8584c3a9ef882d24258cf3b73912..1899c386439090da867cf2317a5223a381c70911 100644 (file)
 #include <QRegularExpressionValidator>
 
 #include "WalletManager.h"
+#include "utils/Utils.h"
 
-PaymentRequestDialog::PaymentRequestDialog(QWidget *parent, QSharedPointer<AppContext> ctx, QString address)
+PaymentRequestDialog::PaymentRequestDialog(QWidget *parent, Wallet *wallet, QString address)
     : WindowModalDialog(parent)
     , ui(new Ui::PaymentRequestDialog)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
     , m_address(std::move(address))
 {
     ui->setupUi(this);
@@ -45,7 +46,7 @@ void PaymentRequestDialog::updatePaymentRequest() {
     QString recipient = ui->line_recipient->text();
     quint64 amount = WalletManager::amountFromString(ui->line_amountXMR->text());
 
-    QString uri = m_ctx->wallet->make_uri(m_address, amount, description, recipient);
+    QString uri = m_wallet->make_uri(m_address, amount, description, recipient);
 
     ui->line_paymentRequestUri->setText(uri);
     ui->line_paymentRequestUri->setCursorPosition(0);
index f60c8118593e6bae64162871d654385a9536b717..9a8eda41917d7ad3b5fc7f39df066fbf537bf4ff 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
+#include "libwalletqt/Wallet.h"
 #include "qrcode/QrCode.h"
 
 namespace Ui {
@@ -19,7 +19,7 @@ class PaymentRequestDialog : public WindowModalDialog
     Q_OBJECT
 
 public:
-    explicit PaymentRequestDialog(QWidget *parent, QSharedPointer<AppContext> ctx, QString address);
+    explicit PaymentRequestDialog(QWidget *parent, Wallet *wallet, QString address);
     ~PaymentRequestDialog() override;
 
 private slots:
@@ -30,7 +30,7 @@ private slots:
 
 private:
     QScopedPointer<Ui::PaymentRequestDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     QString m_address;
     QrCode *m_qrCode;
 };
index 60fc0bafb44403ca5623cbf10f25367787bc1130..8fcd1ac7b216e0dcb99a73dfa2ddda4b36503e01 100644 (file)
@@ -6,26 +6,26 @@
 
 #include "constants.h"
 
-SeedDialog::SeedDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
+SeedDialog::SeedDialog(Wallet *wallet, QWidget *parent)
     : WindowModalDialog(parent)
     , ui(new Ui::SeedDialog)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
 {
     ui->setupUi(this);
     ui->label_seedIcon->setPixmap(QPixmap(":/assets/images/seed.png").scaledToWidth(64, Qt::SmoothTransformation));
 
-    ui->label_restoreHeight->setText(QString::number(m_ctx->wallet->getWalletCreationHeight()));
+    ui->label_restoreHeight->setText(QString::number(m_wallet->getWalletCreationHeight()));
 
-    if (m_ctx->wallet->getSeedLanguage().isEmpty()) {
+    if (m_wallet->getSeedLanguage().isEmpty()) {
         qDebug() << "No seed language set, using default";
-        m_ctx->wallet->setSeedLanguage(constants::seedLanguage);
+        m_wallet->setSeedLanguage(constants::seedLanguage);
     }
 
-    QString seedOffset = m_ctx->wallet->getCacheAttribute("feather.seedoffset");
-    QString seed = m_ctx->wallet->getCacheAttribute("feather.seed");
-    auto seedLength = m_ctx->wallet->seedLength();
+    QString seedOffset = m_wallet->getCacheAttribute("feather.seedoffset");
+    QString seed = m_wallet->getCacheAttribute("feather.seed");
+    auto seedLength = m_wallet->seedLength();
 
-    QString seed_25_words = m_ctx->wallet->getSeed(seedOffset);
+    QString seed_25_words = m_wallet->getSeed(seedOffset);
 
     if (seedLength >= 24) {
         ui->check_toggleSeedType->hide();
index e2bdc2a5db9fc09aef7030c890ac10aff7559e40..a293b1737520c802dd4a55f85ec5bf40b878927d 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class SeedDialog;
@@ -18,14 +18,14 @@ class SeedDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit SeedDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit SeedDialog(Wallet *wallet, QWidget *parent = nullptr);
     ~SeedDialog() override;
 
 private:
     void setSeed(const QString &seed);
 
     QScopedPointer<Ui::SeedDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 };
 
 
index 9710449dd00123554b535322200433e388daa0da..50ede473524d52e86735918330fa2528b294ac6d 100644 (file)
@@ -8,14 +8,14 @@
 
 #include "utils/NetworkManager.h"
 
-TxBroadcastDialog::TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex)
+TxBroadcastDialog::TxBroadcastDialog(QWidget *parent, Nodes *nodes, const QString &transactionHex)
         : WindowModalDialog(parent)
         , ui(new Ui::TxBroadcastDialog)
-        , m_ctx(std::move(ctx))
+        , m_nodes(nodes)
 {
     ui->setupUi(this);
 
-    auto node = m_ctx->nodes->connection();
+    auto node = m_nodes->connection();
     m_rpc = new DaemonRpc(this, node.toAddress());
 
     connect(ui->btn_Broadcast, &QPushButton::clicked, this, &TxBroadcastDialog::broadcastTx);
@@ -33,7 +33,7 @@ TxBroadcastDialog::TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext>
 void TxBroadcastDialog::broadcastTx() {
     QString tx = ui->transaction->toPlainText();
 
-    FeatherNode node = ui->radio_useCustom->isChecked() ? FeatherNode(ui->customNode->text()) : m_ctx->nodes->connection();
+    FeatherNode node = ui->radio_useCustom->isChecked() ? FeatherNode(ui->customNode->text()) : m_nodes->connection();
 
     m_rpc->setDaemonAddress(node.toURL());
     m_rpc->sendRawTransaction(tx);
index 4d826321d38a1d00f2dc2b939f802d845051e337..f8ce21237fbc335beb45c78a3160a427769d6e50 100644 (file)
@@ -6,9 +6,9 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
 #include "utils/daemonrpc.h"
+#include "utils/nodes.h"
 
 namespace Ui {
     class TxBroadcastDialog;
@@ -19,7 +19,7 @@ class TxBroadcastDialog : public WindowModalDialog
     Q_OBJECT
 
 public:
-    explicit TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex = "");
+    explicit TxBroadcastDialog(QWidget *parent, Nodes *nodes, const QString &transactionHex = "");
     ~TxBroadcastDialog() override;
 
 private slots:
@@ -28,7 +28,7 @@ private slots:
 
 private:
     QScopedPointer<Ui::TxBroadcastDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Nodes *m_nodes;
     DaemonRpc *m_rpc;
 };
 
index 9ab1d696886945124b67c86289bead10b0085419..0f2cafa6bc0b02afa0bfaba5ee5e05c953e7e2e4 100644 (file)
 #include "dialog/QrCodeDialog.h"
 #include "libwalletqt/Input.h"
 #include "libwalletqt/Transfer.h"
+#include "libwalletqt/WalletManager.h"
 #include "model/ModelUtils.h"
 #include "qrcode/QrCode.h"
+#include "utils/AppData.h"
+#include "utils/config.h"
+#include "utils/Utils.h"
 
-TxConfAdvDialog::TxConfAdvDialog(QSharedPointer<AppContext> ctx, const QString &description, QWidget *parent)
+TxConfAdvDialog::TxConfAdvDialog(Wallet *wallet, const QString &description, QWidget *parent)
     : WindowModalDialog(parent)
     , ui(new Ui::TxConfAdvDialog)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
     , m_exportUnsignedMenu(new QMenu(this))
     , m_exportSignedMenu(new QMenu(this))
     , m_exportTxKeyMenu(new QMenu(this))
@@ -65,7 +69,7 @@ void TxConfAdvDialog::setTransaction(PendingTransaction *tx, bool isSigned) {
     PendingTransactionInfo *ptx = m_tx->transaction(0); //Todo: support split transactions
 
     // TODO: implement hasTxKey()
-    if (!m_ctx->wallet->isHwBacked() && m_tx->transaction(0)->txKey() == "0100000000000000000000000000000000000000000000000000000000000000") {
+    if (!m_wallet->isHwBacked() && m_tx->transaction(0)->txKey() == "0100000000000000000000000000000000000000000000000000000000000000") {
         ui->btn_exportTxKey->hide();
     }
 
@@ -148,7 +152,7 @@ void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
     for (const auto& o: outputs) {
         auto address = o->address();
         auto amount = WalletManager::displayAmount(o->amount());
-        auto index = m_ctx->wallet->subaddressIndex(address);
+        auto index = m_wallet->subaddressIndex(address);
         cursor.insertText(address, Utils::addressTextFormat(index, o->amount()));
         cursor.insertText(QString(" %1").arg(amount), QTextCharFormat());
         cursor.insertBlock();
@@ -205,7 +209,7 @@ void TxConfAdvDialog::signedCopy() {
 }
 
 void TxConfAdvDialog::txKeyCopy() {
-    if (m_ctx->wallet->isHwBacked()) {
+    if (m_wallet->isHwBacked()) {
         QMessageBox::warning(this, "Unable to get tx private key", "Unable to get tx secret key: wallet is backed by hardware device");
         return;
     }
@@ -218,15 +222,15 @@ void TxConfAdvDialog::signedQrCode() {
 
 void TxConfAdvDialog::broadcastTransaction() {
     if (m_tx == nullptr) return;
-    m_ctx->commitTransaction(m_tx, ui->line_description->text());
+    m_wallet->commitTransaction(m_tx, ui->line_description->text());
     QDialog::accept();
 }
 
 void TxConfAdvDialog::closeDialog() {
     if (m_tx != nullptr)
-        m_ctx->wallet->disposeTransaction(m_tx);
+        m_wallet->disposeTransaction(m_tx);
     if (m_utx != nullptr)
-        m_ctx->wallet->disposeTransaction(m_utx);
+        m_wallet->disposeTransaction(m_utx);
     QDialog::reject();
 }
 
index 803fba960a33b77ae4cb3927fc4bd95470d41407..443a455d3623b7b42bed3608f604c010e5d8c68e 100644 (file)
@@ -9,9 +9,9 @@
 #include <QStandardItemModel>
 #include <QTextCharFormat>
 
-#include "appcontext.h"
 #include "components.h"
 #include "libwalletqt/PendingTransaction.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class TxConfAdvDialog;
@@ -22,7 +22,7 @@ class TxConfAdvDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit TxConfAdvDialog(QSharedPointer<AppContext> ctx, const QString &description, QWidget *parent = nullptr);
+    explicit TxConfAdvDialog(Wallet *wallet, const QString &description, QWidget *parent = nullptr);
     ~TxConfAdvDialog() override;
 
     void setTransaction(PendingTransaction *tx, bool isSigned = true); // #TODO: have libwallet return a UnsignedTransaction, this is just dumb
@@ -46,7 +46,7 @@ private:
     void txKeyCopy();
 
     QScopedPointer<Ui::TxConfAdvDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     PendingTransaction *m_tx = nullptr;
     UnsignedTransaction *m_utx = nullptr;
     QMenu *m_exportUnsignedMenu;
index 1b345d4bf838444b9e637fdf8aa173abb9e7d461..0254a952a685d84f6a057ddc10ee7606e542e7e0 100644 (file)
 #include "TxConfAdvDialog.h"
 #include "utils/AppData.h"
 #include "utils/ColorScheme.h"
+#include "utils/config.h"
 
-TxConfDialog::TxConfDialog(QSharedPointer<AppContext> ctx, PendingTransaction *tx, const QString &address, const QString &description, QWidget *parent)
+TxConfDialog::TxConfDialog(Wallet *wallet, PendingTransaction *tx, const QString &address, const QString &description, QWidget *parent)
         : WindowModalDialog(parent)
         , ui(new Ui::TxConfDialog)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
         , m_tx(tx)
         , m_address(address)
         , m_description(description)
@@ -53,7 +54,7 @@ TxConfDialog::TxConfDialog(QSharedPointer<AppContext> ctx, PendingTransaction *t
     ui->label_fee->setText(QString("%1 (%2 %3)").arg(amounts[1], amounts_fiat[1], preferredCur));
     ui->label_total->setText(QString("%1 (%2 %3)").arg(amounts[2], amounts_fiat[2], preferredCur));
 
-    auto subaddressIndex = m_ctx->wallet->subaddressIndex(address);
+    auto subaddressIndex = m_wallet->subaddressIndex(address);
     QString addressExtra;
 
     ui->label_address->setText(ModelUtils::displayAddress(address, 2));
index 7e148f9fdeb3bcb9c590ef5fec899e32aad3fea2..d3a62861dc7ae052014c50ea22b81bc0f6ed886c 100644 (file)
@@ -6,10 +6,10 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
 #include "libwalletqt/PendingTransaction.h"
 #include "libwalletqt/WalletManager.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class TxConfDialog;
@@ -20,7 +20,7 @@ class TxConfDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit TxConfDialog(QSharedPointer<AppContext> ctx, PendingTransaction *tx, const QString &address, const QString &description, QWidget *parent = nullptr);
+    explicit TxConfDialog(Wallet *wallet, PendingTransaction *tx, const QString &address, const QString &description, QWidget *parent = nullptr);
     ~TxConfDialog() override;
 
     bool showAdvanced = false;
@@ -29,7 +29,7 @@ private:
     void setShowAdvanced();
 
     QScopedPointer<Ui::TxConfDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     PendingTransaction *m_tx;
     QString m_address;
     QString m_description;
index f6a82178cbcb7cde1640a12c5e6bd32103d9db2f..c702ac597faf987834025627f667d787f899b71d 100644 (file)
@@ -8,10 +8,10 @@
 
 #include "utils/NetworkManager.h"
 
-TxImportDialog::TxImportDialog(QWidget *parent, QSharedPointer<AppContext> ctx)
+TxImportDialog::TxImportDialog(QWidget *parent, Wallet *wallet)
         : WindowModalDialog(parent)
         , ui(new Ui::TxImportDialog)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
 {
     ui->setupUi(this);
 
@@ -23,15 +23,15 @@ TxImportDialog::TxImportDialog(QWidget *parent, QSharedPointer<AppContext> ctx)
 void TxImportDialog::onImport() {
     QString txid = ui->line_txid->text();
 
-    if (m_ctx->wallet->haveTransaction(txid)) {
+    if (m_wallet->haveTransaction(txid)) {
         QMessageBox::warning(this, "Warning", "This transaction already exists in the wallet. "
                                               "If you can't find it in your history, "
                                               "check if it belongs to a different account (Wallet -> Account)");
         return;
     }
 
-    if (m_ctx->wallet->importTransaction(txid)) {
-        if (!m_ctx->wallet->haveTransaction(txid)) {
+    if (m_wallet->importTransaction(txid)) {
+        if (!m_wallet->haveTransaction(txid)) {
             QMessageBox::warning(this, "Import transaction", "This transaction does not belong to this wallet.");
             return;
         }
@@ -39,7 +39,7 @@ void TxImportDialog::onImport() {
     } else {
         QMessageBox::warning(this, "Import transaction", "Transaction import failed.");
     }
-    m_ctx->refreshModels();
+    m_wallet->refreshModels();
 }
 
 TxImportDialog::~TxImportDialog() = default;
index 63733284809a5c38fbe4a4e815c675eaa236e439..2b9e452ef1f7c15688b03cde88bdcdb4d2509525 100644 (file)
@@ -6,9 +6,9 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
 #include "utils/daemonrpc.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class TxImportDialog;
@@ -19,7 +19,7 @@ class TxImportDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit TxImportDialog(QWidget *parent, QSharedPointer<AppContext> ctx);
+    explicit TxImportDialog(QWidget *parent, Wallet *wallet);
     ~TxImportDialog() override;
 
 private slots:
@@ -27,7 +27,7 @@ private slots:
 
 private:
     QScopedPointer<Ui::TxImportDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 };
 
 
index 5a80ffda7c9def6c55a8f5e95d49bba077e44d3e..4f982128b36af5f2630ac54f5096ce60c17bb744 100644 (file)
@@ -7,7 +7,6 @@
 #include <QMessageBox>
 #include <QScrollBar>
 
-#include "appcontext.h"
 #include "config.h"
 #include "constants.h"
 #include "libwalletqt/Coins.h"
 #include "Utils.h"
 #include "utils/Icons.h"
 
-TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txInfo, QWidget *parent)
+TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent)
     : QDialog(parent)
     , ui(new Ui::TxInfoDialog)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
     , m_txInfo(txInfo)
-    , m_txProofDialog(new TxProofDialog(this, m_ctx, txInfo))
+    , m_txProofDialog(new TxProofDialog(this, wallet, txInfo))
 {
     ui->setupUi(this);
 
@@ -39,7 +38,7 @@ TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txIn
     connect(ui->btn_CopyTxKey, &QPushButton::clicked, this, &TxInfoDialog::copyTxKey);
     connect(ui->btn_createTxProof, &QPushButton::clicked, this, &TxInfoDialog::createTxProof);
 
-    connect(m_ctx->wallet, &Wallet::newBlock, this, &TxInfoDialog::updateData);
+    connect(m_wallet, &Wallet::newBlock, this, &TxInfoDialog::updateData);
 
     this->setData(txInfo);
 
@@ -79,7 +78,7 @@ TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txIn
         for (const auto& transfer : transfers) {
             auto address = transfer->address();
             auto amount = WalletManager::displayAmount(transfer->amount());
-            auto index = m_ctx->wallet->subaddressIndex(address);
+            auto index = m_wallet->subaddressIndex(address);
             cursor.insertText(address, Utils::addressTextFormat(index, transfer->amount()));
             cursor.insertText(QString(" %1").arg(amount), QTextCharFormat());
             cursor.insertBlock();
@@ -151,7 +150,7 @@ void TxInfoDialog::setData(TransactionInfo *tx) {
 }
 
 void TxInfoDialog::updateData() {
-    TransactionInfo *tx = m_ctx->wallet->history()->transaction(m_txid);
+    TransactionInfo *tx = m_wallet->history()->transaction(m_txid);
     if (!tx) return;
     this->setData(tx);
 }
@@ -161,12 +160,12 @@ void TxInfoDialog::copyTxID() {
 }
 
 void TxInfoDialog::copyTxKey() {
-    if (m_ctx->wallet->isHwBacked()) {
+    if (m_wallet->isHwBacked()) {
         QMessageBox::warning(this, "Unable to get tx private key", "Unable to get tx secret key: wallet is backed by hardware device");
         return;
     }
 
-    m_ctx->wallet->getTxKeyAsync(m_txid, [this](QVariantMap map){
+    m_wallet->getTxKeyAsync(m_txid, [this](QVariantMap map){
         QString txKey = map.value("tx_key").toString();
         if (txKey.isEmpty()) {
             QMessageBox::warning(this, "Unable to copy transaction key", "Transaction key unknown");
index 2f1cc797cb24f2be80294c20039cd8002fef600b..b80e9e4a5614e958b2c78c44868246b351b33a4d 100644 (file)
@@ -9,7 +9,6 @@
 #include <QTextEdit>
 #include <QSvgWidget>
 
-#include "appcontext.h"
 #include "dialog/TxProofDialog.h"
 
 namespace Ui {
@@ -21,7 +20,7 @@ class TxInfoDialog : public QDialog
 Q_OBJECT
 
 public:
-    explicit TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txInfo, QWidget *parent = nullptr);
+    explicit TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent = nullptr);
     ~TxInfoDialog() override;
 
 signals:
@@ -37,7 +36,7 @@ private:
     void viewOnBlockExplorer();
 
     QScopedPointer<Ui::TxInfoDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     TransactionInfo *m_txInfo;
     TxProofDialog *m_txProofDialog;
     QString m_txid;
index bff827ecc96f5002b1e14086737cd3b5eeb34d9f..b3657875ac15db2b8041a51c0c3f491e3e22df0a 100644 (file)
 #include "utils/Icons.h"
 #include "utils/Utils.h"
 
-TxProofDialog::TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, TransactionInfo *txInfo)
+TxProofDialog::TxProofDialog(QWidget *parent, Wallet *wallet, TransactionInfo *txInfo)
     : WindowModalDialog(parent)
     , ui(new Ui::TxProofDialog)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
 {
     ui->setupUi(this);
 
@@ -26,7 +26,7 @@ TxProofDialog::TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, Tr
     }
 
     for (auto const &s: txInfo->subaddrIndex()) {
-        m_InDestinations.push_back(m_ctx->wallet->address(txInfo->subaddrAccount(), s));
+        m_InDestinations.push_back(m_wallet->address(txInfo->subaddrAccount(), s));
     }
 
     // Due to some logic in core we can't create OutProofs
@@ -57,7 +57,7 @@ TxProofDialog::TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, Tr
 void TxProofDialog::getTxKey() {
     if (!m_txKey.isEmpty()) return;
 
-    m_ctx->wallet->getTxKeyAsync(m_txid, [this](QVariantMap map){
+    m_wallet->getTxKeyAsync(m_txid, [this](QVariantMap map){
         m_txKey = map.value("tx_key").toString();
     });
 }
@@ -75,7 +75,7 @@ void TxProofDialog::selectSpendProof() {
         return;
     }
 
-    if (m_ctx->wallet->isHwBacked()) {
+    if (m_wallet->isHwBacked()) {
         this->showWarning("SpendProof creation is not supported on this hardware device.");
         return;
     }
@@ -150,7 +150,7 @@ void TxProofDialog::showWarning(const QString &message) {
 void TxProofDialog::getFormattedProof() {
     QString message = ui->message->toPlainText();
     QString address = ui->combo_address->currentText();
-    QString nettype = Utils::QtEnumToString(m_ctx->wallet->nettype()).toLower();
+    QString nettype = Utils::QtEnumToString(m_wallet->nettype()).toLower();
     nettype = nettype.replace(0, 1, nettype[0].toUpper()); // Capitalize first letter
 
     TxProof proof = this->getProof();
@@ -231,12 +231,12 @@ TxProof TxProofDialog::getProof() {
     TxProof proof = [this, message, address]{
         switch (m_mode) {
             case Mode::SpendProof: {
-                return m_ctx->wallet->getSpendProof(m_txid, message);
+                return m_wallet->getSpendProof(m_txid, message);
             }
             case Mode::OutProof:
             case Mode::InProof:
             default: { // Todo: split this into separate functions
-                return m_ctx->wallet->getTxProof(m_txid, address, message);
+                return m_wallet->getTxProof(m_txid, address, message);
             }
         }
     }();
index cb697199e4aba995a68b755a912f4b61a1c0e9e6..8f14d977bf4a850c745776310b70cbc2f9624f8f 100644 (file)
@@ -6,9 +6,9 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
 #include "libwalletqt/TransactionInfo.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class TxProofDialog;
@@ -19,7 +19,7 @@ class TxProofDialog : public WindowModalDialog
     Q_OBJECT
 
 public:
-    explicit TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, TransactionInfo *txid);
+    explicit TxProofDialog(QWidget *parent, Wallet *wallet, TransactionInfo *txid);
     ~TxProofDialog() override;
     void setTxId(const QString &txid);
     void getTxKey();
@@ -45,7 +45,7 @@ private:
     void showWarning(const QString &message);
 
     QScopedPointer<Ui::TxProofDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 
     QStringList m_OutDestinations;
     QStringList m_InDestinations;
index 65e428e147958db9e5dd30d7848a3b056dc390cb..1ea454908d215ac2acc892b588d0782797effd12 100644 (file)
@@ -8,21 +8,23 @@
 #include <QInputDialog>
 #include <QMessageBox>
 
-ViewOnlyDialog::ViewOnlyDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
+#include "utils/Utils.h"
+
+ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent)
     : WindowModalDialog(parent)
     , ui(new Ui::ViewOnlyDialog)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
 {
     ui->setupUi(this);
 
-    ui->label_restoreHeight->setText(QString::number(m_ctx->wallet->getWalletCreationHeight()));
-    ui->label_primaryAddress->setText(m_ctx->wallet->address(0, 0));
-    ui->label_secretViewKey->setText(m_ctx->wallet->getSecretViewKey());
+    ui->label_restoreHeight->setText(QString::number(m_wallet->getWalletCreationHeight()));
+    ui->label_primaryAddress->setText(m_wallet->address(0, 0));
+    ui->label_secretViewKey->setText(m_wallet->getSecretViewKey());
 
     connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboard);
     connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet);
 
-    if (m_ctx->wallet->viewOnly()) {
+    if (m_wallet->viewOnly()) {
         ui->btn_Save->setEnabled(false);
         ui->btn_Save->setToolTip("Wallet is already view-only");
     }
@@ -45,7 +47,7 @@ void ViewOnlyDialog::onWriteViewOnlyWallet(){
     if((bool)passwordDialog.exec())
         passwd = passwordDialog.textValue();
 
-    m_ctx->wallet->createViewOnly(fn, passwd);
+    m_wallet->createViewOnly(fn, passwd);
 
     QMessageBox::information(this, "Information", "View-only wallet successfully written to disk.");
 }
index 0954ade5876719c9f313bef1e104321251db90d9..08de23843c0378f08d97547a6556852c471b05e2 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class ViewOnlyDialog;
@@ -18,7 +18,7 @@ class ViewOnlyDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit ViewOnlyDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit ViewOnlyDialog(Wallet *wallet, QWidget *parent = nullptr);
     ~ViewOnlyDialog() override;
 
 private slots:
@@ -28,7 +28,7 @@ private:
     void copyToClipboard();
 
     QScopedPointer<Ui::ViewOnlyDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 };
 
 
index d245ea0adfd0085c95cd41f96177f59284d47795..97ed0d2d7cce3d159d5b1f8e3398b59b32dc153e 100644 (file)
@@ -8,81 +8,81 @@
 
 #include "model/ModelUtils.h"
 
-WalletCacheDebugDialog::WalletCacheDebugDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
+WalletCacheDebugDialog::WalletCacheDebugDialog(Wallet *wallet, QWidget *parent)
         : WindowModalDialog(parent)
         , ui(new Ui::WalletCacheDebugDialog)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
 {
     ui->setupUi(this);
 
     ui->output->setFont(ModelUtils::getMonospaceFont());
 
     connect(ui->m_blockchain, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printBlockchain());
+        this->setOutput(m_wallet->printBlockchain());
     });
 
     connect(ui->m_transfers, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printTransfers());
+        this->setOutput(m_wallet->printTransfers());
     });
 
     connect(ui->m_unconfirmed_payments, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printUnconfirmedPayments());
+        this->setOutput(m_wallet->printUnconfirmedPayments());
     });
 
     connect(ui->m_confirmed_txs, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printConfirmedTransferDetails());
+        this->setOutput(m_wallet->printConfirmedTransferDetails());
     });
 
     connect(ui->m_unconfirmed_txs, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printUnconfirmedTransferDetails());
+        this->setOutput(m_wallet->printUnconfirmedTransferDetails());
     });
 
     connect(ui->m_payments, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printPayments());
+        this->setOutput(m_wallet->printPayments());
     });
 
     connect(ui->m_pub_keys, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printPubKeys());
+        this->setOutput(m_wallet->printPubKeys());
     });
 
     connect(ui->m_tx_notes, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printTxNotes());
+        this->setOutput(m_wallet->printTxNotes());
     });
 
     connect(ui->m_subaddresses, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printSubaddresses());
+        this->setOutput(m_wallet->printSubaddresses());
     });
 
     connect(ui->m_subaddress_labels, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printSubaddressLabels());
+        this->setOutput(m_wallet->printSubaddressLabels());
     });
 
     connect(ui->m_additional_tx_keys, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printAdditionalTxKeys());
+        this->setOutput(m_wallet->printAdditionalTxKeys());
     });
 
     connect(ui->m_attributes, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printAttributes());
+        this->setOutput(m_wallet->printAttributes());
     });
 
     connect(ui->m_key_images, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printKeyImages());
+        this->setOutput(m_wallet->printKeyImages());
     });
 
     connect(ui->m_account_tags, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printAccountTags());
+        this->setOutput(m_wallet->printAccountTags());
     });
 
     connect(ui->m_tx_keys, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printTxKeys());
+        this->setOutput(m_wallet->printTxKeys());
     });
 
     connect(ui->m_address_book, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printAddressBook());
+        this->setOutput(m_wallet->printAddressBook());
     });
 
     connect(ui->m_scanned_pool_txs, &QRadioButton::pressed, [this]{
-        this->setOutput(m_ctx->wallet->printScannedPoolTxs());
+        this->setOutput(m_wallet->printScannedPoolTxs());
     });
 
     this->adjustSize();
index bee1510a495f7f4efbb07bd189b57867d5b1af24..13c6ed59ac922571d57e4443834325a6dce8aae1 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class WalletCacheDebugDialog;
@@ -18,14 +18,14 @@ class WalletCacheDebugDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit WalletCacheDebugDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit WalletCacheDebugDialog(Wallet *wallet, QWidget *parent = nullptr);
     ~WalletCacheDebugDialog() override;
 
 private:
     void setOutput(const QString &output);
 
     QScopedPointer<Ui::WalletCacheDebugDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 };
 
 
index b93df83c7612cf51a997eedf075fb9ab04581d35..d3a1d80fd08b091425e3abece91adf5932cb9503 100644 (file)
@@ -6,22 +6,24 @@
 
 #include <QDesktopServices>
 
-WalletInfoDialog::WalletInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
+#include "utils/Utils.h"
+
+WalletInfoDialog::WalletInfoDialog(Wallet *wallet, QWidget *parent)
     : WindowModalDialog(parent)
     , ui(new Ui::WalletInfoDialog)
-    , m_ctx(std::move(ctx))
+    , m_wallet(wallet)
 {
     ui->setupUi(this);
 
-    QFileInfo cache(m_ctx->wallet->cachePath());
+    QFileInfo cache(m_wallet->cachePath());
 
-    ui->label_walletName->setText(QFileInfo(m_ctx->wallet->cachePath()).fileName());
-    ui->label_netType->setText(Utils::QtEnumToString(m_ctx->wallet->nettype()));
-    ui->label_seedType->setText(QString("%1 word").arg(m_ctx->wallet->seedLength()));
-    ui->label_viewOnly->setText(m_ctx->wallet->viewOnly() ? "True" : "False");
-    ui->label_subaddressLookahead->setText(m_ctx->wallet->getSubaddressLookahead());
-    ui->label_keysFile->setText(m_ctx->wallet->keysPath());
-    ui->label_cacheFile->setText(m_ctx->wallet->cachePath());
+    ui->label_walletName->setText(QFileInfo(m_wallet->cachePath()).fileName());
+    ui->label_netType->setText(Utils::QtEnumToString(m_wallet->nettype()));
+    ui->label_seedType->setText(QString("%1 word").arg(m_wallet->seedLength()));
+    ui->label_viewOnly->setText(m_wallet->viewOnly() ? "True" : "False");
+    ui->label_subaddressLookahead->setText(m_wallet->getSubaddressLookahead());
+    ui->label_keysFile->setText(m_wallet->keysPath());
+    ui->label_cacheFile->setText(m_wallet->cachePath());
     ui->label_cacheSize->setText(QString("%1 MB").arg(QString::number(cache.size() / 1e6, 'f', 2)));
 
     connect(ui->btn_openWalletDir, &QPushButton::clicked, this, &WalletInfoDialog::openWalletDir);
@@ -40,7 +42,7 @@ WalletInfoDialog::WalletInfoDialog(QSharedPointer<AppContext> ctx, QWidget *pare
 }
 
 void WalletInfoDialog::openWalletDir() {
-    QFileInfo file(m_ctx->wallet->keysPath());
+    QFileInfo file(m_wallet->keysPath());
     QDesktopServices::openUrl(QUrl::fromLocalFile(file.absolutePath()));
 }
 
index b25af7061e5c54df96928c02fd3d80fe73c8a543..52bac9528703e3aa0068e2578acc788efdda7c46 100644 (file)
@@ -6,8 +6,8 @@
 
 #include <QDialog>
 
-#include "appcontext.h"
 #include "components.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class WalletInfoDialog;
@@ -18,14 +18,14 @@ class WalletInfoDialog : public WindowModalDialog
 Q_OBJECT
 
 public:
-    explicit WalletInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit WalletInfoDialog(Wallet *wallet, QWidget *parent = nullptr);
     ~WalletInfoDialog() override;
 
 private:
     void openWalletDir();
 
     QScopedPointer<Ui::WalletInfoDialog> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 };
 
 #endif //FEATHER_WALLETINFODIALOG_H
diff --git a/src/libwalletqt/CMakeLists.txt b/src/libwalletqt/CMakeLists.txt
deleted file mode 100644 (file)
index e69de29..0000000
index 6cbbc8942f9df846261ce66800c98caf0f9190e9..2ed4e36b0a162770327ec1e41373e96b9b08fbb6 100644 (file)
@@ -6,11 +6,16 @@
 #include <chrono>
 #include <thread>
 
-#include "TransactionHistory.h"
 #include "AddressBook.h"
+#include "Coins.h"
 #include "Subaddress.h"
 #include "SubaddressAccount.h"
-#include "Coins.h"
+#include "TransactionHistory.h"
+#include "WalletManager.h"
+
+#include "config.h"
+#include "constants.h"
+
 #include "model/TransactionHistoryModel.h"
 #include "model/TransactionHistoryProxyModel.h"
 #include "model/AddressBookModel.h"
 #include "utils/ScopeGuard.h"
 
 namespace {
-    static constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] = "feather.subaddress_account";
+    constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] = "feather.subaddress_account";
 }
 
-Wallet::Wallet(QObject * parent)
-        : Wallet(nullptr, parent)
-{
-}
-
-Wallet::ConnectionStatus Wallet::connectionStatus() const
+Wallet::Wallet(Monero::Wallet *wallet, QObject *parent)
+        : QObject(parent)
+        , m_walletImpl(wallet)
+        , m_history(new TransactionHistory(m_walletImpl->history(), this))
+        , m_historyModel(nullptr)
+        , m_addressBook(new AddressBook(m_walletImpl->addressBook(), this))
+        , m_addressBookModel(nullptr)
+        , m_daemonBlockChainHeight(0)
+        , m_daemonBlockChainTargetHeight(0)
+        , m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
+        , m_currentSubaddressAccount(0)
+        , m_subaddress(new Subaddress(m_walletImpl->subaddress(), this))
+        , m_subaddressAccount(new SubaddressAccount(m_walletImpl->subaddressAccount(), this))
+        , m_refreshNow(false)
+        , m_refreshEnabled(false)
+        , m_scheduler(this)
+        , m_useSSL(true)
+        , m_coins(new Coins(m_walletImpl->coins(), this))
+        , m_storeTimer(new QTimer(this))
 {
-    return m_connectionStatus;
-}
+    m_walletListener = new WalletListenerImpl(this);
+    m_walletImpl->setListener(m_walletListener);
+    m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
 
-QString Wallet::getSeed(const QString &seedOffset) const
-{
-    return QString::fromStdString(m_walletImpl->seed(seedOffset.toStdString()));
-}
+    m_addressBookModel = new AddressBookModel(this, m_addressBook);
+    m_subaddressModel = new SubaddressModel(this, m_subaddress);
+    m_subaddressAccountModel = new SubaddressAccountModel(this, m_subaddressAccount);
+    m_coinsModel = new CoinsModel(this, m_coins);
 
-qsizetype Wallet::seedLength() const
-{
-    auto seedLength = this->getCacheAttribute("feather.seed").split(" ", Qt::SkipEmptyParts).length();
-    return seedLength ? seedLength : 25;
-}
+    if (this->status() == Status_Ok) {
+        startRefreshThread();
 
-QString Wallet::getSeedLanguage() const
-{
-    return QString::fromStdString(m_walletImpl->getSeedLanguage());
-}
+        // Store the wallet every 2 minutes
+        m_storeTimer->start(2 * 60 * 1000);
+        connect(m_storeTimer, &QTimer::timeout, [this](){
+            this->storeSafer();
+        });
 
-void Wallet::setSeedLanguage(const QString &lang)
-{
-    m_walletImpl->setSeedLanguage(lang.toStdString());
-}
+        this->updateBalance();
+    }
 
-Wallet::Status Wallet::status() const
-{
-    return static_cast<Status>(m_walletImpl->status());
-}
+    connect(this->history(), &TransactionHistory::txNoteChanged, [this]{
+        this->history()->refresh(this->currentSubaddressAccount());
+    });
 
-NetworkType::Type Wallet::nettype() const
-{
-    return static_cast<NetworkType::Type>(m_walletImpl->nettype());
+    connect(this, &Wallet::createTransactionError, this, &Wallet::onCreateTransactionError);
+    connect(this, &Wallet::refreshed, this, &Wallet::onRefreshed);
+    connect(this, &Wallet::newBlock, this, &Wallet::onNewBlock);
+    connect(this, &Wallet::updated, this, &Wallet::onUpdated);
+    connect(this, &Wallet::heightsRefreshed, this, &Wallet::onHeightsRefreshed);
+    connect(this, &Wallet::transactionCreated, this, &Wallet::onTransactionCreated);
 }
 
-bool Wallet::disconnected() const
-{
-    return m_disconnected;
-}
+// #################### Status ####################
 
-bool Wallet::refreshing() const
-{
-    return m_refreshing;
+Wallet::Status Wallet::status() const {
+    return static_cast<Status>(m_walletImpl->status());
 }
 
-void Wallet::refreshingSet(bool value)
-{
-    if (m_refreshing.exchange(value) != value)
-    {
-        emit refreshingChanged();
-    }
+Wallet::ConnectionStatus Wallet::connectionStatus() const {
+    return m_connectionStatus;
 }
 
-void Wallet::setConnectionStatus(ConnectionStatus value)
-{
-    if (m_connectionStatus == value)
-    {
+void Wallet::setConnectionStatus(ConnectionStatus value) {
+    if (m_connectionStatus == value) {
         return;
     }
 
     m_connectionStatus = value;
     emit connectionStatusChanged(m_connectionStatus);
+}
 
-    bool disconnected = m_connectionStatus == Wallet::ConnectionStatus_Connecting ||
-                        m_connectionStatus == Wallet::ConnectionStatus_Disconnected;
+bool Wallet::isSynchronized() const {
+    return connectionStatus() == ConnectionStatus_Synchronized;
+}
 
-    if (m_disconnected != disconnected)
-    {
-        m_disconnected = disconnected;
-        emit disconnectedChanged();
-    }
+bool Wallet::isConnected() const {
+    auto status = connectionStatus();
+    return status == ConnectionStatus_Synchronizing || status == ConnectionStatus_Synchronized;
 }
 
-void Wallet::onNewBlock(uint64_t walletHeight) {
-    // Called whenever a new block gets scanned by the wallet
-    quint64 daemonHeight = m_daemonBlockChainTargetHeight;
+QString Wallet::errorString() const {
+    return QString::fromStdString(m_walletImpl->errorString());
+}
 
-    if (walletHeight < (daemonHeight - 1)) {
-        setConnectionStatus(ConnectionStatus_Synchronizing);
-    } else {
-        setConnectionStatus(ConnectionStatus_Synchronized);
-    }
+NetworkType::Type Wallet::nettype() const {
+    return static_cast<NetworkType::Type>(m_walletImpl->nettype());
 }
 
-QString Wallet::getProxyAddress() const
-{
-    QMutexLocker locker(&m_proxyMutex);
-    return m_proxyAddress;
+bool Wallet::viewOnly() const {
+    return m_walletImpl->watchOnly();
 }
 
-void Wallet::setProxyAddress(QString address)
-{
-    m_scheduler.run([this, address] {
-        {
-            QMutexLocker locker(&m_proxyMutex);
+bool Wallet::isDeterministic() const {
+    return m_walletImpl->isDeterministic();
+}
 
-            if (!m_walletImpl->setProxy(address.toStdString()))
-            {
-                qCritical() << "failed to set proxy" << address;
-            }
+// #################### Balance ####################
 
-            m_proxyAddress = address;
-        }
-        emit proxyAddressChanged();
-    });
+quint64 Wallet::balance() const {
+    return balance(m_currentSubaddressAccount);
 }
 
-bool Wallet::synchronized() const
-{
-    // Misleading: this will return true if wallet has synchronized at least once even if it isn't currently synchronized
-    return m_walletImpl->synchronized();
+quint64 Wallet::balance(quint32 accountIndex) const {
+    return m_walletImpl->balance(accountIndex);
 }
 
-bool Wallet::isSynchronized() const
-{
-    return connectionStatus() == ConnectionStatus_Synchronized;
+quint64 Wallet::balanceAll() const {
+    return m_walletImpl->balanceAll();
 }
 
-bool Wallet::isConnected() const
-{
-    auto status = connectionStatus();
-    return status == ConnectionStatus_Synchronizing || status == ConnectionStatus_Synchronized;
+quint64 Wallet::unlockedBalance() const {
+    return unlockedBalance(m_currentSubaddressAccount);
 }
 
-void Wallet::setOffline(bool offline) const
-{
-    return m_walletImpl->setOffline(offline);
+quint64 Wallet::unlockedBalance(quint32 accountIndex) const {
+    return m_walletImpl->unlockedBalance(accountIndex);
 }
 
-QString Wallet::errorString() const
-{
-    return QString::fromStdString(m_walletImpl->errorString());
+quint64 Wallet::unlockedBalanceAll() const {
+    return m_walletImpl->unlockedBalanceAll();
 }
 
-bool Wallet::setPassword(const QString &oldPassword, const QString &newPassword)
-{
-    return m_walletImpl->setPassword(oldPassword.toStdString(), newPassword.toStdString());
-}
+void Wallet::updateBalance() {
+    quint64 balance = this->balance();
+    quint64 spendable = this->unlockedBalance();
 
-bool Wallet::verifyPassword(const QString &password)
-{
-    return m_walletImpl->verifyPassword(password.toStdString());
+    emit balanceUpdated(balance, spendable);
 }
 
-QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const
-{
+// #################### Subaddresses and Accounts ####################
+
+QString Wallet::address(quint32 accountIndex, quint32 addressIndex) const {
     return QString::fromStdString(m_walletImpl->address(accountIndex, addressIndex));
 }
 
-SubaddressIndex Wallet::subaddressIndex(const QString &address) const
-{
+SubaddressIndex Wallet::subaddressIndex(const QString &address) const {
     std::pair<uint32_t, uint32_t> i;
     if (!m_walletImpl->subaddressIndex(address.toStdString(), i)) {
         return SubaddressIndex(-1, -1);
@@ -188,74 +173,120 @@ SubaddressIndex Wallet::subaddressIndex(const QString &address) const
     return SubaddressIndex(i.first, i.second);
 }
 
-QString Wallet::cachePath() const
-{
-    return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->filename()));
+quint32 Wallet::currentSubaddressAccount() const {
+    return m_currentSubaddressAccount;
 }
 
-QString Wallet::keysPath() const
-{
-    return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->keysFilename()));;
+void Wallet::switchSubaddressAccount(quint32 accountIndex) {
+    if (accountIndex < numSubaddressAccounts())
+    {
+        m_currentSubaddressAccount = accountIndex;
+        if (!setCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT, QString::number(m_currentSubaddressAccount)))
+        {
+            qWarning() << "failed to set " << ATTRIBUTE_SUBADDRESS_ACCOUNT << " cache attribute";
+        }
+        m_subaddress->refresh(m_currentSubaddressAccount);
+        m_history->refresh(m_currentSubaddressAccount);
+        m_coins->refresh(m_currentSubaddressAccount);
+        this->subaddressModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
+        this->coinsModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
+        this->updateBalance();
+        emit currentSubaddressAccountChanged();
+    }
+}
+void Wallet::addSubaddressAccount(const QString& label) {
+    m_walletImpl->addSubaddressAccount(label.toStdString());
+    switchSubaddressAccount(numSubaddressAccounts() - 1);
+}
+
+quint32 Wallet::numSubaddressAccounts() const {
+    return m_walletImpl->numSubaddressAccounts();
+}
+
+quint32 Wallet::numSubaddresses(quint32 accountIndex) const {
+    return m_walletImpl->numSubaddresses(accountIndex);
+}
+
+void Wallet::addSubaddress(const QString& label) {
+    m_walletImpl->addSubaddress(currentSubaddressAccount(), label.toStdString());
+}
+
+QString Wallet::getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const {
+    return QString::fromStdString(m_walletImpl->getSubaddressLabel(accountIndex, addressIndex));
+}
+
+void Wallet::setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) {
+    m_walletImpl->setSubaddressLabel(accountIndex, addressIndex, label.toStdString());
+}
+
+void Wallet::deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId) {
+    m_scheduler.run([this, accountIndex, addressIndex, paymentId] {
+        m_walletImpl->deviceShowAddress(accountIndex, addressIndex, paymentId.toStdString());
+        emit deviceShowAddressShowed();
+    });
+}
+
+QString Wallet::getSubaddressLookahead() const {
+    auto lookahead = m_walletImpl->getSubaddressLookahead();
+
+    return QString("%1:%2").arg(QString::number(lookahead.first), QString::number(lookahead.second));
 }
 
-void Wallet::store()
+// #################### Seed ####################
+
+QString Wallet::getSeed(const QString &seedOffset) const {
+    return QString::fromStdString(m_walletImpl->seed(seedOffset.toStdString()));
+}
+
+qsizetype Wallet::seedLength() const {
+    auto seedLength = this->getCacheAttribute("feather.seed").split(" ", Qt::SkipEmptyParts).length();
+    return seedLength ? seedLength : 25;
+}
+
+QString Wallet::getSeedLanguage() const
 {
-    m_walletImpl->store();
+    return QString::fromStdString(m_walletImpl->getSeedLanguage());
 }
 
-bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, bool isRecovering, bool isRecoveringFromDevice, quint64 restoreHeight, const QString& proxyAddress)
+void Wallet::setSeedLanguage(const QString &lang)
 {
-    qDebug() << "init non async";
-    if (isRecovering){
-        qDebug() << "RESTORING";
-        m_walletImpl->setRecoveringFromSeed(true);
-    }
-    if (isRecoveringFromDevice){
-        qDebug() << "RESTORING FROM DEVICE";
-        m_walletImpl->setRecoveringFromDevice(true);
-    }
-    if (isRecovering || isRecoveringFromDevice) {
-        m_walletImpl->setRefreshFromBlockHeight(restoreHeight);
-    }
+    m_walletImpl->setSeedLanguage(lang.toStdString());
+}
 
-    {
-        QMutexLocker locker(&m_proxyMutex);
+// #################### Node connection ####################
 
-        if (!m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), m_useSSL, false, proxyAddress.toStdString()))
-        {
-            return false;
-        }
+void Wallet::setOffline(bool offline) const {
+    return m_walletImpl->setOffline(offline);
+}
 
-        m_proxyAddress = proxyAddress;
-    }
-    emit proxyAddressChanged();
+void Wallet::setTrustedDaemon(bool arg) {
+    m_walletImpl->setTrustedDaemon(arg);
+}
 
-    setTrustedDaemon(trustedDaemon);
-    return true;
+void Wallet::setUseSSL(bool ssl) {
+    m_useSSL = ssl;
 }
 
-void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemonPassword)
-{
-    // store daemon login
+void Wallet::setDaemonLogin(const QString &daemonUsername, const QString &daemonPassword) {
     m_daemonUsername = daemonUsername;
     m_daemonPassword = daemonPassword;
 }
 
-void Wallet::initAsync(
-        const QString &daemonAddress,
-        bool trustedDaemon /* = false */,
-        quint64 upperTransactionLimit /* = 0 */,
-        bool isRecovering /* = false */,
-        bool isRecoveringFromDevice /* = false */,
-        quint64 restoreHeight /* = 0 */,
-        const QString &proxyAddress /* = "" */)
+void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64 upperTransactionLimit, const QString &proxyAddress)
 {
     qDebug() << "initAsync: " + daemonAddress;
-    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)
+    const auto future = m_scheduler.run([this, daemonAddress, trustedDaemon, upperTransactionLimit, proxyAddress] {
+        // Beware! This code does not run in the GUI thread.
+
+        bool success;
         {
-            emit walletCreationHeightChanged();
+            QMutexLocker locker(&m_proxyMutex);
+            success = m_walletImpl->init(daemonAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), m_useSSL, false, proxyAddress.toStdString());
+        }
+
+        setTrustedDaemon(trustedDaemon);
+
+        if (success) {
             qDebug() << "init async finished - starting refresh";
             startRefresh();
         }
@@ -266,539 +297,577 @@ void Wallet::initAsync(
     }
 }
 
-bool Wallet::setDaemon(const QString &daemonAddress)
-{
-    qDebug() << "setDaemon: " + daemonAddress;
-    return m_walletImpl->setDaemon(daemonAddress.toStdString(), m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), m_useSSL);
-}
+// #################### Synchronization (Refresh) ####################
+
+void Wallet::startRefresh() {
+    m_refreshEnabled = true;
+    m_refreshNow = true;
+}
+
+void Wallet::pauseRefresh() {
+    m_refreshEnabled = false;
+}
+
+void Wallet::startRefreshThread()
+{
+    const auto future = m_scheduler.run([this] {
+        // Beware! This code does not run in the GUI thread.
+
+        constexpr const std::chrono::seconds refreshInterval{10};
+        constexpr const std::chrono::milliseconds intervalResolution{100};
+
+        auto last = std::chrono::steady_clock::now();
+        while (!m_scheduler.stopping())
+        {
+            if (m_refreshEnabled && (!isHwBacked() || isDeviceConnected()))
+            {
+                const auto now = std::chrono::steady_clock::now();
+                const auto elapsed = now - last;
+                if (elapsed >= refreshInterval || m_refreshNow)
+                {
+                    m_refreshNow = false;
+
+                    // get daemonHeight and targetHeight
+                    // daemonHeight and targetHeight will be 0 if call to get_info fails
+                    quint64 daemonHeight = m_walletImpl->daemonBlockChainHeight();
+                    bool success = daemonHeight > 0;
+
+                    quint64 targetHeight = 0;
+                    if (success) {
+                        targetHeight = m_walletImpl->daemonBlockChainTargetHeight();
+                    }
+                    bool haveHeights = (daemonHeight > 0 && targetHeight > 0);
+
+                    emit heightsRefreshed(haveHeights, daemonHeight, targetHeight);
+
+                    // Don't call refresh function if we don't have the daemon and target height
+                    // We do this to prevent to UI from getting confused about the amount of blocks that are still remaining
+                    if (haveHeights) {
+                        QMutexLocker locker(&m_asyncMutex);
+
+                        if (m_newWallet) {
+                            // Set blockheight to daemonHeight for newly created wallets to speed up initial sync
+                            m_walletImpl->setRefreshFromBlockHeight(daemonHeight);
+                            m_newWallet = false;
+                        }
+
+                        m_walletImpl->refresh();
+                    }
+                    last = std::chrono::steady_clock::now();
+                }
+            }
+
+            std::this_thread::sleep_for(intervalResolution);
+        }
+    });
+    if (!future.first)
+    {
+        throw std::runtime_error("failed to start auto refresh thread");
+    }
+}
+
+void Wallet::onHeightsRefreshed(bool success, quint64 daemonHeight, quint64 targetHeight) {
+    m_daemonBlockChainHeight = daemonHeight;
+    m_daemonBlockChainTargetHeight = targetHeight;
+
+    if (success) {
+        quint64 walletHeight = blockChainHeight();
+
+        if (this->connectionStatus() != Wallet::ConnectionStatus_Disconnected) {
+            if (daemonHeight < targetHeight) {
+                emit blockchainSync(daemonHeight, targetHeight);
+            }
+            else {
+                this->syncStatusUpdated(walletHeight, daemonHeight);
+            }
+        }
+
+        if (walletHeight < (daemonHeight - 1)) {
+            setConnectionStatus(ConnectionStatus_Synchronizing);
+        } else {
+            setConnectionStatus(ConnectionStatus_Synchronized);
+        }
+    } else {
+        setConnectionStatus(ConnectionStatus_Disconnected);
+    }
+}
+
+quint64 Wallet::blockChainHeight() const {
+    // Can not block UI
+    return m_walletImpl->blockChainHeight();
+}
+
+quint64 Wallet::daemonBlockChainHeight() const {
+    return m_daemonBlockChainHeight;
+}
+
+quint64 Wallet::daemonBlockChainTargetHeight() const {
+    return m_daemonBlockChainTargetHeight;
+}
+
+void Wallet::syncStatusUpdated(quint64 height, quint64 target) {
+    if (height < (target - 1)) {
+        emit refreshSync(height, target);
+    }
+    else {
+        this->updateBalance();
+        emit synchronized();
+    }
+}
+
+void Wallet::onNewBlock(uint64_t walletHeight) {
+    // Called whenever a new block gets scanned by the wallet
+    quint64 daemonHeight = m_daemonBlockChainTargetHeight;
+
+    if (walletHeight < (daemonHeight - 1)) {
+        setConnectionStatus(ConnectionStatus_Synchronizing);
+    } else {
+        setConnectionStatus(ConnectionStatus_Synchronized);
+    }
+
+    this->syncStatusUpdated(walletHeight, daemonHeight);
+
+    if (this->isSynchronized()) {
+        this->coins()->refreshUnlocked();
+        this->history()->refresh(this->currentSubaddressAccount());
+        // Todo: only refresh tx confirmations
+    }
+}
+
+void Wallet::onUpdated() {
+    if (m_walletImpl->synchronized()) {
+        this->refreshModels();
+        this->storeSafer();
+    }
+
+    this->updateBalance();
+}
+
+void Wallet::onRefreshed(bool success, const QString &message) {
+    qDebug() << "onRefreshed";
+
+    if (!success) {
+        setConnectionStatus(ConnectionStatus_Disconnected);
+        // Something went wrong during refresh, in some cases we need to notify the user
+        qCritical() << "Exception during refresh: " << message; // Can't use ->errorString() here, other SLOT might snipe it first
+        return;
+    }
+
+    if (!this->refreshedOnce) {
+        this->refreshModels();
+        this->refreshedOnce = true;
+        emit walletRefreshed();
+        // store wallet immediately upon finishing synchronization
+        this->storeSafer();
+    }
+}
+
+void Wallet::refreshModels() {
+    m_history->refresh(this->currentSubaddressAccount());
+    m_coins->refresh(this->currentSubaddressAccount());
+    bool r = this->subaddress()->refresh(this->currentSubaddressAccount());
+
+    if (!r) {
+        // This should only happen if wallet keys got corrupted or were tampered with
+        // The list of subaddresses is wiped to prevent loss of funds
+        // Notify MainWindow to display an error message
+        emit keysCorrupted();
+    }
+}
+
+// #################### Hardware wallet ####################
 
-bool Wallet::isHwBacked() const
-{
+bool Wallet::isHwBacked() const {
     return m_walletImpl->getDeviceType() != Monero::Wallet::Device_Software;
 }
 
-bool Wallet::isLedger() const
-{
+bool Wallet::isLedger() const {
     return m_walletImpl->getDeviceType() == Monero::Wallet::Device_Ledger;
 }
 
-bool Wallet::isTrezor() const
-{
+bool Wallet::isTrezor() const {
     return m_walletImpl->getDeviceType() == Monero::Wallet::Device_Trezor;
 }
 
-bool Wallet::reconnectDevice()
-{
-    return m_walletImpl->reconnectDevice();
-}
-
-//! create a view only wallet
-bool Wallet::createViewOnly(const QString &path, const QString &password) const
-{
-    // Create path
-    QDir d = QFileInfo(path).absoluteDir();
-    d.mkpath(d.absolutePath());
-    return m_walletImpl->createWatchOnly(path.toStdString(),password.toStdString(),m_walletImpl->getSeedLanguage());
+bool Wallet::isDeviceConnected() const {
+    return m_walletImpl->isDeviceConnected();
 }
 
-bool Wallet::connectToDaemon()
-{
-    return m_walletImpl->connectToDaemon();
+bool Wallet::reconnectDevice() {
+    return m_walletImpl->reconnectDevice();
 }
 
-void Wallet::setTrustedDaemon(bool arg)
-{
-    m_walletImpl->setTrustedDaemon(arg);
+void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) {
+    if (m_walletListener != nullptr) {
+        m_walletListener->onPassphraseEntered(passphrase, enter_on_device, entry_abort);
+    }
 }
 
-void Wallet::setUseSSL(bool ssl)
-{
-    m_useSSL = ssl;
+void Wallet::onWalletPassphraseNeeded(bool on_device) {
+    emit this->walletPassphraseNeeded(on_device);
 }
 
-bool Wallet::viewOnly() const
-{
-    return m_walletImpl->watchOnly();
-}
+// #################### Import / Export ####################
 
-bool Wallet::isDeterministic() const
-{
-    return m_walletImpl->isDeterministic();
+bool Wallet::exportKeyImages(const QString& path, bool all) {
+    return m_walletImpl->exportKeyImages(path.toStdString(), all);
 }
 
-quint64 Wallet::balance() const
-{
-    return balance(m_currentSubaddressAccount);
+bool Wallet::importKeyImages(const QString& path) {
+    return m_walletImpl->importKeyImages(path.toStdString());
 }
 
-quint64 Wallet::balance(quint32 accountIndex) const
-{
-    return m_walletImpl->balance(accountIndex);
+bool Wallet::exportOutputs(const QString& path, bool all) {
+    return m_walletImpl->exportOutputs(path.toStdString(), all);
 }
 
-quint64 Wallet::balanceAll() const
-{
-    return m_walletImpl->balanceAll();
+bool Wallet::importOutputs(const QString& path) {
+    return m_walletImpl->importOutputs(path.toStdString());
 }
 
-quint64 Wallet::unlockedBalance() const
-{
-    return unlockedBalance(m_currentSubaddressAccount);
+bool Wallet::importTransaction(const QString& txid) {
+    std::vector<std::string> txids = {txid.toStdString()};
+    return m_walletImpl->scanTransactions(txids);
 }
 
-quint64 Wallet::unlockedBalance(quint32 accountIndex) const
-{
-    return m_walletImpl->unlockedBalance(accountIndex);
-}
+// #################### Wallet cache ####################
 
-quint64 Wallet::unlockedBalanceAll() const
-{
-    return m_walletImpl->unlockedBalanceAll();
+void Wallet::store() {
+    m_walletImpl->store();
 }
 
-quint32 Wallet::currentSubaddressAccount() const
-{
-    return m_currentSubaddressAccount;
-}
-void Wallet::switchSubaddressAccount(quint32 accountIndex)
-{
-    if (accountIndex < numSubaddressAccounts())
-    {
-        m_currentSubaddressAccount = accountIndex;
-        if (!setCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT, QString::number(m_currentSubaddressAccount)))
-        {
-            qWarning() << "failed to set " << ATTRIBUTE_SUBADDRESS_ACCOUNT << " cache attribute";
-        }
-        m_subaddress->refresh(m_currentSubaddressAccount);
-        m_history->refresh(m_currentSubaddressAccount);
-        m_coins->refresh(m_currentSubaddressAccount);
-        this->subaddressModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
-        this->coinsModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
-        emit currentSubaddressAccountChanged();
+void Wallet::storeSafer() {
+    // Do not store a synchronizing wallet: store() is NOT thread safe and may crash the wallet
+    if (!this->isSynchronized()) {
+        return;
     }
-}
-void Wallet::addSubaddressAccount(const QString& label)
-{
-    m_walletImpl->addSubaddressAccount(label.toStdString());
-    switchSubaddressAccount(numSubaddressAccounts() - 1);
-}
-quint32 Wallet::numSubaddressAccounts() const
-{
-    return m_walletImpl->numSubaddressAccounts();
-}
-quint32 Wallet::numSubaddresses(quint32 accountIndex) const
-{
-    return m_walletImpl->numSubaddresses(accountIndex);
-}
-void Wallet::addSubaddress(const QString& label)
-{
-    m_walletImpl->addSubaddress(currentSubaddressAccount(), label.toStdString());
-}
-QString Wallet::getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const
-{
-    return QString::fromStdString(m_walletImpl->getSubaddressLabel(accountIndex, addressIndex));
-}
-void Wallet::setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label)
-{
-    m_walletImpl->setSubaddressLabel(accountIndex, addressIndex, label.toStdString());
-    emit currentSubaddressAccountChanged();
-}
-void Wallet::deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId)
-{
-    m_scheduler.run([this, accountIndex, addressIndex, paymentId] {
-        m_walletImpl->deviceShowAddress(accountIndex, addressIndex, paymentId.toStdString());
-        emit deviceShowAddressShowed();
-    });
-}
-
-QString Wallet::getSubaddressLookahead() const
-{
-    auto lookahead = m_walletImpl->getSubaddressLookahead();
 
-    return QString("%1:%2").arg(QString::number(lookahead.first), QString::number(lookahead.second));
+    qDebug() << "Storing wallet";
+    this->store();
 }
 
-bool Wallet::refreshHeights()
-{
-    // daemonHeight and targetHeight will be 0 if call to get_info fails
-
-    quint64 daemonHeight;
-    QPair<bool, QFuture<void>> daemonHeightFuture = m_scheduler.run([this, &daemonHeight] {
-        daemonHeight = m_walletImpl->daemonBlockChainHeight();;
-    });
-    if (!daemonHeightFuture.first)
-    {
-        return false;
-    }
-    // We must wait here for get_info to return, otherwise targetHeight will get cache value of 0
-    daemonHeightFuture.second.waitForFinished();
-    bool success = daemonHeight > 0;
-
-    quint64 targetHeight = 0;
-    if (success) {
-        QPair<bool, QFuture<void>> targetHeightFuture = m_scheduler.run([this, &targetHeight] {
-            targetHeight = m_walletImpl->daemonBlockChainTargetHeight();
-        });
-        if (!targetHeightFuture.first)
-        {
-            return false;
-        }
-        targetHeightFuture.second.waitForFinished();
-    }
-
-    m_daemonBlockChainHeight = daemonHeight;
-    m_daemonBlockChainTargetHeight = targetHeight;
-
-    success = (daemonHeight > 0 && targetHeight > 0);
-
-    if (success) {
-        quint64 walletHeight = blockChainHeight();
-        emit heightRefreshed(walletHeight, daemonHeight, targetHeight);
+QString Wallet::cachePath() const {
+    return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->filename()));
+}
 
-        if (walletHeight < (daemonHeight - 1)) {
-            setConnectionStatus(ConnectionStatus_Synchronizing);
-        } else {
-            setConnectionStatus(ConnectionStatus_Synchronized);
-        }
-    } else {
-        setConnectionStatus(ConnectionStatus_Disconnected);
-    }
+QString Wallet::keysPath() const {
+    return QDir::toNativeSeparators(QString::fromStdString(m_walletImpl->keysFilename()));;
+}
 
-    return success;
+bool Wallet::setPassword(const QString &oldPassword, const QString &newPassword) {
+    return m_walletImpl->setPassword(oldPassword.toStdString(), newPassword.toStdString());
 }
 
-quint64 Wallet::blockChainHeight() const
-{
-    return m_walletImpl->blockChainHeight();
+bool Wallet::verifyPassword(const QString &password) {
+    return m_walletImpl->verifyPassword(password.toStdString());
 }
 
-quint64 Wallet::daemonBlockChainHeight() const
-{
-    // Can not block UI
-    return m_daemonBlockChainHeight;
+bool Wallet::cacheAttributeExists(const QString &key) {
+    return m_walletImpl->cacheAttributeExists(key.toStdString());
 }
 
-quint64 Wallet::daemonBlockChainTargetHeight() const
-{
-    // Can not block UI
-    return m_daemonBlockChainTargetHeight;
+bool Wallet::setCacheAttribute(const QString &key, const QString &val) {
+    return m_walletImpl->setCacheAttribute(key.toStdString(), val.toStdString());
 }
 
-bool Wallet::exportKeyImages(const QString& path, bool all)
-{
-    return m_walletImpl->exportKeyImages(path.toStdString(), all);
+QString Wallet::getCacheAttribute(const QString &key) const {
+    return QString::fromStdString(m_walletImpl->getCacheAttribute(key.toStdString()));
 }
 
-bool Wallet::importKeyImages(const QString& path)
-{
-    return m_walletImpl->importKeyImages(path.toStdString());
+void Wallet::addCacheTransaction(const QString &txid, const QString &txHex) {
+    this->setCacheAttribute(QString("tx:%1").arg(txid), txHex);
 }
 
-bool Wallet::exportOutputs(const QString& path, bool all) {
-    return m_walletImpl->exportOutputs(path.toStdString(), all);
+QString Wallet::getCacheTransaction(const QString &txid) const {
+    return this->getCacheAttribute(QString("tx:%1").arg(txid));
 }
 
-bool Wallet::importOutputs(const QString& path) {
-    return m_walletImpl->importOutputs(path.toStdString());
+bool Wallet::setUserNote(const QString &txid, const QString &note) {
+    return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
 }
 
-bool Wallet::importTransaction(const QString& txid) {
-    std::vector<std::string> txids = {txid.toStdString()};
-    return m_walletImpl->scanTransactions(txids);
+QString Wallet::getUserNote(const QString &txid) const {
+    return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString()));
 }
 
-QString Wallet::printBlockchain()
-{
+QString Wallet::printBlockchain() {
     return QString::fromStdString(m_walletImpl->printBlockchain());
 }
 
-QString Wallet::printTransfers()
-{
+QString Wallet::printTransfers() {
     return QString::fromStdString(m_walletImpl->printTransfers());
 }
 
-QString Wallet::printPayments()
-{
+QString Wallet::printPayments() {
     return QString::fromStdString(m_walletImpl->printPayments());
 }
 
-QString Wallet::printUnconfirmedPayments()
-{
+QString Wallet::printUnconfirmedPayments() {
     return QString::fromStdString(m_walletImpl->printUnconfirmedPayments());
 }
 
-QString Wallet::printConfirmedTransferDetails()
-{
+QString Wallet::printConfirmedTransferDetails() {
     return QString::fromStdString(m_walletImpl->printConfirmedTransferDetails());
 }
 
-QString Wallet::printUnconfirmedTransferDetails()
-{
+QString Wallet::printUnconfirmedTransferDetails() {
     return QString::fromStdString(m_walletImpl->printUnconfirmedTransferDetails());
 }
 
-QString Wallet::printPubKeys()
-{
+QString Wallet::printPubKeys() {
     return QString::fromStdString(m_walletImpl->printPubKeys());
 }
 
-QString Wallet::printTxNotes()
-{
+QString Wallet::printTxNotes() {
     return QString::fromStdString(m_walletImpl->printTxNotes());
 }
 
-QString Wallet::printSubaddresses()
-{
+QString Wallet::printSubaddresses() {
     return QString::fromStdString(m_walletImpl->printSubaddresses());
 }
 
-QString Wallet::printSubaddressLabels()
-{
+QString Wallet::printSubaddressLabels() {
     return QString::fromStdString(m_walletImpl->printSubaddressLabels());
 }
 
-QString Wallet::printAdditionalTxKeys()
-{
+QString Wallet::printAdditionalTxKeys() {
     return QString::fromStdString(m_walletImpl->printAdditionalTxKeys());
 }
 
-QString Wallet::printAttributes()
-{
+QString Wallet::printAttributes() {
     return QString::fromStdString(m_walletImpl->printAttributes());
 }
 
-QString Wallet::printKeyImages()
-{
+QString Wallet::printKeyImages() {
     return QString::fromStdString(m_walletImpl->printKeyImages());
 }
 
-QString Wallet::printAccountTags()
-{
+QString Wallet::printAccountTags() {
     return QString::fromStdString(m_walletImpl->printAccountTags());
 }
 
-QString Wallet::printTxKeys()
-{
+QString Wallet::printTxKeys() {
     return QString::fromStdString(m_walletImpl->printTxKeys());
 }
 
-QString Wallet::printAddressBook()
-{
+QString Wallet::printAddressBook() {
     return QString::fromStdString(m_walletImpl->printAddressBook());
 }
 
-QString Wallet::printScannedPoolTxs()
-{
+QString Wallet::printScannedPoolTxs() {
     return QString::fromStdString(m_walletImpl->printScannedPoolTxs());
 }
 
-bool Wallet::haveTransaction(const QString &txid)
-{
-    return m_walletImpl->haveTransaction(txid.toStdString());
-}
+// #################### Transactions ####################
 
-void Wallet::startRefresh()
-{
-    m_refreshEnabled = true;
-    m_refreshNow = true;
-}
+// Phase 0: Pre-construction setup
 
-void Wallet::pauseRefresh()
-{
-    m_refreshEnabled = false;
+void Wallet::setSelectedInputs(const QStringList &selectedInputs) {
+    m_selectedInputs.clear();
+    for (const auto &input : selectedInputs) {
+        m_selectedInputs.insert(input.toStdString());
+    }
+    emit selectedInputsChanged(selectedInputs);
 }
 
-PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
-                                              quint64 amount, quint32 mixin_count,
-                                              PendingTransaction::Priority priority, const QStringList &preferredInputs)
-{
-//    pauseRefresh();
-    std::set<std::string> preferred_inputs;
-    for (const auto &input : preferredInputs) {
-        preferred_inputs.insert(input.toStdString());
+// Phase 1: Transaction creation
+// Pick one:
+// - createTransaction
+// - createTransactionMultiDest
+// - sweepOutputs
+
+void Wallet::createTransaction(const QString &address, quint64 amount, const QString &description, bool all) {
+    this->tmpTxDescription = description;
+
+    if (!all && amount == 0) {
+        emit createTransactionError("Cannot send nothing");
+        return;
     }
 
-    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, preferred_inputs);
-    PendingTransaction * result = new PendingTransaction(ptImpl, nullptr);
+    quint64 unlocked_balance = this->unlockedBalance();
+    if (!all && amount > unlocked_balance) {
+        emit createTransactionError(QString("Not enough money to spend.\n\n"
+                                            "Spendable balance: %1").arg(WalletManager::displayAmount(unlocked_balance)));
+        return;
+    } else if (unlocked_balance == 0) {
+        emit createTransactionError("No money to spend");
+        return;
+    }
 
-//    startRefresh();
-    return result;
-}
+    qInfo() << "Creating transaction";
 
-void Wallet::createTransactionAsync(const QString &dst_addr, const QString &payment_id,
-                                    quint64 amount, quint32 mixin_count,
-                                    PendingTransaction::Priority priority, const QStringList &preferredInputs)
-{
-    m_scheduler.run([this, dst_addr, payment_id, amount, mixin_count, priority, preferredInputs] {
-        PendingTransaction *tx = createTransaction(dst_addr, payment_id, amount, mixin_count, priority, preferredInputs);
-        QVector<QString> address {dst_addr};
-        emit transactionCreated(tx, address);
+    m_scheduler.run([this, all, address, amount] {
+        std::set<uint32_t> subaddr_indices;
+
+        Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(address.toStdString(), "", all ? Monero::optional<uint64_t>() : Monero::optional<uint64_t>(amount), constants::mixin,
+                                                                              static_cast<Monero::PendingTransaction::Priority>(this->tx_priority),
+                                                                              currentSubaddressAccount(), subaddr_indices, m_selectedInputs);
+        PendingTransaction *tx = new PendingTransaction(ptImpl, this);
+
+        QVector<QString> addresses{address};
+        emit transactionCreated(tx, addresses);
     });
+
+    emit initiateTransaction();
 }
 
-PendingTransaction* Wallet::createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
-                                                       PendingTransaction::Priority priority, const QStringList &preferredInputs)
-{
-//    pauseRefresh();
+void Wallet::createTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description) {
+    this->tmpTxDescription = description;
 
-    std::vector<std::string> dests;
-    for (auto &addr : dst_addr) {
-        dests.push_back(addr.toStdString());
+    quint64 total_amount = 0;
+    for (auto &amount : amounts) {
+        total_amount += amount;
     }
 
-    std::vector<uint64_t> amounts;
-    for (auto &a : amount) {
-        amounts.push_back(a);
+    auto unlocked_balance = this->unlockedBalance();
+    if (total_amount > unlocked_balance) {
+        emit createTransactionError("Not enough money to spend");
     }
 
-    std::set<std::string> preferred_inputs;
-    for (const auto &input : preferredInputs) {
-        preferred_inputs.insert(input.toStdString());
-    }
+    qInfo() << "Creating transaction";
+    m_scheduler.run([this, addresses, amounts] {
+        std::vector<std::string> dests;
+        for (auto &addr : addresses) {
+            dests.push_back(addr.toStdString());
+        }
 
-    // TODO: remove mixin count
-    std::set<uint32_t> subaddr_indices;
-    Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionMultDest(dests, "", amounts, 11, static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices, preferred_inputs);
-    PendingTransaction * result = new PendingTransaction(ptImpl);
+        std::vector<uint64_t> amount;
+        for (auto &a : amounts) {
+            amount.push_back(a);
+        }
 
-//    startRefresh();
-    return result;
+        std::set<uint32_t> subaddr_indices;
+        Monero::PendingTransaction *ptImpl = m_walletImpl->createTransactionMultDest(dests, "", amount, constants::mixin,
+                                                                                     static_cast<Monero::PendingTransaction::Priority>(this->tx_priority),
+                                                                                     currentSubaddressAccount(), subaddr_indices, m_selectedInputs);
+        PendingTransaction *tx = new PendingTransaction(ptImpl);
+        emit transactionCreated(tx, addresses);
+    });
+
+    emit initiateTransaction();
 }
 
-void Wallet::createTransactionMultiDestAsync(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
-                                             PendingTransaction::Priority priority, const QStringList &preferredInputs)
-{
-    m_scheduler.run([this, dst_addr, amount, priority, preferredInputs] {
-        PendingTransaction *tx = createTransactionMultiDest(dst_addr, amount, priority, preferredInputs);
-        QVector<QString> addresses;
-        for (auto &addr : dst_addr) {
-            addresses.push_back(addr);
+void Wallet::sweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs) {
+    if (churn) {
+        address = this->address(0, 0);
+    }
+
+    qInfo() << "Creating transaction";
+    m_scheduler.run([this, keyImages, address, outputs] {
+        std::vector<std::string> kis;
+        for (const auto &key_image : keyImages) {
+            kis.push_back(key_image.toStdString());
         }
+        Monero::PendingTransaction *ptImpl = m_walletImpl->createTransactionSelected(kis, address.toStdString(), outputs, static_cast<Monero::PendingTransaction::Priority>(this->tx_priority));
+        PendingTransaction *tx = new PendingTransaction(ptImpl, this);
+
+        QVector<QString> addresses {address};
         emit transactionCreated(tx, addresses);
     });
+
+    emit initiateTransaction();
 }
 
-PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
-                                                 quint32 mixin_count, PendingTransaction::Priority priority,
-                                                 const QStringList &preferredInputs)
-{
-//    pauseRefresh();
+// Phase 2: Transaction construction completed
+
+void Wallet::onCreateTransactionError(const QString &msg) {
+    this->tmpTxDescription = "";
+    emit endTransaction();
+}
+
+void Wallet::onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address) {
+    qDebug() << Q_FUNC_INFO;
 
-    std::set<std::string> preferred_inputs;
-    for (const auto &input : preferredInputs) {
-        preferred_inputs.insert(input.toStdString());
+    for (auto &addr : address) {
+        if (addr == constants::donationAddress) {
+            this->donationSending = true;
+        }
     }
 
-    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, preferred_inputs);
-    PendingTransaction * result = new PendingTransaction(ptImpl, this);
+    // Let UI know that the transaction was constructed
+    emit endTransaction();
 
-//    startRefresh();
-    return result;
+    // tx created, but not sent yet. ask user to verify first.
+    emit createTransactionSuccess(tx, address);
 }
 
-void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
-                                       quint32 mixin_count,
-                                       PendingTransaction::Priority priority, const QStringList &preferredInputs)
-{
-    m_scheduler.run([this, dst_addr, payment_id, mixin_count, priority, preferredInputs] {
-        PendingTransaction *tx = createTransactionAll(dst_addr, payment_id, mixin_count, priority, preferredInputs);
-        QVector<QString> address {dst_addr};
-        emit transactionCreated(tx, address);
-    });
-}
+// Phase 3: Commit or dispose
 
-PendingTransaction *Wallet::createTransactionSingle(const QString &key_image, const QString &dst_addr, const size_t outputs,
-        PendingTransaction::Priority priority)
-{
-//    pauseRefresh();
+void Wallet::commitTransaction(PendingTransaction *tx, const QString &description) {
+    // Clear list of selected transfers
+    this->setSelectedInputs({});
 
-    Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionSingle(key_image.toStdString(), dst_addr.toStdString(),
-            outputs, static_cast<Monero::PendingTransaction::Priority>(priority));
-    PendingTransaction * result = new PendingTransaction(ptImpl, this);
+    // Nodes - even well-connected, properly configured ones - consistently fail to relay transactions
+    // To mitigate transactions failing we just send the transaction to every node we know about over Tor
+    if (config()->get(Config::multiBroadcast).toBool()) {
+        // Let MainWindow handle this
+        emit multiBroadcast(tx);
+    }
 
-//    startRefresh();
-    return result;
-}
+    m_scheduler.run([this, tx, description] {
+        auto txIdList = tx->txid();  // retrieve before commit
+        bool success = tx->commit();
 
-void Wallet::createTransactionSingleAsync(const QString &key_image, const QString &dst_addr, const size_t outputs,
-                                          PendingTransaction::Priority priority)
-{
-    m_scheduler.run([this, key_image, dst_addr, outputs, priority] {
-        PendingTransaction *tx = createTransactionSingle(key_image, dst_addr, outputs, priority);
-        QVector<QString> address {dst_addr};
-        emit transactionCreated(tx, address);
-    });
-}
+        if (success && !description.isEmpty()) {
+            for (const auto &txid : txIdList) {
+                this->setUserNote(txid, description);
+            }
+        }
 
-PendingTransaction *Wallet::createTransactionSelected(const QVector<QString> &key_images, const QString &dst_addr,
-                                                      size_t outputs, PendingTransaction::Priority priority)
-{
-    std::vector<std::string> kis;
-    for (const auto &key_image : key_images) {
-        kis.push_back(key_image.toStdString());
-    }
-    Monero::PendingTransaction *ptImpl = m_walletImpl->createTransactionSelected(kis, dst_addr.toStdString(), outputs, static_cast<Monero::PendingTransaction::Priority>(priority));
-    PendingTransaction *result = new PendingTransaction(ptImpl, this);
+        // Store wallet immediately, so we don't risk losing tx key if wallet crashes
+        this->storeSafer();
 
-    return result;
-}
+        this->history()->refresh(this->currentSubaddressAccount());
+        this->coins()->refresh(this->currentSubaddressAccount());
 
-void Wallet::createTransactionSelectedAsync(const QVector<QString> &key_images, const QString &dst_addr,
-                                            size_t outputs, PendingTransaction::Priority priority)
-{
-    m_scheduler.run([this, key_images, dst_addr, outputs, priority] {
-        PendingTransaction *tx = createTransactionSelected(key_images, dst_addr, outputs, priority);
-        QVector<QString> address {dst_addr};
-        emit transactionCreated(tx, address);
+        this->updateBalance();
+
+        // this tx was a donation to Feather, stop our nagging
+        if (this->donationSending) {
+            this->donationSending = false;
+            emit donationSent();
+        }
+
+        emit transactionCommitted(success, tx, txIdList);
     });
 }
 
-PendingTransaction *Wallet::createSweepUnmixableTransaction()
-{
-//    pauseRefresh();
-
-    Monero::PendingTransaction * ptImpl = m_walletImpl->createSweepUnmixableTransaction();
-    PendingTransaction * result = new PendingTransaction(ptImpl, this);
+void Wallet::disposeTransaction(PendingTransaction *t) {
+    m_walletImpl->disposeTransaction(t->m_pimpl);
+    delete t;
+}
 
-//    startRefresh();
-    return result;
+void Wallet::disposeTransaction(UnsignedTransaction *t) {
+    delete t;
 }
 
-void Wallet::createSweepUnmixableTransactionAsync()
+// #################### Transaction import ####################
+
+bool Wallet::haveTransaction(const QString &txid)
 {
-    m_scheduler.run([this] {
-        PendingTransaction *tx = createSweepUnmixableTransaction();
-        QVector<QString> address {""};
-        emit transactionCreated(tx, address);
-    });
+    return m_walletImpl->haveTransaction(txid.toStdString());
 }
 
 UnsignedTransaction * Wallet::loadTxFile(const QString &fileName)
 {
     qDebug() << "Trying to sign " << fileName;
-    Monero::UnsignedTransaction * ptImpl = m_walletImpl->loadUnsignedTx(fileName.toStdString());
-    UnsignedTransaction * result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
+    Monero::UnsignedTransaction *ptImpl = m_walletImpl->loadUnsignedTx(fileName.toStdString());
+    UnsignedTransaction *result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
     return result;
 }
 
 UnsignedTransaction * Wallet::loadTxFromBase64Str(const QString &unsigned_tx)
 {
-    Monero::UnsignedTransaction * ptImpl = m_walletImpl->loadUnsignedTxFromBase64Str(unsigned_tx.toStdString());
-    UnsignedTransaction * result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
+    Monero::UnsignedTransaction *ptImpl = m_walletImpl->loadUnsignedTxFromBase64Str(unsigned_tx.toStdString());
+    UnsignedTransaction *result = new UnsignedTransaction(ptImpl, m_walletImpl, this);
     return result;
 }
 
 PendingTransaction * Wallet::loadSignedTxFile(const QString &fileName)
 {
     qDebug() << "Tying to load " << fileName;
-    Monero::PendingTransaction * ptImpl = m_walletImpl->loadSignedTx(fileName.toStdString());
-    PendingTransaction * result = new PendingTransaction(ptImpl, this);
+    Monero::PendingTransaction *ptImpl = m_walletImpl->loadSignedTx(fileName.toStdString());
+    PendingTransaction *result = new PendingTransaction(ptImpl, this);
     return result;
 }
 
@@ -811,77 +880,16 @@ bool Wallet::submitTxFile(const QString &fileName) const
     return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages");
 }
 
-bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
-{
-    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();
-        }
-
-        return result;
-    }
-}
-
-void Wallet::commitTransactionAsync(PendingTransaction *t, const QString &description)
-{
-    m_scheduler.run([this, t, description] {
-        auto txIdList = t->txid();  // retrieve before commit
-        bool success = t->commit();
-
-        if (success && !description.isEmpty()) {
-            for (const auto &txid : txIdList) {
-                this->setUserNote(txid, description);
-            }
-        }
-
-        emit transactionCommitted(success, t, txIdList);
-    });
-}
-
-void Wallet::disposeTransaction(PendingTransaction *t)
-{
-    m_walletImpl->disposeTransaction(t->m_pimpl);
-    delete t;
-}
-
-void Wallet::disposeTransaction(UnsignedTransaction *t)
-{
-    delete t;
-}
+// #################### Models ####################
 
-//void Wallet::estimateTransactionFeeAsync(const QString &destination,
-//                                         quint64 amount,
-//                                         PendingTransaction::Priority priority,
-//                                         const QJSValue &callback)
-//{
-//    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));
-//        return QJSValueList({QString::fromStdString(Monero::Wallet::displayAmount(fee))});
-//    }, callback);
-//}
-
-TransactionHistory *Wallet::history() const
-{
+TransactionHistory *Wallet::history() const {
     return m_history;
 }
 
-TransactionHistoryProxyModel *Wallet::historyModel() const
+TransactionHistoryProxyModel *Wallet::historyModel()
 {
     if (!m_historyModel) {
-        Wallet * w = const_cast<Wallet*>(this);
+        Wallet *w = const_cast<Wallet*>(this);
         m_historyModel = new TransactionHistoryModel(w);
         m_historyModel->setTransactionHistory(this->history());
         m_historySortFilterModel = new TransactionHistoryProxyModel(w);
@@ -893,108 +901,49 @@ TransactionHistoryProxyModel *Wallet::historyModel() const
     return m_historySortFilterModel;
 }
 
-TransactionHistoryModel *Wallet::transactionHistoryModel() const
-{
+TransactionHistoryModel* Wallet::transactionHistoryModel() const {
     return m_historyModel;
 }
 
-AddressBook *Wallet::addressBook() const
-{
+AddressBook* Wallet::addressBook() const {
     return m_addressBook;
 }
 
-AddressBookModel *Wallet::addressBookModel() const
-{
-
-    if (!m_addressBookModel) {
-        Wallet * w = const_cast<Wallet*>(this);
-        m_addressBookModel = new AddressBookModel(w,m_addressBook);
-    }
-
+AddressBookModel* Wallet::addressBookModel() const {
     return m_addressBookModel;
 }
 
-Subaddress *Wallet::subaddress()
-{
+Subaddress* Wallet::subaddress() const {
     return m_subaddress;
 }
 
-SubaddressModel *Wallet::subaddressModel()
-{
-    if (!m_subaddressModel) {
-        m_subaddressModel = new SubaddressModel(this, m_subaddress);
-    }
+SubaddressModel* Wallet::subaddressModel() const {
     return m_subaddressModel;
 }
 
-SubaddressAccount *Wallet::subaddressAccount() const
-{
+SubaddressAccount* Wallet::subaddressAccount() const {
     return m_subaddressAccount;
 }
 
-SubaddressAccountModel *Wallet::subaddressAccountModel() const
-{
-    if (!m_subaddressAccountModel) {
-        Wallet * w = const_cast<Wallet*>(this);
-        m_subaddressAccountModel = new SubaddressAccountModel(w,m_subaddressAccount);
-    }
+SubaddressAccountModel* Wallet::subaddressAccountModel() const {
     return m_subaddressAccountModel;
 }
 
-Coins *Wallet::coins() const
-{
+Coins* Wallet::coins() const {
     return m_coins;
 }
 
-CoinsModel *Wallet::coinsModel() const
-{
-    if (!m_coinsModel) {
-        Wallet * w = const_cast<Wallet*>(this);
-        m_coinsModel = new CoinsModel(w, m_coins);
-    }
+CoinsModel* Wallet::coinsModel() const {
     return m_coinsModel;
 }
 
-QString Wallet::generatePaymentId() const
-{
-    return QString::fromStdString(Monero::Wallet::genPaymentId());
-}
-
-QString Wallet::integratedAddress(const QString &paymentId) const
-{
-    return QString::fromStdString(m_walletImpl->integratedAddress(paymentId.toStdString()));
-}
-
-bool Wallet::cacheAttributeExists(const QString &key) {
-    return m_walletImpl->cacheAttributeExists(key.toStdString());
-}
-
-QString Wallet::getCacheAttribute(const QString &key) const {
-    return QString::fromStdString(m_walletImpl->getCacheAttribute(key.toStdString()));
-}
-
-bool Wallet::setCacheAttribute(const QString &key, const QString &val)
-{
-    return m_walletImpl->setCacheAttribute(key.toStdString(), val.toStdString());
-}
-
-bool Wallet::setUserNote(const QString &txid, const QString &note)
-{
-    return m_walletImpl->setUserNote(txid.toStdString(), note.toStdString());
-}
-
-QString Wallet::getUserNote(const QString &txid) const
-{
-    return QString::fromStdString(m_walletImpl->getUserNote(txid.toStdString()));
-}
+// #################### Transaction proofs ####################
 
-QString Wallet::getTxKey(const QString &txid) const
-{
+QString Wallet::getTxKey(const QString &txid) const {
     return QString::fromStdString(m_walletImpl->getTxKey(txid.toStdString()));
 }
 
-void Wallet::getTxKeyAsync(const QString &txid, const std::function<void (QVariantMap)> &callback)
-{
+void Wallet::getTxKeyAsync(const QString &txid, const std::function<void (QVariantMap)> &callback) {
     m_scheduler.run([this, txid] {
         QVariantMap map;
         map["tx_key"] = getTxKey(txid);
@@ -1002,32 +951,23 @@ void Wallet::getTxKeyAsync(const QString &txid, const std::function<void (QVaria
     }, callback);
 }
 
-TxKeyResult Wallet::checkTxKey(const QString &txid, const QString &tx_key, const QString &address)
-{
+TxKeyResult Wallet::checkTxKey(const QString &txid, const QString &tx_key, const QString &address) {
     uint64_t received;
     bool in_pool;
     uint64_t confirmations;
+
     bool success = m_walletImpl->checkTxKey(txid.toStdString(), tx_key.toStdString(), address.toStdString(), received, in_pool, confirmations);
     QString errorString = success ? "" : this->errorString();
     bool good = received > 0;
     return {success, good, QString::fromStdString(Monero::Wallet::displayAmount(received)), in_pool, confirmations, errorString};
 }
 
-TxProof Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const
-{
+TxProof Wallet::getTxProof(const QString &txid, const QString &address, const QString &message) const {
     std::string result = m_walletImpl->getTxProof(txid.toStdString(), address.toStdString(), message.toStdString());
     return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString()));
 }
 
-//void Wallet::getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback)
-//{
-//    m_scheduler.run([this, txid, address, message] {
-//        return QJSValueList({txid, getTxProof(txid, address, message)});
-//    }, callback);
-//}
-
-TxProofResult Wallet::checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature)
-{
+TxProofResult Wallet::checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature) {
     bool good;
     uint64_t received;
     bool in_pool;
@@ -1036,29 +976,19 @@ TxProofResult Wallet::checkTxProof(const QString &txid, const QString &address,
     return {success, good, received, in_pool, confirmations};
 }
 
-void Wallet::checkTxProofAsync(const QString &txid, const QString &address, const QString &message,
-                               const QString &signature) {
+void Wallet::checkTxProofAsync(const QString &txid, const QString &address, const QString &message, const QString &signature) {
     m_scheduler.run([this, txid, address, message, signature] {
         auto result = this->checkTxProof(txid, address, message, signature);
         emit transactionProofVerified(result);
     });
 }
 
-Q_INVOKABLE TxProof Wallet::getSpendProof(const QString &txid, const QString &message) const
-{
+TxProof Wallet::getSpendProof(const QString &txid, const QString &message) const {
     std::string result = m_walletImpl->getSpendProof(txid.toStdString(), message.toStdString());
     return TxProof(QString::fromStdString(result), QString::fromStdString(m_walletImpl->errorString()));
 }
 
-//void Wallet::getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback)
-//{
-//    m_scheduler.run([this, txid, message] {
-//        return QJSValueList({txid, getSpendProof(txid, message)});
-//    }, callback);
-//}
-
-Q_INVOKABLE QPair<bool, bool> Wallet::checkSpendProof(const QString &txid, const QString &message,
-                                                      const QString &signature) const {
+QPair<bool, bool> Wallet::checkSpendProof(const QString &txid, const QString &message, const QString &signature) const {
     bool good;
     bool success = m_walletImpl->checkSpendProof(txid.toStdString(), message.toStdString(), signature.toStdString(), good);
     return {success, good};
@@ -1071,80 +1001,81 @@ void Wallet::checkSpendProofAsync(const QString &txid, const QString &message, c
     });
 }
 
-QString Wallet::signMessage(const QString &message, bool filename, const QString &address) const
-{
-  if (filename) {
-    QFile file(message);
-    uchar *data = NULL;
+// #################### Sign / Verify message ####################
 
-    try {
-      if (!file.open(QIODevice::ReadOnly))
-        return "";
-      quint64 size = file.size();
-      if (size == 0) {
-        file.close();
-        return QString::fromStdString(m_walletImpl->signMessage(std::string()));
-      }
-      data = file.map(0, size);
-      if (!data) {
-        file.close();
-        return "";
-      }
-      std::string signature = m_walletImpl->signMessage(std::string(reinterpret_cast<const char*>(data), size), address.toStdString());
-      file.unmap(data);
-      file.close();
-      return QString::fromStdString(signature);
+QString Wallet::signMessage(const QString &message, bool filename, const QString &address) const {
+    if (filename) {
+        QFile file(message);
+        uchar *data = nullptr;
+
+        try {
+            if (!file.open(QIODevice::ReadOnly))
+                return "";
+            quint64 size = file.size();
+            if (size == 0) {
+                file.close();
+                return QString::fromStdString(m_walletImpl->signMessage(std::string()));
+            }
+            data = file.map(0, size);
+            if (!data) {
+                file.close();
+                return "";
+            }
+            std::string signature = m_walletImpl->signMessage(std::string(reinterpret_cast<const char*>(data), size), address.toStdString());
+            file.unmap(data);
+            file.close();
+            return QString::fromStdString(signature);
+        }
+        catch (const std::exception &e) {
+            if (data)
+                file.unmap(data);
+            file.close();
+            return "";
+        }
     }
-    catch (const std::exception &e) {
-      if (data)
-        file.unmap(data);
-      file.close();
-      return "";
+    else {
+        return QString::fromStdString(m_walletImpl->signMessage(message.toStdString(), address.toStdString()));
     }
-  }
-  else {
-    return QString::fromStdString(m_walletImpl->signMessage(message.toStdString(), address.toStdString()));
-  }
 }
 
-bool Wallet::verifySignedMessage(const QString &message, const QString &address, const QString &signature, bool filename) const
-{
-  if (filename) {
-    QFile file(message);
-    uchar *data = NULL;
+bool Wallet::verifySignedMessage(const QString &message, const QString &address, const QString &signature, bool filename) const {
+    if (filename) {
+        QFile file(message);
+        uchar *data = nullptr;
 
-    try {
-      if (!file.open(QIODevice::ReadOnly))
-        return false;
-      quint64 size = file.size();
-      if (size == 0) {
-        file.close();
-        return m_walletImpl->verifySignedMessage(std::string(), address.toStdString(), signature.toStdString());
-      }
-      data = file.map(0, size);
-      if (!data) {
-        file.close();
-        return false;
-      }
-      bool ret = m_walletImpl->verifySignedMessage(std::string(reinterpret_cast<const char*>(data), size), address.toStdString(), signature.toStdString());
-      file.unmap(data);
-      file.close();
-      return ret;
+        try {
+            if (!file.open(QIODevice::ReadOnly))
+                return false;
+            quint64 size = file.size();
+            if (size == 0) {
+                file.close();
+                return m_walletImpl->verifySignedMessage(std::string(), address.toStdString(), signature.toStdString());
+            }
+            data = file.map(0, size);
+            if (!data) {
+                file.close();
+                return false;
+            }
+            bool ret = m_walletImpl->verifySignedMessage(std::string(reinterpret_cast<const char*>(data), size), address.toStdString(), signature.toStdString());
+            file.unmap(data);
+            file.close();
+            return ret;
+        }
+        catch (const std::exception &e) {
+            if (data)
+                file.unmap(data);
+            file.close();
+            return false;
+        }
     }
-    catch (const std::exception &e) {
-      if (data)
-        file.unmap(data);
-      file.close();
-      return false;
+    else {
+        return m_walletImpl->verifySignedMessage(message.toStdString(), address.toStdString(), signature.toStdString());
     }
-  }
-  else {
-    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) const
-{
+// #################### URI Parsing ####################
+
+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) const {
    std::string s_address, s_payment_id, s_tx_description, s_recipient_name, s_error;
    std::vector<std::string> s_unknown_parameters;
    bool res= m_walletImpl->parse_uri(uri.toStdString(), s_address, s_payment_id, amount, s_tx_description, s_recipient_name, s_unknown_parameters, s_error);
@@ -1161,8 +1092,7 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
    return res;
 }
 
-QVariantMap Wallet::parse_uri_to_object(const QString &uri) const
-{
+QVariantMap Wallet::parse_uri_to_object(const QString &uri) const {
     QString address;
     QString payment_id;
     uint64_t amount = 0;
@@ -1185,157 +1115,13 @@ QVariantMap Wallet::parse_uri_to_object(const QString &uri) const
     return result;
 }
 
-QString Wallet::make_uri(const QString &address, quint64 &amount, const QString &description,
-                         const QString &recipient) const
-{
+QString Wallet::make_uri(const QString &address, quint64 &amount, const QString &description, const QString &recipient) const {
     std::string error;
     std::string uri = m_walletImpl->make_uri(address.toStdString(), "", amount, description.toStdString(), recipient.toStdString(), error);
     return QString::fromStdString(uri);
 }
 
-bool Wallet::rescanSpent()
-{
-    QMutexLocker locker(&m_asyncMutex);
-
-    return m_walletImpl->rescanSpent();
-}
-
-bool Wallet::useForkRules(quint8 required_version, quint64 earlyBlocks) const
-{
-    if(m_connectionStatus == Wallet::ConnectionStatus_Disconnected)
-        return false;
-    try {
-        return m_walletImpl->useForkRules(required_version,earlyBlocks);
-    } catch (const std::exception &e) {
-        qDebug() << e.what();
-        return false;
-    }
-}
-
-void Wallet::setWalletCreationHeight(quint64 height)
-{
-    m_walletImpl->setRefreshFromBlockHeight(height);
-    emit walletCreationHeightChanged();
-}
-
-QString Wallet::getDaemonLogPath() const
-{
-    return QString::fromStdString(m_walletImpl->getDefaultDataDir()) + "/bitmonero.log";
-}
-
-bool Wallet::blackballOutput(const QString &amount, const QString &offset)
-{
-    return m_walletImpl->blackballOutput(amount.toStdString(), offset.toStdString());
-}
-
-bool Wallet::blackballOutputs(const QList<QString> &pubkeys, bool add)
-{
-    std::vector<std::string> std_pubkeys;
-    foreach (const QString &pubkey, pubkeys) {
-        std_pubkeys.push_back(pubkey.toStdString());
-    }
-    return m_walletImpl->blackballOutputs(std_pubkeys, add);
-}
-
-bool Wallet::blackballOutputs(const QString &filename, bool add)
-{
-    QFile file(filename);
-
-    try {
-        if (!file.open(QIODevice::ReadOnly))
-            return false;
-        QList<QString> outputs;
-        QTextStream in(&file);
-        while (!in.atEnd()) {
-            outputs.push_back(in.readLine());
-        }
-        file.close();
-        return blackballOutputs(outputs, add);
-    }
-    catch (const std::exception &e) {
-        file.close();
-        return false;
-    }
-}
-
-bool Wallet::unblackballOutput(const QString &amount, const QString &offset)
-{
-    return m_walletImpl->unblackballOutput(amount.toStdString(), offset.toStdString());
-}
-
-QString Wallet::getRing(const QString &key_image)
-{
-    std::vector<uint64_t> cring;
-    if (!m_walletImpl->getRing(key_image.toStdString(), cring))
-        return "";
-    QString ring = "";
-    for (uint64_t out: cring)
-    {
-        if (!ring.isEmpty())
-            ring = ring + " ";
-        QString s;
-        s.setNum(out);
-        ring = ring + s;
-    }
-    return ring;
-}
-
-QString Wallet::getRings(const QString &txid)
-{
-    std::vector<std::pair<std::string, std::vector<uint64_t>>> crings;
-    if (!m_walletImpl->getRings(txid.toStdString(), crings))
-        return "";
-    QString ring = "";
-    for (const auto &cring: crings)
-    {
-        if (!ring.isEmpty())
-            ring = ring + "|";
-        ring = ring + QString::fromStdString(cring.first) + " absolute";
-        for (uint64_t out: cring.second)
-        {
-            ring = ring + " ";
-            QString s;
-            s.setNum(out);
-            ring = ring + s;
-        }
-    }
-    return ring;
-}
-
-bool Wallet::setRing(const QString &key_image, const QString &ring, bool relative)
-{
-    std::vector<uint64_t> cring;
-    QStringList strOuts = ring.split(" ");
-    foreach(QString str, strOuts)
-    {
-        uint64_t out;
-        bool ok;
-        out = str.toULong(&ok);
-        if (ok)
-            cring.push_back(out);
-    }
-    return m_walletImpl->setRing(key_image.toStdString(), cring, relative);
-}
-
-void Wallet::segregatePreForkOutputs(bool segregate)
-{
-    m_walletImpl->segregatePreForkOutputs(segregate);
-}
-
-void Wallet::segregationHeight(quint64 height)
-{
-    m_walletImpl->segregationHeight(height);
-}
-
-void Wallet::keyReuseMitigation2(bool mitigation)
-{
-    m_walletImpl->keyReuseMitigation2(mitigation);
-}
-
-void Wallet::onWalletPassphraseNeeded(bool on_device)
-{
-    emit this->walletPassphraseNeeded(on_device);
-}
+// #################### Misc / Unused ####################
 
 quint64 Wallet::getBytesReceived() const {
     // TODO: this can segfault. Unclear why.
@@ -1351,57 +1137,34 @@ quint64 Wallet::getBytesSent() const {
     return m_walletImpl->getBytesSent();
 }
 
-bool Wallet::isDeviceConnected() const {
-    return m_walletImpl->isDeviceConnected();
+QString Wallet::getDaemonLogPath() const {
+    return QString::fromStdString(m_walletImpl->getDefaultDataDir()) + "/bitmonero.log";
 }
 
 bool Wallet::setRingDatabase(const QString &path) {
     return m_walletImpl->setRingDatabase(path.toStdString());
 }
 
-void Wallet::onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort)
-{
-    if (m_walletListener != nullptr)
-    {
-        m_walletListener->onPassphraseEntered(passphrase, enter_on_device, entry_abort);
-    }
+void Wallet::setWalletCreationHeight(quint64 height) {
+    m_walletImpl->setRefreshFromBlockHeight(height);
 }
 
-Wallet::Wallet(Monero::Wallet *w, QObject *parent)
-        : QObject(parent)
-        , m_walletImpl(w)
-        , m_history(new TransactionHistory(m_walletImpl->history(), this))
-        , m_historyModel(nullptr)
-        , m_addressBook(new AddressBook(m_walletImpl->addressBook(), this))
-        , m_addressBookModel(nullptr)
-        , m_daemonBlockChainHeight(0)
-        , m_daemonBlockChainTargetHeight(0)
-        , m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
-        , m_disconnected(true)
-        , m_currentSubaddressAccount(0)
-        , m_subaddress(new Subaddress(m_walletImpl->subaddress(), this))
-        , m_subaddressModel(nullptr)
-        , m_subaddressAccount(new SubaddressAccount(m_walletImpl->subaddressAccount(), this))
-        , m_subaddressAccountModel(nullptr)
-        , m_coinsModel(nullptr)
-        , m_refreshNow(false)
-        , m_refreshEnabled(false)
-        , m_refreshing(false)
-        , m_scheduler(this)
-        , m_useSSL(true)
-        , m_coins(new Coins(m_walletImpl->coins(), this))
-{
-    m_walletListener = new WalletListenerImpl(this);
-    m_walletImpl->setListener(m_walletListener);
-    m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
-    // start cache timers
-    m_initialized = false;
-    m_daemonUsername = "";
-    m_daemonPassword = "";
+//! create a view only wallet
+bool Wallet::createViewOnly(const QString &path, const QString &password) const {
+    // Create path
+    QDir d = QFileInfo(path).absoluteDir();
+    d.mkpath(d.absolutePath());
+    return m_walletImpl->createWatchOnly(path.toStdString(),password.toStdString(),m_walletImpl->getSeedLanguage());
+}
 
-    if (this->status() == Status_Ok) {
-        startRefreshThread();
-    }
+bool Wallet::rescanSpent() {
+    QMutexLocker locker(&m_asyncMutex);
+
+    return m_walletImpl->rescanSpent();
+}
+
+void Wallet::setNewWallet() {
+    m_newWallet = true;
 }
 
 Wallet::~Wallet()
@@ -1413,57 +1176,15 @@ Wallet::~Wallet()
 
     m_scheduler.shutdownWaitForFinished();
 
-    //Monero::WalletManagerFactory::getWalletManager()->closeWallet(m_walletImpl);
-    if(status() == Status_Critical || status() == Status_BadPassword)
+    if (status() == Status_Critical || status() == Status_BadPassword) {
         qDebug("Not storing wallet cache");
-    else if( m_walletImpl->store())
-        qDebug("Wallet cache stored successfully");
-    else
-        qDebug("Error storing wallet cache");
+    }
+    else {
+        bool success = m_walletImpl->store();
+        success ? qDebug("Wallet cache stored successfully") : qDebug("Error storing wallet cache");
+    }
+
     delete m_walletImpl;
     m_walletImpl = nullptr;
-    delete m_walletListener;
-    m_walletListener = NULL;
     qDebug("m_walletImpl deleted");
 }
-
-void Wallet::startRefreshThread()
-{
-    const auto future = m_scheduler.run([this] {
-        constexpr const std::chrono::seconds refreshInterval{10};
-        constexpr const std::chrono::milliseconds intervalResolution{100};
-
-        auto last = std::chrono::steady_clock::now();
-        while (!m_scheduler.stopping())
-        {
-            if (m_refreshEnabled && (!isHwBacked() || isDeviceConnected()))
-            {
-                const auto now = std::chrono::steady_clock::now();
-                const auto elapsed = now - last;
-                if (elapsed >= refreshInterval || m_refreshNow)
-                {
-                    m_refreshNow = false;
-                    // Don't call refresh function if we don't have the daemon and target height
-                    // We do this to prevent to UI from getting confused about the amount of blocks that are still remaining
-                    bool haveHeights = refreshHeights();
-                    if (haveHeights) {
-                        refresh(false);
-                    }
-                    last = std::chrono::steady_clock::now();
-                }
-            }
-
-            std::this_thread::sleep_for(intervalResolution);
-        }
-    });
-    if (!future.first)
-    {
-        throw std::runtime_error("failed to start auto refresh thread");
-    }
-}
-
-void Wallet::onRefreshed(bool success) {
-    if (!success) {
-        setConnectionStatus(ConnectionStatus_Disconnected);
-    }
-}
\ No newline at end of file
index 84ee30f522dd717827476fbefa222c29baf57731..b165ab8365350d6ddc8b5b56038e55ead3078d91 100644 (file)
@@ -10,9 +10,9 @@
 #include <QList>
 #include <QtConcurrent/QtConcurrent>
 
-#include "wallet/api/wallet2_api.h" // we need to have an access to the Monero::Wallet::Status enum here;
+#include "wallet/api/wallet2_api.h"
 #include "utils/scheduler.h"
-#include "PendingTransaction.h" // we need to have an access to the PendingTransaction::Priority enum here;
+#include "PendingTransaction.h"
 #include "UnsignedTransaction.h"
 #include "utils/networktype.h"
 #include "PassphraseHelper.h"
@@ -86,8 +86,7 @@ class Wallet : public QObject, public PassphrasePrompter
 Q_OBJECT
 
 public:
-    explicit Wallet(QObject *parent = nullptr);
-    explicit Wallet(Monero::Wallet *w, QObject * parent = nullptr);
+    explicit Wallet(Monero::Wallet *w, QObject *parent = nullptr);
     ~Wallet() override;
 
     enum Status {
@@ -109,28 +108,12 @@ public:
 
     Q_ENUM(ConnectionStatus)
 
-    //! return connection status
-    ConnectionStatus connectionStatus() const;
-
-    //! returns mnemonic seed
-    QString getSeed(const QString &seedOffset) const;
-
-    qsizetype seedLength() const;
-
-    //! returns seed language
-    QString getSeedLanguage() const;
-
-    //! set seed language
-    void setSeedLanguage(const QString &lang);
-
+    // ##### Status #####
     //! returns last operation's status
     Status status() const;
 
-    //! returns network type of the wallet.
-    NetworkType::Type nettype() const;
-
-    //! returns true if wallet was ever synchronized
-    bool synchronized() const;
+    //! return connection status
+    ConnectionStatus connectionStatus() const;
 
     //! returns true if wallet is currently synchronized
     bool isSynchronized() const;
@@ -138,61 +121,19 @@ public:
     //! return true if wallet is connected to a node
     bool isConnected() const;
 
-    void setOffline(bool offline) const;
-
     //! returns last operation's error message
     QString errorString() const;
 
-    //! changes the password using existing parameters (path, seed, seed lang)
-    bool setPassword(const QString &oldPassword, const QString &newPassword);
-
-    //! verify wallet password
-    bool verifyPassword(const QString &password);
-
-    //! returns wallet's public address
-    QString address(quint32 accountIndex, quint32 addressIndex) const;
-
-    //! returns the subaddress index of the address
-    SubaddressIndex subaddressIndex(const QString &address) const;
-
-    //! returns wallet cache file path
-    QString cachePath() const;
-
-    //! returns wallet keys file path
-    QString keysPath() const;
-
-    //! saves wallet to the file by given path
-    //! empty path stores in current location
-    void store();
-   // void storeAsync(const QJSValue &callback, const QString &path = "");
-
-    //! initializes wallet asynchronously
-    void initAsync(
-            const QString &daemonAddress,
-            bool trustedDaemon = false,
-            quint64 upperTransactionLimit = 0,
-            bool isRecovering = false,
-            bool isRecoveringFromDevice = false,
-            quint64 restoreHeight = 0,
-            const QString &proxyAddress = "");
-
-    bool setDaemon(const QString &daemonAddress);
-
-    // Set daemon rpc user/pass
-    void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
-
-    //! create a view only wallet
-    bool createViewOnly(const QString &path, const QString &password) const;
-
-    //! connects to daemon
-    bool connectToDaemon();
+    //! returns network type of the wallet.
+    NetworkType::Type nettype() const;
 
-    //! indicates if daemon is trusted
-    void setTrustedDaemon(bool arg);
+    //! returns if view only wallet
+    bool viewOnly() const;
 
-    //! indicates if ssl should be used to connect to daemon
-    void setUseSSL(bool ssl);
+    //! return true if deterministic keys
+    bool isDeterministic() const;
 
+    // ##### Balance #####
     //! returns balance
     quint64 balance() const;
     quint64 balance(quint32 accountIndex) const;
@@ -203,7 +144,15 @@ public:
     quint64 unlockedBalance(quint32 accountIndex) const;
     quint64 unlockedBalanceAll() const;
 
-    //! account/address management
+    void updateBalance();
+
+    // ##### Subaddresses and Accounts #####
+    //! returns wallet's public address
+    QString address(quint32 accountIndex, quint32 addressIndex) const;
+
+    //! returns the subaddress index of the address
+    SubaddressIndex subaddressIndex(const QString &address) const;
+
     quint32 currentSubaddressAccount() const;
     void switchSubaddressAccount(quint32 accountIndex);
     void addSubaddressAccount(const QString& label);
@@ -215,23 +164,77 @@ public:
     void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId);
     QString getSubaddressLookahead() const;
 
-    //! hw-device backed wallets
+    // ##### Seed #####
+
+    //! returns mnemonic seed
+    QString getSeed(const QString &seedOffset) const;
+
+    qsizetype seedLength() const;
+
+    //! returns seed language
+    QString getSeedLanguage() const;
+
+    //! set seed language
+    void setSeedLanguage(const QString &lang);
+
+    //! Get wallet keys
+    QString getSecretViewKey() const {return QString::fromStdString(m_walletImpl->secretViewKey());}
+    QString getPublicViewKey() const {return QString::fromStdString(m_walletImpl->publicViewKey());}
+    QString getSecretSpendKey() const {return QString::fromStdString(m_walletImpl->secretSpendKey());}
+    QString getPublicSpendKey() const {return QString::fromStdString(m_walletImpl->publicSpendKey());}
+
+    // ##### Node connection #####
+
+    void setOffline(bool offline) const;
+
+    //! indicates if daemon is trusted
+    void setTrustedDaemon(bool arg);
+
+    //! indicates if ssl should be used to connect to daemon
+    void setUseSSL(bool ssl);
+
+    //! Set daemon rpc user/pass
+    void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
+
+    //! initializes wallet asynchronously
+    void initAsync(const QString &daemonAddress,
+                   bool trustedDaemon = false,
+                   quint64 upperTransactionLimit = 0,
+                   const QString &proxyAddress = "");
+
+    // ##### Synchronization (Refresh) #####
+    void startRefresh();
+    void pauseRefresh();
+
+    //! returns current wallet's block height
+    //! (can be less than daemon's blockchain height when wallet sync in progress)
+    quint64 blockChainHeight() const;
+
+    //! returns daemon's blockchain height
+    quint64 daemonBlockChainHeight() const;
+
+    //! returns daemon's blockchain target height
+    quint64 daemonBlockChainTargetHeight() const;
+
+    void syncStatusUpdated(quint64 height, quint64 target);
+
+    void refreshModels();
+
+    // ##### Hardware wallet #####
     bool isHwBacked() const;
     bool isLedger() const;
     bool isTrezor() const;
 
+    bool isDeviceConnected() const;
+
     //! attempt to reconnect to hw-device
     bool reconnectDevice();
 
-    //! returns if view only wallet
-    bool viewOnly() const;
-
-    //! return true if deterministic keys
-    bool isDeterministic() const;
-
-    //! refresh daemon blockchain and target height
-    bool refreshHeights();
+    // Passphrase entry for hardware wallets
+    void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
+    void onWalletPassphraseNeeded(bool on_device) override;
 
+    // ##### Import / Export #####
     //! export/import key images
     bool exportKeyImages(const QString& path, bool all = false);
     bool importKeyImages(const QString& path);
@@ -243,6 +246,35 @@ public:
     //! import a transaction
     bool importTransaction(const QString& txid);
 
+    // ##### Wallet cache #####
+    //! saves wallet to the file by given path
+    //! empty path stores in current location
+    void store();
+    void storeSafer();
+
+    //! returns wallet cache file path
+    QString cachePath() const;
+
+    //! returns wallet keys file path
+    QString keysPath() const;
+
+    //! changes the password using existing parameters (path, seed, seed lang)
+    bool setPassword(const QString &oldPassword, const QString &newPassword);
+
+    //! verify wallet password
+    bool verifyPassword(const QString &password);
+
+    //! Namespace your cacheAttribute keys to avoid collisions
+    bool cacheAttributeExists(const QString &key);
+    bool setCacheAttribute(const QString &key, const QString &val);
+    QString getCacheAttribute(const QString &key) const;
+
+    void addCacheTransaction(const QString &txid, const QString &txHex);
+    QString getCacheTransaction(const QString &txid) const;
+
+    bool setUserNote(const QString &txid, const QString &note);
+    QString getUserNote(const QString &txid) const;
+
     QString printBlockchain();
     QString printTransfers();
     QString printPayments();
@@ -261,77 +293,25 @@ public:
     QString printAddressBook();
     QString printScannedPoolTxs();
 
-    //! does wallet have txid
-    bool haveTransaction(const QString &txid);
-
-    //! refreshes the wallet
-    bool refresh(bool historyAndSubaddresses = false);
-
-    // pause/resume refresh
-    void startRefresh();
-    void pauseRefresh();
-
-    //! returns current wallet's block height
-    //! (can be less than daemon's blockchain height when wallet sync in progress)
-    quint64 blockChainHeight() const;
-
-    //! returns daemon's blockchain height
-    quint64 daemonBlockChainHeight() const;
-
-    //! returns daemon's blockchain target height
-    quint64 daemonBlockChainTargetHeight() const;
-
-    //! creates transaction
-    PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
-                                           quint64 amount, quint32 mixin_count,
-                                           PendingTransaction::Priority priority,
-                                           const QStringList &preferredInputs);
+    // ##### Transactions #####
+    void setSelectedInputs(const QStringList &selected);
 
-    //! creates async transaction
-    void createTransactionAsync(const QString &dst_addr, const QString &payment_id,
-                                quint64 amount, quint32 mixin_count,
-                                PendingTransaction::Priority priority, const QStringList &preferredInputs);
+    void createTransaction(const QString &address, quint64 amount, const QString &description, bool all);
+    void createTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
+    void sweepOutputs(const QVector<QString> &keyImages, QString address, bool churn, int outputs);
 
-    //! creates multi-destination transaction
-    PendingTransaction * createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
-                                                    PendingTransaction::Priority priority, const QStringList &preferredInputs);
+    void onCreateTransactionError(const QString &msg);
+    void commitTransaction(PendingTransaction *tx, const QString &description="");
 
-    //! creates async multi-destination transaction
-    void createTransactionMultiDestAsync(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
-                                         PendingTransaction::Priority priority, const QStringList &preferredInputs);
-
-
-    //! creates transaction with all outputs
-    PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
-                                              quint32 mixin_count, PendingTransaction::Priority priority,
-                                              const QStringList &preferredInputs);
-
-    //! creates async transaction with all outputs
-    void createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
-                                   quint32 mixin_count, PendingTransaction::Priority priority,
-                                   const QStringList &preferredInputs);
-
-    //! creates transaction with single input
-    PendingTransaction * createTransactionSingle(const QString &key_image, const QString &dst_addr,
-            size_t outputs, PendingTransaction::Priority priority);
-
-    //! creates async transaction with single input
-    void createTransactionSingleAsync(const QString &key_image, const QString &dst_addr,
-            size_t outputs, PendingTransaction::Priority priority);
-
-    //! creates transaction with selected inputs
-    PendingTransaction * createTransactionSelected(const QVector<QString> &key_images, const QString &dst_addr,
-                                                   size_t outputs, PendingTransaction::Priority priority);
-
-    //! creates async transaction with selected inputs
-    void createTransactionSelectedAsync(const QVector<QString> &key_images, const QString &dst_addr,
-                                        size_t outputs, PendingTransaction::Priority priority);
+    //! deletes transaction and frees memory
+    void disposeTransaction(PendingTransaction * t);
 
-    //! creates sweep unmixable transaction
-    PendingTransaction * createSweepUnmixableTransaction();
+    //! deletes unsigned transaction and frees memory
+    void disposeTransaction(UnsignedTransaction * t);
 
-    //! creates async sweep unmixable transaction
-    void createSweepUnmixableTransactionAsync();
+    // ##### Transaction import #####
+    //! does wallet have txid
+    bool haveTransaction(const QString &txid);
 
     //! Sign a transfer from file
     UnsignedTransaction * loadTxFile(const QString &fileName);
@@ -345,136 +325,73 @@ public:
     //! Submit a transfer from file
     bool submitTxFile(const QString &fileName) const;
 
-    //! asynchronous transaction commit
-    void commitTransactionAsync(PendingTransaction * t, const QString &description="");
+    // ##### Models #####
+    TransactionHistory* history() const;
+    TransactionHistoryProxyModel* historyModel();
+    TransactionHistoryModel* transactionHistoryModel() const;
+    AddressBook* addressBook() const;
+    AddressBookModel* addressBookModel() const;
+    Subaddress* subaddress() const;
+    SubaddressModel* subaddressModel() const;
+    SubaddressAccount* subaddressAccount() const;
+    SubaddressAccountModel* subaddressAccountModel() const;
+    Coins* coins() const;
+    CoinsModel* coinsModel() const;
+
+    // ##### Transaction proofs #####
 
-    //! deletes transaction and frees memory
-    void disposeTransaction(PendingTransaction * t);
-
-    //! deletes unsigned transaction and frees memory
-    void disposeTransaction(UnsignedTransaction * t);
-
-//    void estimateTransactionFeeAsync(const QString &destination,
-//                                                 quint64 amount,
-//                                                 PendingTransaction::Priority priority,
-//                                                 const QJSValue &callback);
-
-    //! returns transaction history
-    TransactionHistory * history() const;
-
-    //! returns transaction history model
-    TransactionHistoryProxyModel *historyModel() const;
-
-    //! returns transaction history model (the real one)
-    TransactionHistoryModel *transactionHistoryModel() const;
-
-    //! returns Address book
-    AddressBook *addressBook() const;
-
-    //! returns address book model
-    AddressBookModel *addressBookModel() const;
-
-    //! returns subaddress
-    Subaddress *subaddress();
-
-    //! returns subaddress model
-    SubaddressModel *subaddressModel();
-
-    //! returns subaddress account
-    SubaddressAccount *subaddressAccount() const;
-
-    //! returns subaddress account model
-    SubaddressAccountModel *subaddressAccountModel() const;
-
-    //! returns coins
-    Coins *coins() const;
-
-    //! return coins model
-    CoinsModel *coinsModel() const;
-
-    //! generate payment id
-    QString generatePaymentId() const;
+    QString getTxKey(const QString &txid) const;
+    void getTxKeyAsync(const QString &txid, const std::function<void (QVariantMap)> &callback);
 
-    //! integrated address
-    QString integratedAddress(const QString &paymentId) const;
+    TxKeyResult checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
+    TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const;
+    TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
+    void checkTxProofAsync(const QString &txid, const QString &address, const QString &message, const QString &signature);
+    TxProof getSpendProof(const QString &txid, const QString &message) const;
+    QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
+    void checkSpendProofAsync(const QString &txid, const QString &message, const QString &signature);
 
+    // ##### Sign / Verify message #####
     //! signing a message
     QString signMessage(const QString &message, bool filename = false, const QString &address = "") const;
 
     //! verify a signed message
     bool verifySignedMessage(const QString &message, const QString &address, const QString &signature, bool filename = false) const;
 
-    //! Parse URI
+    // ##### URI Parsing #####
     bool 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) const;
     QVariantMap parse_uri_to_object(const QString &uri) const;
 
     QString make_uri(const QString &address, quint64 &amount, const QString &description, const QString &recipient) const;
 
-    //! Namespace your cacheAttribute keys to avoid collisions
-    bool cacheAttributeExists(const QString &key);
-    bool setCacheAttribute(const QString &key, const QString &val);
-    QString getCacheAttribute(const QString &key) const;
-
-    bool setUserNote(const QString &txid, const QString &note);
-    QString getUserNote(const QString &txid) const;
-    QString getTxKey(const QString &txid) const;
-    void getTxKeyAsync(const QString &txid, const std::function<void (QVariantMap)> &callback);
+    // ##### Misc / Unused #####
 
-    TxKeyResult checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
-    TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const;
-   // void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback);
-    //QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
-    TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
-    void checkTxProofAsync(const QString &txid, const QString &address, const QString &message, const QString &signature);
-    TxProof getSpendProof(const QString &txid, const QString &message) const;
-   // void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback);
-    QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
-    void checkSpendProofAsync(const QString &txid, const QString &message, const QString &signature);
-    // Rescan spent outputs
-    bool rescanSpent();
+    quint64 getBytesReceived() const;
+    quint64 getBytesSent() const;
 
-    // check if fork rules should be used
-    bool useForkRules(quint8 version, quint64 earlyBlocks = 0) const;
+    QString getDaemonLogPath() const;
 
-    //! Get wallet keys
-    QString getSecretViewKey() const {return QString::fromStdString(m_walletImpl->secretViewKey());}
-    QString getPublicViewKey() const {return QString::fromStdString(m_walletImpl->publicViewKey());}
-    QString getSecretSpendKey() const {return QString::fromStdString(m_walletImpl->secretSpendKey());}
-    QString getPublicSpendKey() const {return QString::fromStdString(m_walletImpl->publicSpendKey());}
+    bool setRingDatabase(const QString &path);
 
     quint64 getWalletCreationHeight() const {return m_walletImpl->getRefreshFromBlockHeight();}
     void setWalletCreationHeight(quint64 height);
 
-    QString getDaemonLogPath() const;
+    //! Rescan spent outputs
+    bool rescanSpent();
 
-    // Blackballed outputs
-    bool blackballOutput(const QString &amount, const QString &offset);
-    bool blackballOutputs(const QList<QString> &outputs, bool add);
-    bool blackballOutputs(const QString &filename, bool add);
-    bool unblackballOutput(const QString &amount, const QString &offset);
+    //! Indicates that the wallet is new
+    void setNewWallet();
 
-    // Rings
-    QString getRing(const QString &key_image);
-    QString getRings(const QString &txid);
-    bool setRing(const QString &key_image, const QString &ring, bool relative);
+    //! create a view only wallet
+    bool createViewOnly(const QString &path, const QString &password) const;
 
-    // key reuse mitigation options
-    void segregatePreForkOutputs(bool segregate);
-    void segregationHeight(quint64 height);
-    void keyReuseMitigation2(bool mitigation);
+    PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
 
-    // Passphrase entry for hardware wallets
-    void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
-    void onWalletPassphraseNeeded(bool on_device) override;
+    QString tmpTxDescription; // TODO: remove the need for this var
+    bool refreshedOnce = false;
 
-    quint64 getBytesReceived() const;
-    quint64 getBytesSent() const;
+    void onHeightsRefreshed(bool success, quint64 daemonHeight, quint64 targetHeight);
 
-    bool isDeviceConnected() const;
-
-    bool setRingDatabase(const QString &path);
-
-    // TODO: setListener() when it implemented in API
 signals:
     // emitted on every event happened with wallet
     // (money sent/received, new block)
@@ -488,15 +405,12 @@ signals:
     void moneyReceived(const QString &txId, quint64 amount);
     void unconfirmedMoneyReceived(const QString &txId, quint64 amount);
     void newBlock(quint64 height, quint64 targetHeight);
-    void addressBookChanged() const;
-    void historyModelChanged() const;
     void walletCreationHeightChanged();
     void deviceButtonRequest(quint64 buttonCode);
     void deviceButtonPressed();
     void deviceError(const QString &message);
     void walletPassphraseNeeded(bool onDevice);
     void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
-    void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const;
     void deviceShowAddressShowed();
     void transactionProofVerified(TxProofResult result);
     void spendProofVerified(QPair<bool, bool> result);
@@ -506,72 +420,82 @@ signals:
 
     void connectionStatusChanged(int status) const;
     void currentSubaddressAccountChanged() const;
-    void disconnectedChanged() const;
-    void proxyAddressChanged() const;
-    void refreshingChanged() const;
 
-private:
-    //! initializes wallet
-    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 onRefreshed(bool success);
+    void refreshSync(int height, int target);
+    void blockchainSync(int height, int target);
+    void synchronized();
+    void balanceUpdated(quint64 balance, quint64 spendable);
+    void keysCorrupted();
+
+    void endTransaction();
+    void createTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address);
+    void donationSent();
+    void walletRefreshed();
+
+    void initiateTransaction();
+    void createTransactionError(QString message);
+
+    void selectedInputsChanged(const QStringList &selectedInputs);
 
+    void multiBroadcast(PendingTransaction *tx);
+    void heightsRefreshed(bool success, quint64 daemonHeight, quint64 targetHeight);
+
+private:
+    // ###### Status ######
     void setConnectionStatus(ConnectionStatus value);
-    QString getProxyAddress() const;
-    void setProxyAddress(QString address);
-    void startRefreshThread();
 
+    // ##### Synchronization (Refresh) #####
+    void startRefreshThread();
     void onNewBlock(uint64_t height);
+    void onUpdated();
+    void onRefreshed(bool success, const QString &message);
+
+    // ##### Transactions #####
+    void onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address);
 
 private:
     friend class WalletManager;
     friend class WalletListenerImpl;
-    //! libwallet's
-    Monero::Wallet * m_walletImpl;
-    // history lifetime managed by wallet;
-    TransactionHistory * m_history;
-    // Used for UI history view
-    mutable TransactionHistoryModel * m_historyModel;
-    mutable TransactionHistoryProxyModel * m_historySortFilterModel;
-    QString m_paymentId;
-    AddressBook * m_addressBook;
-    mutable AddressBookModel * m_addressBookModel;
-    mutable quint64 m_daemonBlockChainHeight;
-    mutable quint64 m_daemonBlockChainTargetHeight;
-
-    mutable ConnectionStatus m_connectionStatus;
-
-    bool m_disconnected;
-    mutable bool m_initialized;
+
+    Monero::Wallet *m_walletImpl;
+
+    TransactionHistory *m_history;
+    TransactionHistoryModel *m_historyModel;
+    TransactionHistoryProxyModel *m_historySortFilterModel;
+
+    AddressBook *m_addressBook;
+    AddressBookModel *m_addressBookModel;
+
+    quint64 m_daemonBlockChainHeight;
+    quint64 m_daemonBlockChainTargetHeight;
+
+    ConnectionStatus m_connectionStatus;
+
     uint32_t m_currentSubaddressAccount;
-    Subaddress * m_subaddress;
-    mutable SubaddressModel * m_subaddressModel;
-    SubaddressAccount * m_subaddressAccount;
-    mutable SubaddressAccountModel * m_subaddressAccountModel;
-    Coins * m_coins;
-    mutable CoinsModel * m_coinsModel;
+    Subaddress *m_subaddress;
+    SubaddressModel *m_subaddressModel;
+    SubaddressAccount *m_subaddressAccount;
+    SubaddressAccountModel *m_subaddressAccountModel;
+
+    Coins *m_coins;
+    CoinsModel *m_coinsModel;
+
     QMutex m_asyncMutex;
     QString m_daemonUsername;
     QString m_daemonPassword;
-    QString m_proxyAddress;
-    mutable QMutex m_proxyMutex;
+
+    QMutex m_proxyMutex;
     std::atomic<bool> m_refreshNow;
     std::atomic<bool> m_refreshEnabled;
-    std::atomic<bool> m_refreshing;
     WalletListenerImpl *m_walletListener;
     FutureScheduler m_scheduler;
-    int m_connectionTimeout = 30;
+
     bool m_useSSL;
+    bool donationSending = false;
+    bool m_newWallet = false;
+
+    QTimer *m_storeTimer = nullptr;
+    std::set<std::string> m_selectedInputs;
 };
 
 
index c1ec41fe739451f84fc230126f08df833d6b7f73..e5a47ed74e1815cafc1185eb816c83ce3443f4ca 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "WalletListenerImpl.h"
 #include "Wallet.h"
+#include "WalletManager.h"
 
 WalletListenerImpl::WalletListenerImpl(Wallet * w)
     : m_wallet(w)
@@ -11,28 +12,40 @@ WalletListenerImpl::WalletListenerImpl(Wallet * w)
 
 }
 
+// Beware!
+// Do not call non-signal m_wallet functions here
+// Nothing here runs in the GUI thread
+
 void WalletListenerImpl::moneySpent(const std::string &txId, uint64_t amount)
 {
-    qDebug() << __FUNCTION__;
-    emit m_wallet->moneySpent(QString::fromStdString(txId), amount);
+    // Outgoing tx included in a block
+    QString qTxId = QString::fromStdString(txId);
+    qDebug() << Q_FUNC_INFO << qTxId << " " << WalletManager::displayAmount(amount);
+
+    emit m_wallet->moneySpent(qTxId, amount);
 }
 
 void WalletListenerImpl::moneyReceived(const std::string &txId, uint64_t amount)
 {
-    qDebug() << __FUNCTION__;
-    emit m_wallet->moneyReceived(QString::fromStdString(txId), amount);
+    // Incoming tx included in a block.
+    QString qTxId = QString::fromStdString(txId);
+    qDebug() << Q_FUNC_INFO << qTxId << " " << WalletManager::displayAmount(amount);
+
+    emit m_wallet->moneyReceived(qTxId, amount);
 }
 
 void WalletListenerImpl::unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
 {
-    qDebug() << __FUNCTION__;
-    emit m_wallet->unconfirmedMoneyReceived(QString::fromStdString(txId), amount);
+    // Incoming tx in pool
+    QString qTxId = QString::fromStdString(txId);
+    qDebug() << Q_FUNC_INFO << qTxId << " " << WalletManager::displayAmount(amount);
+
+    emit m_wallet->unconfirmedMoneyReceived(qTxId, amount);
 }
 
 void WalletListenerImpl::newBlock(uint64_t height)
 {
-    // qDebug() << __FUNCTION__;
-    m_wallet->onNewBlock(height);
+    // Called whenever a new block gets scanned by the wallet
     emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
 }
 
@@ -45,7 +58,6 @@ void WalletListenerImpl::updated()
 void WalletListenerImpl::refreshed(bool success)
 {
     QString message = m_wallet->errorString();
-    m_wallet->onRefreshed(success);
     emit m_wallet->refreshed(success, message);
 }
 
index 1e52c8782412f669e4c74240d60279f1e35e6689..15894bef650141cbf31e07792aca96726d671ff9 100644 (file)
@@ -232,7 +232,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
     EventFilter filter;
     app.installEventFilter(&filter);
 
-    WindowManager windowManager(&filter);
+    WindowManager windowManager(QCoreApplication::instance(), &filter);
 
     QObject::connect(&app, &SingleApplication::instanceStarted, [&windowManager]() {
         windowManager.raise();
index 64177d061e65f25085c7d962a9c7c2f6b599ade6..fe640099449554c87244d30c6c4c93d6bc8c3774 100644 (file)
@@ -7,9 +7,10 @@
 #include <QDesktopServices>
 #include <QRegularExpression>
 
+#include "utils/config.h"
 #include "utils/Utils.h"
 #include "utils/os/tails.h"
-#include "appcontext.h"
+#include "utils/os/whonix.h"
 #include "config-feather.h"
 
 TorManager::TorManager(QObject *parent)
@@ -313,4 +314,8 @@ TorManager* TorManager::instance()
     }
 
     return m_instance;
-}
\ No newline at end of file
+}
+
+TorManager::~TorManager() {
+    qDebug() << "~TorManager";
+}
index 31c30bee203faa6f8955a71cb262c51e98fdcc8c..c0d4e3039aafe020423d60d2cda88efa28f61516 100644 (file)
@@ -18,6 +18,7 @@ Q_OBJECT
 
 public:
     explicit TorManager(QObject *parent = nullptr);
+    ~TorManager() override;
 
     void init();
     void start();
index 6ff97cd474bdd62fd8c2428ffb60046e57d99940..3f9d7af5eaa75acd9c6e60923abc78eb5a225800 100644 (file)
@@ -4,9 +4,10 @@
 #include <QObject>
 
 #include "nodes.h"
+#include "utils/AppData.h"
 #include "utils/Utils.h"
 #include "utils/os/tails.h"
-#include "appcontext.h"
+#include "utils/os/whonix.h"
 #include "constants.h"
 #include "utils/WebsocketNotifier.h"
 #include "utils/TorManager.h"
@@ -94,21 +95,21 @@ void NodeList::ensureStructure(QJsonObject &obj, NetworkType::Type networkType)
     obj[networkTypeStr] = netTypeObj;
 }
 
-Nodes::Nodes(QObject *parent)
+Nodes::Nodes(QObject *parent, Wallet *wallet)
     : QObject(parent)
     , modelWebsocket(new NodeModel(NodeSource::websocket, this))
     , modelCustom(new NodeModel(NodeSource::custom, this))
     , m_connection(FeatherNode())
+    , m_wallet(wallet)
 {
     // TODO: This class is in desperate need of refactoring
 
     this->loadConfig();
     connect(websocketNotifier(), &WebsocketNotifier::NodesReceived, this, &Nodes::onWSNodesReceived);
-}
 
-void Nodes::setContext(AppContext *ctx) {
-    m_ctx = ctx;
-    connect(m_ctx, &AppContext::walletRefreshed, this, &Nodes::onWalletRefreshed);
+    if (m_wallet) {
+        connect(m_wallet, &Wallet::walletRefreshed, this, &Nodes::onWalletRefreshed);
+    }
 }
 
 void Nodes::loadConfig() {
@@ -195,7 +196,11 @@ void Nodes::connectToNode() {
 }
 
 void Nodes::connectToNode(const FeatherNode &node) {
-    if (!m_ctx) {
+    if (!m_wallet) {
+        return;
+    }
+
+    if (!m_allowConnection) {
         return;
     }
 
@@ -217,11 +222,11 @@ void Nodes::connectToNode(const FeatherNode &node) {
     qInfo() << QString("Attempting to connect to %1 (%2)").arg(node.toAddress(), node.custom ? "custom" : "ws");
 
     if (!node.url.userName().isEmpty() && !node.url.password().isEmpty()) {
-        m_ctx->wallet->setDaemonLogin(node.url.userName(), node.url.password());
+        m_wallet->setDaemonLogin(node.url.userName(), node.url.password());
     }
 
     // Don't use SSL over Tor/i2p
-    m_ctx->wallet->setUseSSL(!node.isAnonymityNetwork());
+    m_wallet->setUseSSL(!node.isAnonymityNetwork());
 
     QString proxyAddress;
     if (useSocks5Proxy(node)) {
@@ -233,7 +238,7 @@ void Nodes::connectToNode(const FeatherNode &node) {
         }
     }
 
-    m_ctx->wallet->initAsync(node.toAddress(), true, 0, false, false, 0, proxyAddress);
+    m_wallet->initAsync(node.toAddress(), true, 0, proxyAddress);
 
     m_connection = node;
     m_connection.isActive = false;
@@ -244,16 +249,16 @@ void Nodes::connectToNode(const FeatherNode &node) {
 }
 
 void Nodes::autoConnect(bool forceReconnect) {
-    if (!m_ctx) {
+    if (!m_wallet) {
         return;
     }
 
     // this function is responsible for automatically connecting to a daemon.
-    if (m_ctx->wallet == nullptr || !m_enableAutoconnect) {
+    if (m_wallet == nullptr || !m_enableAutoconnect) {
         return;
     }
 
-    Wallet::ConnectionStatus status = m_ctx->wallet->connectionStatus();
+    Wallet::ConnectionStatus status = m_wallet->connectionStatus();
     bool wsMode = (this->source() == NodeSource::websocket);
 
     if (wsMode && !m_wsNodesReceived && websocketNodes().count() == 0) {
@@ -423,7 +428,7 @@ bool Nodes::useOnionNodes() {
     }
 
     if (privacyLevel == Config::allTorExceptInitSync) {
-        if (m_ctx && m_ctx->refreshed) {
+        if (m_wallet && m_wallet->refreshedOnce) {
             return true;
         }
 
@@ -431,7 +436,7 @@ bool Nodes::useOnionNodes() {
             int initSyncThreshold = config()->get(Config::initSyncThreshold).toInt();
             int networkHeight = appData()->heights[constants::networkType];
 
-            if (m_ctx && m_ctx->wallet->blockChainHeight() > (networkHeight - initSyncThreshold)) {
+            if (m_wallet && m_wallet->blockChainHeight() > (networkHeight - initSyncThreshold)) {
                 return true;
             }
         }
@@ -584,4 +589,12 @@ int Nodes::modeHeight(const QList<FeatherNode> &nodes) {
     }
 
     return mode_height;
-}
\ No newline at end of file
+}
+
+void Nodes::allowConnection() {
+    m_allowConnection = true;
+}
+
+Nodes::~Nodes() {
+    qDebug() << "~Nodes";
+}
index ed261232387abbf0fecaf53950fc940284eee35c..5228dfd1c6e11fbeef21c789df4acf62c84284ba 100644 (file)
@@ -118,9 +118,11 @@ class Nodes : public QObject {
     Q_OBJECT
 
 public:
-    explicit Nodes(QObject *parent = nullptr);
-    void setContext(AppContext *ctx);
+    explicit Nodes(QObject *parent, Wallet *wallet);
+    ~Nodes() override;
+
     void loadConfig();
+    void allowConnection();
 
     NodeSource source();
     FeatherNode connection();
@@ -144,7 +146,7 @@ private slots:
     void onWalletRefreshed();
 
 private:
-    AppContext *m_ctx = nullptr;
+    Wallet *m_wallet = nullptr;
     QJsonObject m_configJson;
 
     NodeList m_nodes;
@@ -159,6 +161,8 @@ private:
     bool m_wsNodesReceived = false;
     bool m_enableAutoconnect = true;
 
+    bool m_allowConnection = false;
+
     FeatherNode pickEligibleNode();
 
     bool useOnionNodes();
index b2e354ccb9d00a91f3f2068e1d169c2cf1b38cde..418fd57b258868333e24fddee211244f5d9cbecb 100644 (file)
@@ -4,10 +4,10 @@
 #include <QScreen>
 #include <QDesktopServices>
 
+#include "utils/config.h"
 #include "utils/Utils.h"
 #include "utils/xmrig.h"
 #include "utils/TorManager.h"
-#include "appcontext.h"
 
 XmRig::XmRig(const QString &configDir, QObject *parent)
     : QObject(parent)
index da27e54239ba3df73ae385a39ff0e67cbb234da9..96f384204e2cc2b023beccf05866a08651626152 100644 (file)
@@ -9,6 +9,7 @@
 #include <QTableWidget>
 
 #include "CCSProgressDelegate.h"
+#include "utils/Utils.h"
 
 CCSWidget::CCSWidget(QWidget *parent)
         : QWidget(parent)
@@ -37,8 +38,9 @@ void CCSWidget::linkClicked() {
     QModelIndex index = ui->tableView->currentIndex();
     auto entry = m_model->entry(index.row());
 
-    if (entry)
+    if (entry) {
         Utils::externalLinkWarning(this, entry->url);
+    }
 }
 
 void CCSWidget::donateClicked() {
index 3590d4f56d28cd61b0aed093f798c048ffd4421d..0b47e4db56f35656765a326081aaedc68963e07a 100644 (file)
@@ -10,7 +10,6 @@
 #include <QProgressBar>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "model/CCSModel.h"
 #include "widgets/CCSEntry.h"
 
index 6865b13b2c6482a040eabdc1503f3fd82a96b17a..e00a9009464ea4ebd215a349bd067de5ec2e7c50 100644 (file)
 #include "utils/NetworkManager.h"
 #include "utils/WebsocketNotifier.h"
 
-LocalMoneroWidget::LocalMoneroWidget(QWidget *parent, QSharedPointer<AppContext> ctx)
+LocalMoneroWidget::LocalMoneroWidget(QWidget *parent, Wallet *wallet)
         : QWidget(parent)
         , ui(new Ui::LocalMoneroWidget)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
 {
     ui->setupUi(this);
 
index c62409e1d396bcc983eddf0b390f2ee37ee66d9d..ffb470a3f3570f1a2ab93c561cc2ed607051f325 100644 (file)
@@ -7,8 +7,8 @@
 #include <QWidget>
 
 #include "api/LocalMoneroApi.h"
-#include "appcontext.h"
 #include "model/LocalMoneroModel.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class LocalMoneroWidget;
@@ -19,7 +19,7 @@ class LocalMoneroWidget : public QWidget
 Q_OBJECT
 
 public:
-    explicit LocalMoneroWidget(QWidget *parent, QSharedPointer<AppContext> ctx);
+    explicit LocalMoneroWidget(QWidget *parent, Wallet *wallet);
     ~LocalMoneroWidget() override;
 
 public slots:
@@ -42,7 +42,7 @@ private:
     void updatePaymentMethods();
 
     QScopedPointer<Ui::LocalMoneroWidget> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 
     int m_currentPage = 0;
 
index 1ef0299b90a7780ea8c7f2d3affcec0db17c3747..d102ba8e82f52e69bc37fde3a979d72037948dbe 100644 (file)
@@ -8,7 +8,6 @@
 #include <QTreeView>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "model/NodeModel.h"
 #include "utils/nodes.h"
 
index 0a17e7be5a155fddabebe7c12024f79b8d2e2f9b..b4a8ef238a9f83a538ec1998d369496b5348a628 100644 (file)
@@ -6,11 +6,12 @@
 
 #include "constants.h"
 #include "utils/AppData.h"
+#include "utils/config.h"
 
-TickerWidgetBase::TickerWidgetBase(QWidget *parent, QSharedPointer<AppContext> ctx)
+TickerWidgetBase::TickerWidgetBase(QWidget *parent, Wallet *wallet)
         : QWidget(parent)
         , ui(new Ui::TickerWidget)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
 {
     ui->setupUi(this);
 
@@ -53,8 +54,8 @@ void TickerWidgetBase::setDisplayText(const QString &text) {
 }
 
 // BalanceTickerWidget
-BalanceTickerWidget::BalanceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, bool totalBalance)
-        : TickerWidgetBase(parent, std::move(ctx))
+BalanceTickerWidget::BalanceTickerWidget(QWidget *parent, Wallet *wallet, bool totalBalance)
+        : TickerWidgetBase(parent, wallet)
         , m_totalBalance(totalBalance)
 {
     if (totalBalance)
@@ -64,13 +65,13 @@ BalanceTickerWidget::BalanceTickerWidget(QWidget *parent, QSharedPointer<AppCont
 
     this->setPercentageVisible(false);
 
-    connect(m_ctx.get(), &AppContext::balanceUpdated, this, &BalanceTickerWidget::updateDisplay);
+    connect(m_wallet, &Wallet::balanceUpdated, this, &BalanceTickerWidget::updateDisplay);
     connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &BalanceTickerWidget::updateDisplay);
     connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &BalanceTickerWidget::updateDisplay);
 }
 
 void BalanceTickerWidget::updateDisplay() {
-    double balance = (m_totalBalance ? m_ctx->wallet->balanceAll() : m_ctx->wallet->balance()) / constants::cdiv;
+    double balance = (m_totalBalance ? m_wallet->balanceAll() : m_wallet->balance()) / constants::cdiv;
     QString fiatCurrency = config()->get(Config::preferredFiatCurrency).toString();
     double balanceFiatAmount = appData()->prices.convert("XMR", fiatCurrency, balance);
     if (balanceFiatAmount < 0)
@@ -79,8 +80,8 @@ void BalanceTickerWidget::updateDisplay() {
 }
 
 // PriceTickerWidget
-PriceTickerWidget::PriceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol)
-        : TickerWidgetBase(parent, std::move(ctx))
+PriceTickerWidget::PriceTickerWidget(QWidget *parent, Wallet *wallet, QString symbol)
+        : TickerWidgetBase(parent, wallet)
         , m_symbol(std::move(symbol))
 {
     this->setTitle(m_symbol);
@@ -107,8 +108,8 @@ void PriceTickerWidget::updateDisplay() {
 }
 
 //RatioTickerWidget
-RatioTickerWidget::RatioTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol1, QString symbol2)
-        : TickerWidgetBase(parent, std::move(ctx))
+RatioTickerWidget::RatioTickerWidget(QWidget *parent, Wallet *wallet, QString symbol1, QString symbol2)
+        : TickerWidgetBase(parent, wallet)
         , m_symbol1(std::move(symbol1))
         , m_symbol2(std::move(symbol2))
 {
index 768458621b4c91ea8de6f33d5f72eff9fe983b0e..96c80854722d60e7705f77e8b8096ab8e91251f4 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <QWidget>
 
-#include "appcontext.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class TickerWidget;
@@ -17,7 +17,7 @@ class TickerWidgetBase : public QWidget
     Q_OBJECT
 
 public:
-    explicit TickerWidgetBase(QWidget *parent, QSharedPointer<AppContext> ctx);
+    explicit TickerWidgetBase(QWidget *parent, Wallet *wallet);
     ~TickerWidgetBase() override;
 
     void setTitle(const QString &title);
@@ -34,7 +34,7 @@ private:
     QScopedPointer<Ui::TickerWidget> ui;
 
 protected:
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
 };
 
 class BalanceTickerWidget : public TickerWidgetBase
@@ -42,7 +42,7 @@ class BalanceTickerWidget : public TickerWidgetBase
     Q_OBJECT
 
 public:
-    explicit BalanceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, bool totalBalance);
+    explicit BalanceTickerWidget(QWidget *parent, Wallet *wallet, bool totalBalance);
 
 public slots:
     void updateDisplay() override;
@@ -56,7 +56,7 @@ class PriceTickerWidget : public TickerWidgetBase
     Q_OBJECT
 
 public:
-    explicit PriceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol);
+    explicit PriceTickerWidget(QWidget *parent, Wallet *wallet, QString symbol);
 
 public slots:
     void updateDisplay() override;
@@ -70,7 +70,7 @@ class RatioTickerWidget : public TickerWidgetBase
     Q_OBJECT
 
 public:
-    explicit RatioTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol1, QString symbol2);
+    explicit RatioTickerWidget(QWidget *parent, Wallet *wallet, QString symbol1, QString symbol2);
 
 public slots:
     void updateDisplay() override;
index 444b6851a2914f656bd262806e19586166740351..f3c676f4041bdb40db8061b68b33d955c2b0001f 100644 (file)
 #include <QTableWidget>
 
 #include "utils/Icons.h"
+#include "utils/Utils.h"
 
-XMRigWidget::XMRigWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
+XMRigWidget::XMRigWidget(Wallet *wallet, QWidget *parent)
         : QWidget(parent)
         , ui(new Ui::XMRigWidget)
-        , m_ctx(std::move(ctx))
+        , m_wallet(wallet)
         , m_XMRig(new XmRig(Config::defaultConfigDir().path()))
         , m_model(new QStandardItemModel(this))
         , m_contextMenu(new QMenu(this))
@@ -96,25 +97,25 @@ XMRigWidget::XMRigWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
     ui->relayTor->setChecked(config()->get(Config::xmrigNetworkTor).toBool());
 
     // Receiving address
-    auto username = m_ctx->wallet->getCacheAttribute("feather.xmrig_username");
+    auto username = m_wallet->getCacheAttribute("feather.xmrig_username");
     if (!username.isEmpty()) {
         ui->lineEdit_address->setText(username);
     }
     connect(ui->lineEdit_address, &QLineEdit::textChanged, [=]() {
-        m_ctx->wallet->setCacheAttribute("feather.xmrig_username", ui->lineEdit_address->text());
+        m_wallet->setCacheAttribute("feather.xmrig_username", ui->lineEdit_address->text());
     });
     connect(ui->btn_fillPrimaryAddress, &QPushButton::clicked, this, &XMRigWidget::onUsePrimaryAddressClicked);
 
     // Password
-    auto password = m_ctx->wallet->getCacheAttribute("feather.xmrig_password");
+    auto password = m_wallet->getCacheAttribute("feather.xmrig_password");
     if (!password.isEmpty()) {
         ui->lineEdit_password->setText(password);
     } else {
         ui->lineEdit_password->setText("featherwallet");
-        m_ctx->wallet->setCacheAttribute("feather.xmrig_password", ui->lineEdit_password->text());
+        m_wallet->setCacheAttribute("feather.xmrig_password", ui->lineEdit_password->text());
     }
     connect(ui->lineEdit_password, &QLineEdit::textChanged, [=]() {
-        m_ctx->wallet->setCacheAttribute("feather.xmrig_password", ui->lineEdit_password->text());
+        m_wallet->setCacheAttribute("feather.xmrig_password", ui->lineEdit_password->text());
     });
 
     // [Status] tab
@@ -171,7 +172,7 @@ void XMRigWidget::onClearClicked() {
 }
 
 void XMRigWidget::onUsePrimaryAddressClicked() {
-    ui->lineEdit_address->setText(m_ctx->wallet->address(0, 0));
+    ui->lineEdit_address->setText(m_wallet->address(0, 0));
 }
 
 void XMRigWidget::onStartClicked() {
@@ -193,8 +194,8 @@ void XMRigWidget::onStartClicked() {
     }
 
     // username is receiving address usually
-    auto username = m_ctx->wallet->getCacheAttribute("feather.xmrig_username");
-    auto password = m_ctx->wallet->getCacheAttribute("feather.xmrig_password");
+    auto username = m_wallet->getCacheAttribute("feather.xmrig_username");
+    auto password = m_wallet->getCacheAttribute("feather.xmrig_password");
 
     if (username.isEmpty()) {
         ui->console->appendPlainText("Please specify a receiving address on the Settings screen.");
@@ -203,7 +204,7 @@ void XMRigWidget::onStartClicked() {
 
     if (address.contains("cryptonote.social") && !username.contains(".")) {
         // cryptonote social requires <addr>.<username>, we'll just grab a few chars from primary addy
-        username = QString("%1.%2").arg(username, m_ctx->wallet->address(0, 0).mid(0, 6));
+        username = QString("%1.%2").arg(username, m_wallet->address(0, 0).mid(0, 6));
     }
 
     int threads = ui->threadSlider->value();
index b7eb8e80bca32a2a63290293131de9a7dc5ca5e2..a7e3f6730169838e36bb08b1898cd79c4a197059 100644 (file)
@@ -7,10 +7,11 @@
 #include <QMenu>
 #include <QWidget>
 #include <QItemSelection>
+#include <QStandardItemModel>
 
-#include "appcontext.h"
 #include "utils/xmrig.h"
 #include "utils/config.h"
+#include "libwalletqt/Wallet.h"
 
 namespace Ui {
     class XMRigWidget;
@@ -21,7 +22,7 @@ class XMRigWidget : public QWidget
     Q_OBJECT
 
 public:
-    explicit XMRigWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr);
+    explicit XMRigWidget(Wallet *wallet, QWidget *parent = nullptr);
     ~XMRigWidget() override;
     QStandardItemModel *model();
 
@@ -63,7 +64,7 @@ private:
     bool checkXMRigPath();
 
     QScopedPointer<Ui::XMRigWidget> ui;
-    QSharedPointer<AppContext> m_ctx;
+    Wallet *m_wallet;
     XmRig *m_XMRig;
     QStandardItemModel *m_model;
     QMenu *m_contextMenu;
index 0e0ba65fb731b46a12572cb27b9894728c9798e8..ab47ded17a40adaa32677856f19379a492374c00 100644 (file)
@@ -9,7 +9,6 @@
 #include <QWidget>
 #include <QDir>
 
-#include "appcontext.h"
 #include "WalletWizard.h"
 
 namespace Ui {
index 6710dd4cabbc25e3f06a25828b25706cbab2a958..99482d71e9c5eb3510a67eb31a21bd043524215e 100644 (file)
@@ -8,8 +8,6 @@
 #include <QWizardPage>
 #include <QWidget>
 
-#include "appcontext.h"
-
 namespace Ui {
     class PageMenu;
 }
index f07306c0892a3ea924bb751953e1133098fcef1e..a9df6fc3c160ac2e959ddc63f1e1ace6072fb65e 100644 (file)
@@ -8,7 +8,6 @@
 #include <QWizardPage>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "utils/nodes.h"
 
 namespace Ui {
index ba6ba6232310f531f57434eeafd9129cb831be56..e666acc825360ac98b17a6d1ee25dffb141cde26 100644 (file)
@@ -6,8 +6,6 @@
 
 #include <QWizardPage>
 
-#include "appcontext.h"
-
 namespace Ui {
     class PageNetworkProxy;
 }
index 443e161e4795d54693f141fbf60b601fcb14d9d7..dd0b0acaddb0769926b14dcf956e551131b508d8 100644 (file)
@@ -6,8 +6,6 @@
 
 #include <QWizardPage>
 
-#include "appcontext.h"
-
 namespace Ui {
     class PageNetworkWebsocket;
 }
index a39ec554bed3cc36b54d7cfaa050a0489198721a..3f4cd550a4ea58c5c25e5a734c1011fd71c343b6 100644 (file)
@@ -5,10 +5,10 @@
 #define FEATHER_OPENWALLET_H
 
 #include <QLabel>
+#include <QStandardItemModel>
 #include <QWizardPage>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "model/WalletKeysFilesModel.h"
 
 namespace Ui {
index 12f2d061a7118389d523b3c5f6de29cd6bd9bd09..32d1be100b4231b54108c1a3766c370b1ab7e1c5 100644 (file)
@@ -7,7 +7,6 @@
 #include <QWizardPage>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "WalletWizard.h"
 
 namespace Ui {
index e7f0ff16b71250854e27a93087cd393e86e8039c..d3f77f3b04b6a617b0ffe29e7803a03ff95e038a 100644 (file)
@@ -7,7 +7,6 @@
 #include <QWizardPage>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "WalletWizard.h"
 
 namespace Ui {
index bed1b9207cf0af2ecc3d2a0ead9e8facb42e7728..fd263fbd8f9e5ea62ce89f12a59dcc3845d1d243 100644 (file)
@@ -7,7 +7,6 @@
 #include <QWizardPage>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "WalletWizard.h"
 
 namespace Ui {
index ae26f0821d7e7e1f25b1727ccaee0acb3f05102f..fe8d86aca9311f0b614a3e095b23b4aa1ac2ddb5 100644 (file)
@@ -7,7 +7,6 @@
 #include <QWizardPage>
 #include <QWidget>
 
-#include "appcontext.h"
 #include "WalletWizard.h"
 
 namespace Ui {
index 82e32bda606be391022b66a1917be2735fcd1962..73ac30fcc54493ad04ba9a1c2c0b92fc9f5cd818 100644 (file)
@@ -9,8 +9,6 @@
 #include <QWidget>
 #include <QDir>
 
-#include "appcontext.h"
-
 namespace Ui {
     class PageWalletFile;
 }
index 37eb4404af1cf05eac3bbcdb2cf7b560ff9ce99d..4ae57398fa791e80aaf4bb457b65dfa7b8642c87 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "WalletWizard.h"
 #include "constants.h"
+#include "libwalletqt/WalletManager.h"
 
 PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *parent)
     : QWizardPage(parent)
index 780052b6c1556d994e12c5853856a9b3cdebd39e..832ff7a2ea99260f34751b92f3dd3c8c83f9e85a 100644 (file)
@@ -10,7 +10,6 @@
 #include <QTextEdit>
 #include <QCompleter>
 
-#include "appcontext.h"
 #include "WalletWizard.h"
 
 namespace Ui {
index 2aa4c00f2bf55137d93bae51d606cc8e8b75588b..394ac72caebdb8607943f8c443ea127e5676e522 100644 (file)
@@ -11,7 +11,6 @@
 #include <QCompleter>
 
 #include "utils/textedit.h"
-#include "appcontext.h"
 
 namespace Ui {
     class PageWalletRestoreSeed;
index b423a6e359844dd082150477429b623a5188ce32..975cac87971ec93bd8af50be57f06a456c89391d 100644 (file)
@@ -8,10 +8,10 @@
 #include <QLabel>
 #include <QRadioButton>
 
-#include "appcontext.h"
 #include "model/WalletKeysFilesModel.h"
 #include "utils/RestoreHeightLookup.h"
 #include "utils/config.h"
+#include "utils/Seed.h"
 #include "constants.h"
 
 enum WizardMode {