refactor: remove appcontext, cleanup Wallet

This commit is contained in:
tobtoht 2023-03-01 03:05:56 +01:00
parent b057f750a5
commit 402bea3fd6
No known key found for this signature in database
GPG key ID: E45B10DD027D2472
82 changed files with 1626 additions and 2340 deletions

2
monero

@ -1 +1 @@
Subproject commit f7705c2c6740699a3fa47895473f79c006624559 Subproject commit 772d207026dac31f927efa733fda3f73b103e71a

View file

@ -9,11 +9,12 @@
#include "dialog/OutputInfoDialog.h" #include "dialog/OutputInfoDialog.h"
#include "dialog/OutputSweepDialog.h" #include "dialog/OutputSweepDialog.h"
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/Utils.h"
CoinsWidget::CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent) CoinsWidget::CoinsWidget(Wallet *wallet, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::CoinsWidget) , ui(new Ui::CoinsWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_headerMenu(new QMenu(this)) , m_headerMenu(new QMenu(this))
, m_copyMenu(new QMenu("Copy",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(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) { 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::SpentHeight, true);
ui->coins->setColumnHidden(CoinsModel::Frozen, true); ui->coins->setColumnHidden(CoinsModel::Frozen, true);
if (!m_ctx->wallet->viewOnly()) { if (!m_wallet->viewOnly()) {
ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, true); ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, true);
} else { } else {
ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, false); ui->coins->setColumnHidden(CoinsModel::KeyImageKnown, false);
@ -188,7 +189,7 @@ void CoinsWidget::spendSelected() {
keyimages << m_model->entryFromIndex(m_proxyModel->mapToSource(index))->keyImage(); keyimages << m_model->entryFromIndex(m_proxyModel->mapToSource(index))->keyImage();
} }
m_ctx->setSelectedInputs(keyimages); m_wallet->setSelectedInputs(keyimages);
this->selectCoins(keyimages); this->selectCoins(keyimages);
} }
@ -239,7 +240,7 @@ void CoinsWidget::onSweepOutputs() {
int ret = dialog.exec(); int ret = dialog.exec();
if (!ret) return; 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) { void CoinsWidget::copy(copyField field) {
@ -298,18 +299,18 @@ QVector<CoinsInfo*> CoinsWidget::currentEntries() {
void CoinsWidget::freezeCoins(QStringList &pubkeys) { void CoinsWidget::freezeCoins(QStringList &pubkeys) {
for (auto &pubkey : 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_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
m_ctx->updateBalance(); m_wallet->updateBalance();
} }
void CoinsWidget::thawCoins(QStringList &pubkeys) { void CoinsWidget::thawCoins(QStringList &pubkeys) {
for (auto &pubkey : 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_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
m_ctx->updateBalance(); m_wallet->updateBalance();
} }
void CoinsWidget::selectCoins(const QStringList &keyimages) { void CoinsWidget::selectCoins(const QStringList &keyimages) {

View file

@ -8,10 +8,10 @@
#include <QWidget> #include <QWidget>
#include <QSvgWidget> #include <QSvgWidget>
#include "appcontext.h"
#include "model/CoinsModel.h" #include "model/CoinsModel.h"
#include "model/CoinsProxyModel.h" #include "model/CoinsProxyModel.h"
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class CoinsWidget; class CoinsWidget;
@ -22,7 +22,7 @@ class CoinsWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit CoinsWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit CoinsWidget(Wallet *wallet, QWidget *parent = nullptr);
void setModel(CoinsModel * model, Coins * coins); void setModel(CoinsModel * model, Coins * coins);
~CoinsWidget() override; ~CoinsWidget() override;
@ -62,7 +62,7 @@ private:
}; };
QScopedPointer<Ui::CoinsWidget> ui; QScopedPointer<Ui::CoinsWidget> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
QMenu *m_contextMenu; QMenu *m_contextMenu;
QMenu *m_headerMenu; QMenu *m_headerMenu;

View file

@ -8,13 +8,14 @@
#include "dialog/ContactsDialog.h" #include "dialog/ContactsDialog.h"
#include "libwalletqt/AddressBook.h" #include "libwalletqt/AddressBook.h"
#include "libwalletqt/WalletManager.h"
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "utils/Icons.h" #include "utils/Icons.h"
ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent) ContactsWidget::ContactsWidget(Wallet *wallet, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::ContactsWidget) , ui(new Ui::ContactsWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -23,7 +24,7 @@ ContactsWidget::ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
ui->searchLayout->addWidget(m_btn_addContact, 0, Qt::AlignRight); ui->searchLayout->addWidget(m_btn_addContact, 0, Qt::AlignRight);
connect(m_btn_addContact, &QPushButton::clicked, [this]{this->newContact();}); 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 = new AddressBookProxyModel;
m_proxyModel->setSourceModel(m_model); m_proxyModel->setSourceModel(m_model);
ui->contacts->setModel(m_proxyModel); ui->contacts->setModel(m_proxyModel);
@ -124,17 +125,17 @@ void ContactsWidget::newContact(QString address, QString name)
address = dialog.getAddress(); address = dialog.getAddress();
name = dialog.getName(); name = dialog.getName();
bool addressValid = WalletManager::addressValid(address, m_ctx->wallet->nettype()); bool addressValid = WalletManager::addressValid(address, m_wallet->nettype());
if (!addressValid) { if (!addressValid) {
QMessageBox::warning(this, "Invalid address", "Invalid address"); QMessageBox::warning(this, "Invalid address", "Invalid address");
return; return;
} }
int num_addresses = m_ctx->wallet->addressBook()->count(); int num_addresses = m_wallet->addressBook()->count();
QString address_entry; QString address_entry;
QString name_entry; QString name_entry;
for (int i=0; i<num_addresses; i++) { 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(); address_entry = entry.address();
name_entry = entry.description(); 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() void ContactsWidget::deleteContact()

View file

@ -8,9 +8,9 @@
#include <QWidget> #include <QWidget>
#include <QMenu> #include <QMenu>
#include "appcontext.h"
#include "model/AddressBookModel.h" #include "model/AddressBookModel.h"
#include "model/AddressBookProxyModel.h" #include "model/AddressBookProxyModel.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class ContactsWidget; class ContactsWidget;
@ -21,7 +21,7 @@ class ContactsWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit ContactsWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit ContactsWidget(Wallet *wallet, QWidget *parent = nullptr);
~ContactsWidget() override; ~ContactsWidget() override;
void setSearchbarVisible(bool visible); void setSearchbarVisible(bool visible);
@ -44,7 +44,7 @@ private slots:
private: private:
QScopedPointer<Ui::ContactsWidget> ui; QScopedPointer<Ui::ContactsWidget> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
QAction *m_showFullAddressesAction; QAction *m_showFullAddressesAction;
QMenu *m_rowMenu; QMenu *m_rowMenu;

View file

@ -6,20 +6,20 @@
#include <QMessageBox> #include <QMessageBox>
#include "appcontext.h"
#include "dialog/TxInfoDialog.h" #include "dialog/TxInfoDialog.h"
#include "dialog/TxProofDialog.h" #include "dialog/TxProofDialog.h"
#include "libwalletqt/WalletManager.h"
#include "utils/config.h" #include "utils/config.h"
#include "utils/Icons.h" #include "utils/Icons.h"
#include "WebsocketNotifier.h" #include "WebsocketNotifier.h"
HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent) HistoryWidget::HistoryWidget(Wallet *wallet, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::HistoryWidget) , ui(new Ui::HistoryWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_contextMenu(new QMenu(this)) , m_contextMenu(new QMenu(this))
, m_copyMenu(new QMenu("Copy", this)) , m_copyMenu(new QMenu("Copy", this))
, m_model(m_ctx->wallet->historyModel()) , m_model(wallet->historyModel())
{ {
ui->setupUi(this); ui->setupUi(this);
m_contextMenu->addMenu(m_copyMenu); m_contextMenu->addMenu(m_copyMenu);
@ -49,7 +49,7 @@ HistoryWidget::HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
ui->syncNotice->hide(); 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->syncNotice->setVisible(config()->get(Config::showHistorySyncNotice).toBool());
ui->history->setHistoryModel(m_model); ui->history->setHistoryModel(m_model);
@ -119,7 +119,7 @@ void HistoryWidget::showTxDetails() {
auto *tx = ui->history->currentEntry(); auto *tx = ui->history->currentEntry();
if (!tx) return; 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){ connect(dialog, &TxInfoDialog::resendTranscation, [this](const QString &txid){
emit resendTransaction(txid); emit resendTransaction(txid);
}); });
@ -148,7 +148,7 @@ void HistoryWidget::createTxProof() {
auto *tx = ui->history->currentEntry(); auto *tx = ui->history->currentEntry();
if (!tx) return; if (!tx) return;
TxProofDialog dialog{this, m_ctx, tx}; TxProofDialog dialog{this, m_wallet, tx};
dialog.getTxKey(); dialog.getTxKey();
dialog.exec(); dialog.exec();
} }

View file

@ -7,7 +7,6 @@
#include <QWidget> #include <QWidget>
#include <QMenu> #include <QMenu>
#include "appcontext.h"
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
#include "model/TransactionHistoryModel.h" #include "model/TransactionHistoryModel.h"
@ -22,7 +21,7 @@ class HistoryWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit HistoryWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit HistoryWidget(Wallet *wallet, QWidget *parent = nullptr);
~HistoryWidget() override; ~HistoryWidget() override;
void setSearchbarVisible(bool visible); void setSearchbarVisible(bool visible);
@ -58,7 +57,7 @@ private:
void showSyncNoticeMsg(); void showSyncNoticeMsg();
QScopedPointer<Ui::HistoryWidget> ui; QScopedPointer<Ui::HistoryWidget> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
QMenu *m_contextMenu; QMenu *m_contextMenu;
QMenu *m_copyMenu; QMenu *m_copyMenu;
TransactionHistoryProxyModel *m_model; TransactionHistoryProxyModel *m_model;

View file

@ -43,7 +43,9 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
: QMainWindow(parent) : QMainWindow(parent)
, ui(new Ui::MainWindow) , ui(new Ui::MainWindow)
, m_windowManager(windowManager) , 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); ui->setupUi(this);
@ -55,7 +57,7 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
m_windowCalc = new CalcWindow(this); m_windowCalc = new CalcWindow(this);
m_splashDialog = new SplashDialog(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)); 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); connect(m_windowManager, &WindowManager::websocketStatusChanged, this, &MainWindow::onWebsocketStatusChanged);
this->onWebsocketStatusChanged(!config()->get(Config::disableWebsocket).toBool()); this->onWebsocketStatusChanged(!config()->get(Config::disableWebsocket).toBool());
connect(m_windowManager, &WindowManager::proxySettingsChanged, [this]{ connect(m_windowManager, &WindowManager::proxySettingsChanged, this, &MainWindow::onProxySettingsChanged);
m_ctx->onProxySettingsChanged(); connect(m_windowManager, &WindowManager::updateBalance, m_wallet, &Wallet::updateBalance);
this->onProxySettingsChanged(); connect(m_windowManager, &WindowManager::offlineMode, this, &MainWindow::onOfflineMode);
});
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(torManager(), &TorManager::connectionStateChanged, this, &MainWindow::onTorConnectionStateChanged); connect(torManager(), &TorManager::connectionStateChanged, this, &MainWindow::onTorConnectionStateChanged);
this->onTorConnectionStateChanged(torManager()->torConnected); this->onTorConnectionStateChanged(torManager()->torConnected);
@ -191,20 +184,20 @@ void MainWindow::initWidgets() {
ui->tabHomeWidget->setCurrentIndex(TabsHome(homeWidget)); ui->tabHomeWidget->setCurrentIndex(TabsHome(homeWidget));
// [History] // [History]
m_historyWidget = new HistoryWidget(m_ctx, this); m_historyWidget = new HistoryWidget(m_wallet, this);
ui->historyWidgetLayout->addWidget(m_historyWidget); ui->historyWidgetLayout->addWidget(m_historyWidget);
connect(m_historyWidget, &HistoryWidget::viewOnBlockExplorer, this, &MainWindow::onViewOnBlockExplorer); connect(m_historyWidget, &HistoryWidget::viewOnBlockExplorer, this, &MainWindow::onViewOnBlockExplorer);
connect(m_historyWidget, &HistoryWidget::resendTransaction, this, &MainWindow::onResendTransaction); connect(m_historyWidget, &HistoryWidget::resendTransaction, this, &MainWindow::onResendTransaction);
// [Send] // [Send]
m_sendWidget = new SendWidget(m_ctx, this); m_sendWidget = new SendWidget(m_wallet, this);
ui->sendWidgetLayout->addWidget(m_sendWidget); ui->sendWidgetLayout->addWidget(m_sendWidget);
// -------------- // --------------
m_contactsWidget = new ContactsWidget(m_ctx, this); m_contactsWidget = new ContactsWidget(m_wallet, this);
ui->contactsWidgetLayout->addWidget(m_contactsWidget); ui->contactsWidgetLayout->addWidget(m_contactsWidget);
// [Receive] // [Receive]
m_receiveWidget = new ReceiveWidget(m_ctx, this); m_receiveWidget = new ReceiveWidget(m_wallet, this);
ui->receiveWidgetLayout->addWidget(m_receiveWidget); ui->receiveWidgetLayout->addWidget(m_receiveWidget);
connect(m_receiveWidget, &ReceiveWidget::showTransactions, [this](const QString &text) { connect(m_receiveWidget, &ReceiveWidget::showTransactions, [this](const QString &text) {
m_historyWidget->setSearchText(text); m_historyWidget->setSearchText(text);
@ -213,18 +206,18 @@ void MainWindow::initWidgets() {
connect(m_contactsWidget, &ContactsWidget::fillAddress, m_sendWidget, &SendWidget::fillAddress); connect(m_contactsWidget, &ContactsWidget::fillAddress, m_sendWidget, &SendWidget::fillAddress);
// [Coins] // [Coins]
m_coinsWidget = new CoinsWidget(m_ctx, this); m_coinsWidget = new CoinsWidget(m_wallet, this);
ui->coinsWidgetLayout->addWidget(m_coinsWidget); ui->coinsWidgetLayout->addWidget(m_coinsWidget);
#ifdef HAS_LOCALMONERO #ifdef HAS_LOCALMONERO
m_localMoneroWidget = new LocalMoneroWidget(this, m_ctx); m_localMoneroWidget = new LocalMoneroWidget(this, m_wallet);
ui->localMoneroLayout->addWidget(m_localMoneroWidget); ui->localMoneroLayout->addWidget(m_localMoneroWidget);
#else #else
ui->tabWidgetExchanges->setTabVisible(0, false); ui->tabWidgetExchanges->setTabVisible(0, false);
#endif #endif
#ifdef HAS_XMRIG #ifdef HAS_XMRIG
m_xmrig = new XMRigWidget(m_ctx, this); m_xmrig = new XMRigWidget(m_wallet, this);
ui->xmrRigLayout->addWidget(m_xmrig); ui->xmrRigLayout->addWidget(m_xmrig);
connect(m_xmrig, &XMRigWidget::miningStarted, [this]{ this->updateTitle(); }); connect(m_xmrig, &XMRigWidget::miningStarted, [this]{ this->updateTitle(); });
@ -239,7 +232,7 @@ void MainWindow::initWidgets() {
ui->frame_coinControl->setVisible(false); ui->frame_coinControl->setVisible(false);
connect(ui->btn_resetCoinControl, &QPushButton::clicked, [this]{ connect(ui->btn_resetCoinControl, &QPushButton::clicked, [this]{
m_ctx->setSelectedInputs({}); m_wallet->setSelectedInputs({});
}); });
m_walletUnlockWidget = new WalletUnlockWidget(this); m_walletUnlockWidget = new WalletUnlockWidget(this);
@ -276,8 +269,8 @@ void MainWindow::initMenu() {
// [Wallet] -> [Advanced] // [Wallet] -> [Advanced]
connect(ui->actionStore_wallet, &QAction::triggered, this, &MainWindow::tryStoreWallet); connect(ui->actionStore_wallet, &QAction::triggered, this, &MainWindow::tryStoreWallet);
connect(ui->actionUpdate_balance, &QAction::triggered, [this]{m_ctx->updateBalance();}); connect(ui->actionUpdate_balance, &QAction::triggered, [this]{m_wallet->updateBalance();});
connect(ui->actionRefresh_tabs, &QAction::triggered, [this]{m_ctx->refreshModels();}); connect(ui->actionRefresh_tabs, &QAction::triggered, [this]{m_wallet->refreshModels();});
connect(ui->actionRescan_spent, &QAction::triggered, this, &MainWindow::rescanSpent); connect(ui->actionRescan_spent, &QAction::triggered, this, &MainWindow::rescanSpent);
connect(ui->actionWallet_cache_debug, &QAction::triggered, this, &MainWindow::showWalletCacheDebugDialog); connect(ui->actionWallet_cache_debug, &QAction::triggered, this, &MainWindow::showWalletCacheDebugDialog);
@ -399,14 +392,14 @@ void MainWindow::initMenu() {
void MainWindow::initHome() { void MainWindow::initHome() {
// Ticker widgets // Ticker widgets
m_tickerWidgets.append(new PriceTickerWidget(this, m_ctx, "XMR")); m_tickerWidgets.append(new PriceTickerWidget(this, m_wallet, "XMR"));
m_tickerWidgets.append(new PriceTickerWidget(this, m_ctx, "BTC")); m_tickerWidgets.append(new PriceTickerWidget(this, m_wallet, "BTC"));
m_tickerWidgets.append(new RatioTickerWidget(this, m_ctx, "XMR", "BTC")); m_tickerWidgets.append(new RatioTickerWidget(this, m_wallet, "XMR", "BTC"));
for (const auto &widget : m_tickerWidgets) { for (const auto &widget : m_tickerWidgets) {
ui->tickerLayout->addWidget(widget); 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); ui->fiatTickerLayout->addWidget(m_balanceTickerWidget);
connect(ui->ccsWidget, &CCSWidget::selected, this, &MainWindow::showSendScreen); connect(ui->ccsWidget, &CCSWidget::selected, this, &MainWindow::showSendScreen);
@ -419,29 +412,56 @@ void MainWindow::initHome() {
} }
void MainWindow::initWalletContext() { void MainWindow::initWalletContext() {
connect(m_ctx.get(), &AppContext::balanceUpdated, this, &MainWindow::onBalanceUpdated); connect(m_wallet, &Wallet::balanceUpdated, this, &MainWindow::onBalanceUpdated);
connect(m_ctx.get(), &AppContext::synchronized, this, &MainWindow::onSynchronized); connect(m_wallet, &Wallet::synchronized, this, &MainWindow::onSynchronized); //TODO
connect(m_ctx.get(), &AppContext::blockchainSync, this, &MainWindow::onBlockchainSync); connect(m_wallet, &Wallet::blockchainSync, this, &MainWindow::onBlockchainSync);
connect(m_ctx.get(), &AppContext::refreshSync, this, &MainWindow::onRefreshSync); connect(m_wallet, &Wallet::refreshSync, this, &MainWindow::onRefreshSync);
connect(m_ctx.get(), &AppContext::createTransactionError, this, &MainWindow::onCreateTransactionError); connect(m_wallet, &Wallet::createTransactionError, this, &MainWindow::onCreateTransactionError);
connect(m_ctx.get(), &AppContext::createTransactionSuccess, this, &MainWindow::onCreateTransactionSuccess); connect(m_wallet, &Wallet::createTransactionSuccess, this, &MainWindow::onCreateTransactionSuccess);
connect(m_ctx.get(), &AppContext::transactionCommitted, this, &MainWindow::onTransactionCommitted); connect(m_wallet, &Wallet::transactionCommitted, this, &MainWindow::onTransactionCommitted);
connect(m_ctx.get(), &AppContext::deviceError, this, &MainWindow::onDeviceError); connect(m_wallet, &Wallet::initiateTransaction, this, &MainWindow::onInitiateTransaction);
connect(m_ctx.get(), &AppContext::deviceButtonRequest, this, &MainWindow::onDeviceButtonRequest); connect(m_wallet, &Wallet::endTransaction, this, &MainWindow::onEndTransaction);
connect(m_ctx.get(), &AppContext::deviceButtonPressed, this, &MainWindow::onDeviceButtonPressed); connect(m_wallet, &Wallet::keysCorrupted, this, &MainWindow::onKeysCorrupted);
connect(m_ctx.get(), &AppContext::initiateTransaction, this, &MainWindow::onInitiateTransaction); connect(m_wallet, &Wallet::selectedInputsChanged, this, &MainWindow::onSelectedInputsChanged);
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);
// Wallet // 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 // Order is important, first inform UI about a potential disconnect, then reconnect
this->onConnectionStatusChanged(status); 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){ void MainWindow::menuToggleTabVisible(const QString &key){
@ -459,15 +479,15 @@ void MainWindow::menuClearHistoryClicked() {
} }
QString MainWindow::walletName() { QString MainWindow::walletName() {
return QFileInfo(m_ctx->wallet->cachePath()).fileName(); return QFileInfo(m_wallet->cachePath()).fileName();
} }
QString MainWindow::walletCachePath() { QString MainWindow::walletCachePath() {
return m_ctx->wallet->cachePath(); return m_wallet->cachePath();
} }
QString MainWindow::walletKeysPath() { QString MainWindow::walletKeysPath() {
return m_ctx->wallet->keysPath(); return m_wallet->keysPath();
} }
void MainWindow::displayWalletErrorMsg(const QString &err) { void MainWindow::displayWalletErrorMsg(const QString &err) {
@ -497,10 +517,10 @@ void MainWindow::onWalletOpened() {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
m_splashDialog->hide(); m_splashDialog->hide();
m_ctx->wallet->setRingDatabase(Utils::ringDatabasePath()); m_wallet->setRingDatabase(Utils::ringDatabasePath());
m_ctx->updateBalance(); m_wallet->updateBalance();
if (m_ctx->wallet->isHwBacked()) { if (m_wallet->isHwBacked()) {
m_statusBtnHwDevice->show(); m_statusBtnHwDevice->show();
} }
@ -508,38 +528,39 @@ void MainWindow::onWalletOpened() {
this->setEnabled(true); this->setEnabled(true);
// receive page // receive page
m_ctx->wallet->subaddress()->refresh(m_ctx->wallet->currentSubaddressAccount()); m_wallet->subaddress()->refresh(m_wallet->currentSubaddressAccount());
if (m_ctx->wallet->subaddress()->count() == 1) { if (m_wallet->subaddress()->count() == 1) {
for (int i = 0; i < 10; i++) { 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 // history page
m_ctx->wallet->history()->refresh(m_ctx->wallet->currentSubaddressAccount()); m_wallet->history()->refresh(m_wallet->currentSubaddressAccount());
// coins page // coins page
m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount()); m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
m_coinsWidget->setModel(m_ctx->wallet->coinsModel(), m_ctx->wallet->coins()); m_coinsWidget->setModel(m_wallet->coinsModel(), m_wallet->coins());
m_ctx->wallet->coinsModel()->setCurrentSubaddressAccount(m_ctx->wallet->currentSubaddressAccount()); m_wallet->coinsModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
// Coin labeling uses set_tx_note, so we need to refresh history too // Coin labeling uses set_tx_note, so we need to refresh history too
connect(m_ctx->wallet->coins(), &Coins::descriptionChanged, [this] { connect(m_wallet->coins(), &Coins::descriptionChanged, [this] {
m_ctx->wallet->history()->refresh(m_ctx->wallet->currentSubaddressAccount()); m_wallet->history()->refresh(m_wallet->currentSubaddressAccount());
}); });
// Vice versa // Vice versa
connect(m_ctx->wallet->history(), &TransactionHistory::txNoteChanged, [this] { connect(m_wallet->history(), &TransactionHistory::txNoteChanged, [this] {
m_ctx->wallet->coins()->refresh(m_ctx->wallet->currentSubaddressAccount()); m_wallet->coins()->refresh(m_wallet->currentSubaddressAccount());
}); });
this->updatePasswordIcon(); this->updatePasswordIcon();
this->updateTitle(); this->updateTitle();
m_ctx->nodes->connectToNode(); m_nodes->allowConnection();
m_nodes->connectToNode();
m_updateBytes.start(250); m_updateBytes.start(250);
if (config()->get(Config::writeRecentlyOpenedWallets).toBool()) { 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() { 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" QMessageBox::warning(this, "Save wallet", "Unable to save wallet during synchronization.\n\n"
"Wait until synchronization is finished and try again."); "Wait until synchronization is finished and try again.");
return; return;
} }
m_ctx->wallet->store(); m_wallet->store();
} }
void MainWindow::onWebsocketStatusChanged(bool enabled) { void MainWindow::onWebsocketStatusChanged(bool enabled) {
@ -614,6 +635,8 @@ void MainWindow::onWebsocketStatusChanged(bool enabled) {
} }
void MainWindow::onProxySettingsChanged() { void MainWindow::onProxySettingsChanged() {
m_nodes->connectToNode();
int proxy = config()->get(Config::proxy).toInt(); int proxy = config()->get(Config::proxy).toInt();
if (proxy == Config::Proxy::Tor) { if (proxy == Config::Proxy::Tor) {
@ -631,6 +654,14 @@ void MainWindow::onProxySettingsChanged() {
m_statusBtnProxySettings->hide(); m_statusBtnProxySettings->hide();
} }
void MainWindow::onOfflineMode(bool offline) {
if (!m_wallet) {
return;
}
m_wallet->setOffline(offline);
this->onConnectionStatusChanged(Wallet::ConnectionStatus_Disconnected);
}
void MainWindow::onSynchronized() { void MainWindow::onSynchronized() {
this->updateNetStats(); this->updateNetStats();
this->setStatusText("Synchronized"); this->setStatusText("Synchronized");
@ -693,13 +724,13 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
QString tx_err = tx->errorString(); QString tx_err = tx->errorString();
qCritical() << tx_err; 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); err = QString("%1 Wrong node version: %2").arg(err, tx_err);
else else
err = QString("%1 %2").arg(err, tx_err); err = QString("%1 %2").arg(err, tx_err);
if (tx_err.contains("Node response did not include the requested real output")) { 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" 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." "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; qDebug() << Q_FUNC_INFO << err;
this->displayWalletErrorMsg(err); this->displayWalletErrorMsg(err);
m_ctx->wallet->disposeTransaction(tx); m_wallet->disposeTransaction(tx);
return; return;
} }
else if (tx->txCount() == 0) { else if (tx->txCount() == 0) {
err = QString("%1 %2").arg(err, "No unmixable outputs to sweep."); err = QString("%1 %2").arg(err, "No unmixable outputs to sweep.");
qDebug() << Q_FUNC_INFO << err; qDebug() << Q_FUNC_INFO << err;
this->displayWalletErrorMsg(err); this->displayWalletErrorMsg(err);
m_ctx->wallet->disposeTransaction(tx); m_wallet->disposeTransaction(tx);
return; return;
} }
else if (tx->txCount() > 1) { else if (tx->txCount() > 1) {
err = QString("%1 %2").arg(err, "Split transactions are not supported. Try sending a smaller amount."); err = QString("%1 %2").arg(err, "Split transactions are not supported. Try sending a smaller amount.");
qDebug() << Q_FUNC_INFO << err; qDebug() << Q_FUNC_INFO << err;
this->displayWalletErrorMsg(err); this->displayWalletErrorMsg(err);
m_ctx->wallet->disposeTransaction(tx); m_wallet->disposeTransaction(tx);
return; 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."); 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; qDebug() << Q_FUNC_INFO << err;
this->displayWalletErrorMsg(err); this->displayWalletErrorMsg(err);
m_ctx->wallet->disposeTransaction(tx); m_wallet->disposeTransaction(tx);
return; 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 // Show advanced dialog on multi-destination transactions
if (address.size() > 1 || m_ctx->wallet->viewOnly()) { if (address.size() > 1 || m_wallet->viewOnly()) {
TxConfAdvDialog dialog_adv{m_ctx, m_ctx->tmpTxDescription, this}; TxConfAdvDialog dialog_adv{m_wallet, m_wallet->tmpTxDescription, this};
dialog_adv.setTransaction(tx, !m_ctx->wallet->viewOnly()); dialog_adv.setTransaction(tx, !m_wallet->viewOnly());
dialog_adv.exec(); dialog_adv.exec();
return; 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()) { switch (dialog.exec()) {
case QDialog::Rejected: case QDialog::Rejected:
{ {
if (!dialog.showAdvanced) if (!dialog.showAdvanced) {
m_ctx->onCancelTransaction(tx, address); m_wallet->disposeTransaction(tx);
}
break; break;
} }
case QDialog::Accepted: case QDialog::Accepted:
m_ctx->commitTransaction(tx, m_ctx->tmpTxDescription); m_wallet->commitTransaction(tx, m_wallet->tmpTxDescription);
break; break;
} }
if (dialog.showAdvanced) { 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.setTransaction(tx);
dialog_adv.exec(); dialog_adv.exec();
} }
@ -789,8 +821,8 @@ void MainWindow::onTransactionCommitted(bool status, PendingTransaction *tx, con
msgBox.exec(); msgBox.exec();
if (msgBox.clickedButton() == showDetailsButton) { if (msgBox.clickedButton() == showDetailsButton) {
this->showHistoryTab(); this->showHistoryTab();
TransactionInfo *txInfo = m_ctx->wallet->history()->transaction(txid.first()); TransactionInfo *txInfo = m_wallet->history()->transaction(txid.first());
auto *dialog = new TxInfoDialog(m_ctx, txInfo, this); auto *dialog = new TxInfoDialog(m_wallet, txInfo, this);
connect(dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction); connect(dialog, &TxInfoDialog::resendTranscation, this, &MainWindow::onResendTransaction);
dialog->show(); dialog->show();
dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setAttribute(Qt::WA_DeleteOnClose);
@ -815,22 +847,22 @@ void MainWindow::onCreateTransactionError(const QString &message) {
} }
void MainWindow::showWalletInfoDialog() { void MainWindow::showWalletInfoDialog() {
WalletInfoDialog dialog{m_ctx, this}; WalletInfoDialog dialog{m_wallet, this};
dialog.exec(); dialog.exec();
} }
void MainWindow::showSeedDialog() { 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."); QMessageBox::information(this, "Information", "Seed unavailable: Wallet keys are stored on hardware device.");
return; 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"); QMessageBox::information(this, "Information", "Wallet is view-only and has no seed.\n\nTo obtain wallet keys go to Wallet -> View-Only");
return; 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"); QMessageBox::information(this, "Information", "Wallet is non-deterministic and has no seed.\n\nTo obtain wallet keys go to Wallet -> Keys");
return; return;
} }
@ -839,18 +871,18 @@ void MainWindow::showSeedDialog() {
return; return;
} }
SeedDialog dialog{m_ctx, this}; SeedDialog dialog{m_wallet, this};
dialog.exec(); dialog.exec();
} }
void MainWindow::showPasswordDialog() { void MainWindow::showPasswordDialog() {
PasswordChangeDialog dialog{this, m_ctx->wallet}; PasswordChangeDialog dialog{this, m_wallet};
dialog.exec(); dialog.exec();
this->updatePasswordIcon(); this->updatePasswordIcon();
} }
void MainWindow::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"); QIcon icon = emptyPassword ? icons()->icon("unlock.svg") : icons()->icon("lock.svg");
m_statusBtnPassword->setIcon(icon); m_statusBtnPassword->setIcon(icon);
} }
@ -860,12 +892,12 @@ void MainWindow::showKeysDialog() {
return; return;
} }
KeysDialog dialog{m_ctx, this}; KeysDialog dialog{m_wallet, this};
dialog.exec(); dialog.exec();
} }
void MainWindow::showViewOnlyDialog() { void MainWindow::showViewOnlyDialog() {
ViewOnlyDialog dialog{m_ctx, this}; ViewOnlyDialog dialog{m_wallet, this};
dialog.exec(); dialog.exec();
} }
@ -900,16 +932,16 @@ void MainWindow::menuAboutClicked() {
} }
void MainWindow::menuSettingsClicked(bool showProxyTab) { void MainWindow::menuSettingsClicked(bool showProxyTab) {
m_windowManager->showSettings(m_ctx, this, showProxyTab); m_windowManager->showSettings(m_nodes, this, showProxyTab);
} }
void MainWindow::menuSignVerifyClicked() { void MainWindow::menuSignVerifyClicked() {
SignVerifyDialog dialog{m_ctx->wallet, this}; SignVerifyDialog dialog{m_wallet, this};
dialog.exec(); dialog.exec();
} }
void MainWindow::menuVerifyTxProof() { void MainWindow::menuVerifyTxProof() {
VerifyProofDialog dialog{m_ctx->wallet, this}; VerifyProofDialog dialog{m_wallet, this};
dialog.exec(); dialog.exec();
} }
@ -936,18 +968,18 @@ void MainWindow::updateWidgetIcons() {
QIcon MainWindow::hardwareDevicePairedIcon() { QIcon MainWindow::hardwareDevicePairedIcon() {
QString filename; QString filename;
if (m_ctx->wallet->isLedger()) if (m_wallet->isLedger())
filename = "ledger.png"; filename = "ledger.png";
else if (m_ctx->wallet->isTrezor()) else if (m_wallet->isTrezor())
filename = ColorScheme::darkScheme ? "trezor_white.png" : "trezor.png"; filename = ColorScheme::darkScheme ? "trezor_white.png" : "trezor.png";
return icons()->icon(filename); return icons()->icon(filename);
} }
QIcon MainWindow::hardwareDeviceUnpairedIcon() { QIcon MainWindow::hardwareDeviceUnpairedIcon() {
QString filename; QString filename;
if (m_ctx->wallet->isLedger()) if (m_wallet->isLedger())
filename = "ledger_unpaired.png"; 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"; filename = ColorScheme::darkScheme ? "trezor_unpaired_white.png" : "trezor_unpaired.png";
return icons()->icon(filename); return icons()->icon(filename);
} }
@ -964,10 +996,10 @@ void MainWindow::closeEvent(QCloseEvent *event) {
m_updateBytes.stop(); m_updateBytes.stop();
m_txTimer.stop(); m_txTimer.stop();
m_ctx->stopTimers();
// Wallet signal may fire after AppContext is gone, causing segv // Wallet signal may fire after AppContext is gone, causing segv
m_ctx->wallet->disconnect(); m_wallet->disconnect();
this->disconnect();
this->saveGeo(); this->saveGeo();
m_windowManager->closeWindow(this); m_windowManager->closeWindow(this);
@ -1031,16 +1063,16 @@ void MainWindow::onViewOnBlockExplorer(const QString &txid) {
} }
void MainWindow::onResendTransaction(const QString &txid) { void MainWindow::onResendTransaction(const QString &txid) {
QString txHex = m_ctx->getCacheTransaction(txid); QString txHex = m_wallet->getCacheTransaction(txid);
if (txHex.isEmpty()) { if (txHex.isEmpty()) {
QMessageBox::warning(this, "Unable to resend transaction", "Transaction was not found in transaction cache. Unable to resend."); QMessageBox::warning(this, "Unable to resend transaction", "Transaction was not found in transaction cache. Unable to resend.");
return; return;
} }
// Connect to a different node so chances of successful relay are higher // 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(); dialog.exec();
} }
@ -1048,14 +1080,14 @@ void MainWindow::importContacts() {
const QString targetFile = QFileDialog::getOpenFileName(this, "Import CSV file", QDir::homePath(), "CSV Files (*.csv)"); const QString targetFile = QFileDialog::getOpenFileName(this, "Import CSV file", QDir::homePath(), "CSV Files (*.csv)");
if(targetFile.isEmpty()) return; if(targetFile.isEmpty()) return;
auto *model = m_ctx->wallet->addressBookModel(); auto *model = m_wallet->addressBookModel();
QMapIterator<QString, QString> i(model->readCSV(targetFile)); QMapIterator<QString, QString> i(model->readCSV(targetFile));
int inserts = 0; int inserts = 0;
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
bool addressValid = WalletManager::addressValid(i.value(), m_ctx->wallet->nettype()); bool addressValid = WalletManager::addressValid(i.value(), m_wallet->nettype());
if(addressValid) { if(addressValid) {
m_ctx->wallet->addressBook()->addRow(i.value(), "", i.key()); m_wallet->addressBook()->addRow(i.value(), "", i.key());
inserts++; inserts++;
} }
} }
@ -1075,7 +1107,7 @@ void MainWindow::restoreGeo() {
} }
void MainWindow::showDebugInfo() { void MainWindow::showDebugInfo() {
DebugInfoDialog dialog{m_ctx, this}; DebugInfoDialog dialog{m_wallet, m_nodes, this};
dialog.exec(); dialog.exec();
} }
@ -1084,7 +1116,7 @@ void MainWindow::showWalletCacheDebugDialog() {
return; return;
} }
WalletCacheDebugDialog dialog{m_ctx, this}; WalletCacheDebugDialog dialog{m_wallet, this};
dialog.exec(); dialog.exec();
} }
@ -1103,7 +1135,7 @@ void MainWindow::showAddressChecker() {
return; return;
} }
SubaddressIndex index = m_ctx->wallet->subaddressIndex(address); SubaddressIndex index = m_wallet->subaddressIndex(address);
if (!index.isValid()) { if (!index.isValid()) {
// TODO: probably mention lookahead here // TODO: probably mention lookahead here
QMessageBox::warning(this, "Address Checker", "This address does not belong to this wallet."); 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)"); 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.isEmpty()) return;
if (!fn.endsWith("_keyImages")) fn += "_keyImages"; if (!fn.endsWith("_keyImages")) fn += "_keyImages";
bool r = m_ctx->wallet->exportKeyImages(fn, true); bool r = m_wallet->exportKeyImages(fn, true);
if (!r) { 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 { } else {
QMessageBox::information(this, "Key image export", "Successfully exported key images."); QMessageBox::information(this, "Key image export", "Successfully exported key images.");
} }
@ -1128,12 +1160,12 @@ void MainWindow::exportKeyImages() {
void MainWindow::importKeyImages() { void MainWindow::importKeyImages() {
QString fn = QFileDialog::getOpenFileName(this, "Import key image file", QDir::homePath(), "Key Images (*_keyImages)"); QString fn = QFileDialog::getOpenFileName(this, "Import key image file", QDir::homePath(), "Key Images (*_keyImages)");
if (fn.isEmpty()) return; if (fn.isEmpty()) return;
bool r = m_ctx->wallet->importKeyImages(fn); bool r = m_wallet->importKeyImages(fn);
if (!r) { 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 { } else {
QMessageBox::information(this, "Key image import", "Successfully imported key images"); 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)"); 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.isEmpty()) return;
if (!fn.endsWith("_outputs")) fn += "_outputs"; if (!fn.endsWith("_outputs")) fn += "_outputs";
bool r = m_ctx->wallet->exportOutputs(fn, true); bool r = m_wallet->exportOutputs(fn, true);
if (!r) { 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 { } else {
QMessageBox::information(this, "Outputs export", "Successfully exported outputs."); QMessageBox::information(this, "Outputs export", "Successfully exported outputs.");
} }
@ -1152,20 +1184,20 @@ void MainWindow::exportOutputs() {
void MainWindow::importOutputs() { void MainWindow::importOutputs() {
QString fn = QFileDialog::getOpenFileName(this, "Import outputs file", QDir::homePath(), "Outputs (*_outputs)"); QString fn = QFileDialog::getOpenFileName(this, "Import outputs file", QDir::homePath(), "Outputs (*_outputs)");
if (fn.isEmpty()) return; if (fn.isEmpty()) return;
bool r = m_ctx->wallet->importOutputs(fn); bool r = m_wallet->importOutputs(fn);
if (!r) { 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 { } else {
QMessageBox::information(this, "Outputs import", "Successfully imported outputs"); QMessageBox::information(this, "Outputs import", "Successfully imported outputs");
m_ctx->refreshModels(); m_wallet->refreshModels();
} }
} }
void MainWindow::loadUnsignedTx() { void MainWindow::loadUnsignedTx() {
QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*unsigned_monero_tx)"); QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*unsigned_monero_tx)");
if (fn.isEmpty()) return; if (fn.isEmpty()) return;
UnsignedTransaction *tx = m_ctx->wallet->loadTxFile(fn); UnsignedTransaction *tx = m_wallet->loadTxFile(fn);
auto err = m_ctx->wallet->errorString(); auto err = m_wallet->errorString();
if (!err.isEmpty()) { if (!err.isEmpty()) {
QMessageBox::warning(this, "Load transaction from file", QString("Failed to load transaction.\n\n%1").arg(err)); QMessageBox::warning(this, "Load transaction from file", QString("Failed to load transaction.\n\n%1").arg(err));
return; return;
@ -1180,8 +1212,8 @@ void MainWindow::loadUnsignedTxFromClipboard() {
QMessageBox::warning(this, "Load unsigned transaction from clipboard", "Clipboard is empty"); QMessageBox::warning(this, "Load unsigned transaction from clipboard", "Clipboard is empty");
return; return;
} }
UnsignedTransaction *tx = m_ctx->wallet->loadTxFromBase64Str(unsigned_tx); UnsignedTransaction *tx = m_wallet->loadTxFromBase64Str(unsigned_tx);
auto err = m_ctx->wallet->errorString(); auto err = m_wallet->errorString();
if (!err.isEmpty()) { if (!err.isEmpty()) {
QMessageBox::warning(this, "Load unsigned transaction from clipboard", QString("Failed to load transaction.\n\n%1").arg(err)); QMessageBox::warning(this, "Load unsigned transaction from clipboard", QString("Failed to load transaction.\n\n%1").arg(err));
return; return;
@ -1193,25 +1225,25 @@ void MainWindow::loadUnsignedTxFromClipboard() {
void MainWindow::loadSignedTx() { void MainWindow::loadSignedTx() {
QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*signed_monero_tx)"); QString fn = QFileDialog::getOpenFileName(this, "Select transaction to load", QDir::homePath(), "Transaction (*signed_monero_tx)");
if (fn.isEmpty()) return; if (fn.isEmpty()) return;
PendingTransaction *tx = m_ctx->wallet->loadSignedTxFile(fn); PendingTransaction *tx = m_wallet->loadSignedTxFile(fn);
auto err = m_ctx->wallet->errorString(); auto err = m_wallet->errorString();
if (!err.isEmpty()) { if (!err.isEmpty()) {
QMessageBox::warning(this, "Load signed transaction from file", err); QMessageBox::warning(this, "Load signed transaction from file", err);
return; return;
} }
TxConfAdvDialog dialog{m_ctx, "", this}; TxConfAdvDialog dialog{m_wallet, "", this};
dialog.setTransaction(tx); dialog.setTransaction(tx);
dialog.exec(); dialog.exec();
} }
void MainWindow::loadSignedTxFromText() { void MainWindow::loadSignedTxFromText() {
TxBroadcastDialog dialog{this, m_ctx}; TxBroadcastDialog dialog{this, m_nodes};
dialog.exec(); dialog.exec();
} }
void MainWindow::createUnsignedTxDialog(UnsignedTransaction *tx) { void MainWindow::createUnsignedTxDialog(UnsignedTransaction *tx) {
TxConfAdvDialog dialog{m_ctx, "", this}; TxConfAdvDialog dialog{m_wallet, "", this};
dialog.setUnsignedTransaction(tx); dialog.setUnsignedTransaction(tx);
dialog.exec(); dialog.exec();
} }
@ -1229,11 +1261,13 @@ void MainWindow::importTransaction() {
} }
} }
TxImportDialog dialog(this, m_ctx); TxImportDialog dialog(this, m_wallet);
dialog.exec(); dialog.exec();
} }
void MainWindow::onDeviceError(const QString &error) { void MainWindow::onDeviceError(const QString &error) {
qCritical() << "Device error: " << error;
if (m_showDeviceError) { if (m_showDeviceError) {
return; return;
} }
@ -1243,7 +1277,7 @@ void MainWindow::onDeviceError(const QString &error) {
m_showDeviceError = true; m_showDeviceError = true;
auto result = QMessageBox::question(this, "Hardware device", "Lost connection to hardware device. Attempt to reconnect?"); auto result = QMessageBox::question(this, "Hardware device", "Lost connection to hardware device. Attempt to reconnect?");
if (result == QMessageBox::Yes) { if (result == QMessageBox::Yes) {
bool r = m_ctx->wallet->reconnectDevice(); bool r = m_wallet->reconnectDevice();
if (r) { if (r) {
break; break;
} }
@ -1254,14 +1288,14 @@ void MainWindow::onDeviceError(const QString &error) {
} }
} }
m_statusBtnHwDevice->setIcon(this->hardwareDevicePairedIcon()); m_statusBtnHwDevice->setIcon(this->hardwareDevicePairedIcon());
m_ctx->wallet->startRefresh(); m_wallet->startRefresh();
m_showDeviceError = false; m_showDeviceError = false;
} }
void MainWindow::onDeviceButtonRequest(quint64 code) { void MainWindow::onDeviceButtonRequest(quint64 code) {
qDebug() << "DeviceButtonRequest, code: " << code; qDebug() << "DeviceButtonRequest, code: " << code;
if (m_ctx->wallet->isTrezor()) { if (m_wallet->isTrezor()) {
switch (code) { switch (code) {
case 1: case 1:
{ {
@ -1306,41 +1340,41 @@ void MainWindow::onWalletPassphraseNeeded(bool on_device) {
"the hardware wallet for better security.", "the hardware wallet for better security.",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
if (button == QMessageBox::Yes) { if (button == QMessageBox::Yes) {
m_ctx->wallet->onPassphraseEntered("", true, false); m_wallet->onPassphraseEntered("", true, false);
return; return;
} }
bool ok; bool ok;
QString passphrase = QInputDialog::getText(nullptr, "Wallet Passphrase Needed", "Enter passphrase:", QLineEdit::EchoMode::Password, "", &ok); QString passphrase = QInputDialog::getText(nullptr, "Wallet Passphrase Needed", "Enter passphrase:", QLineEdit::EchoMode::Password, "", &ok);
if (ok) { if (ok) {
m_ctx->wallet->onPassphraseEntered(passphrase, false, false); m_wallet->onPassphraseEntered(passphrase, false, false);
} else { } else {
m_ctx->wallet->onPassphraseEntered(passphrase, false, true); m_wallet->onPassphraseEntered(passphrase, false, true);
} }
} }
void MainWindow::updateNetStats() { void MainWindow::updateNetStats() {
if (!m_ctx->wallet || m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected if (!m_wallet || m_wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected
|| m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_Synchronized) || m_wallet->connectionStatus() == Wallet::ConnectionStatus_Synchronized)
{ {
m_statusLabelNetStats->hide(); m_statusLabelNetStats->hide();
return; return;
} }
m_statusLabelNetStats->show(); 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() { void MainWindow::rescanSpent() {
if (!m_ctx->wallet->rescanSpent()) { if (!m_wallet->rescanSpent()) {
QMessageBox::warning(this, "Rescan spent", m_ctx->wallet->errorString()); QMessageBox::warning(this, "Rescan spent", m_wallet->errorString());
} else { } else {
QMessageBox::information(this, "Rescan spent", "Successfully rescanned spent outputs."); QMessageBox::information(this, "Rescan spent", "Successfully rescanned spent outputs.");
} }
} }
void MainWindow::showBalanceDialog() { void MainWindow::showBalanceDialog() {
BalanceDialog dialog{this, m_ctx->wallet}; BalanceDialog dialog{this, m_wallet};
dialog.exec(); dialog.exec();
} }
@ -1420,7 +1454,7 @@ void MainWindow::onInitiateTransaction() {
m_constructingTransaction = true; m_constructingTransaction = true;
m_txTimer.start(1000); m_txTimer.start(1000);
if (m_ctx->wallet->isHwBacked()) { if (m_wallet->isHwBacked()) {
QString message = "Constructing transaction: action may be required on device."; QString message = "Constructing transaction: action may be required on device.";
m_splashDialog->setMessage(message); m_splashDialog->setMessage(message);
m_splashDialog->setIcon(QPixmap(":/assets/images/unconfirmed.png")); m_splashDialog->setIcon(QPixmap(":/assets/images/unconfirmed.png"));
@ -1435,7 +1469,7 @@ void MainWindow::onEndTransaction() {
m_txTimer.stop(); m_txTimer.stop();
this->setStatusText(m_statusText); this->setStatusText(m_statusText);
if (m_ctx->wallet->isHwBacked()) { if (m_wallet->isHwBacked()) {
m_splashDialog->hide(); m_splashDialog->hide();
} }
} }
@ -1456,7 +1490,7 @@ void MainWindow::onSelectedInputsChanged(const QStringList &selectedInputs) {
if (numInputs > 0) { if (numInputs > 0) {
quint64 totalAmount = 0; quint64 totalAmount = 0;
auto coins = m_ctx->wallet->coins()->coinsFromKeyImage(selectedInputs); auto coins = m_wallet->coins()->coinsFromKeyImage(selectedInputs);
for (const auto coin : coins) { for (const auto coin : coins) {
totalAmount += coin->amount(); totalAmount += coin->amount();
} }
@ -1467,20 +1501,20 @@ void MainWindow::onSelectedInputsChanged(const QStringList &selectedInputs) {
} }
void MainWindow::onExportHistoryCSV(bool checked) { void MainWindow::onExportHistoryCSV(bool checked) {
if (m_ctx->wallet == nullptr) if (m_wallet == nullptr)
return; return;
QString fn = QFileDialog::getSaveFileName(this, "Save CSV file", QDir::homePath(), "CSV (*.csv)"); QString fn = QFileDialog::getSaveFileName(this, "Save CSV file", QDir::homePath(), "CSV (*.csv)");
if (fn.isEmpty()) if (fn.isEmpty())
return; return;
if (!fn.endsWith(".csv")) if (!fn.endsWith(".csv"))
fn += ".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)); QMessageBox::information(this, "CSV export", QString("Transaction history exported to %1").arg(fn));
} }
void MainWindow::onExportContactsCSV(bool checked) { void MainWindow::onExportContactsCSV(bool checked) {
if (m_ctx->wallet == nullptr) return; if (m_wallet == nullptr) return;
auto *model = m_ctx->wallet->addressBookModel(); auto *model = m_wallet->addressBookModel();
if (model->rowCount() <= 0){ if (model->rowCount() <= 0){
QMessageBox::warning(this, "Error", "Addressbook empty"); QMessageBox::warning(this, "Error", "Addressbook empty");
return; return;
@ -1540,19 +1574,19 @@ QString MainWindow::getPlatformTag() {
} }
QString MainWindow::getHardwareDevice() { QString MainWindow::getHardwareDevice() {
if (!m_ctx->wallet->isHwBacked()) if (!m_wallet->isHwBacked())
return ""; return "";
if (m_ctx->wallet->isTrezor()) if (m_wallet->isTrezor())
return "Trezor"; return "Trezor";
if (m_ctx->wallet->isLedger()) if (m_wallet->isLedger())
return "Ledger"; return "Ledger";
return "Unknown"; return "Unknown";
} }
void MainWindow::updateTitle() { 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]"; title += " [view-only]";
#ifdef HAS_XMRIG #ifdef HAS_XMRIG
if (m_xmrig->isMining()) if (m_xmrig->isMining())
@ -1565,13 +1599,13 @@ void MainWindow::updateTitle() {
} }
void MainWindow::donationNag() { void MainWindow::donationNag() {
if (m_ctx->networkType != NetworkType::Type::MAINNET) if (m_wallet->nettype() != NetworkType::Type::MAINNET)
return; return;
if (m_ctx->wallet->viewOnly()) if (m_wallet->viewOnly())
return; return;
if (m_ctx->wallet->balanceAll() == 0) if (m_wallet->balanceAll() == 0)
return; return;
auto donationCounter = config()->get(Config::donateBeg).toInt(); auto donationCounter = config()->get(Config::donateBeg).toInt();
@ -1640,7 +1674,7 @@ bool MainWindow::verifyPassword(bool sensitive) {
return false; return false;
} }
if (!m_ctx->wallet->verifyPassword(passwordDialog.password)) { if (!m_wallet->verifyPassword(passwordDialog.password)) {
incorrectPassword = true; incorrectPassword = true;
continue; continue;
} }
@ -1707,7 +1741,7 @@ void MainWindow::unlockWallet(const QString &password) {
return; return;
} }
if (!m_ctx->wallet->verifyPassword(password)) { if (!m_wallet->verifyPassword(password)) {
m_walletUnlockWidget->incorrectPassword(); m_walletUnlockWidget->incorrectPassword();
return; return;
} }
@ -1742,4 +1776,6 @@ void MainWindow::toggleSearchbar(bool visible) {
m_coinsWidget->focusSearchbar(); m_coinsWidget->focusSearchbar();
} }
MainWindow::~MainWindow() = default; MainWindow::~MainWindow() {
qDebug() << "~MainWindow";
};

View file

@ -8,7 +8,6 @@
#include <QSystemTrayIcon> #include <QSystemTrayIcon>
#include <QMenu> #include <QMenu>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "CalcWindow.h" #include "CalcWindow.h"
#include "SettingsDialog.h" #include "SettingsDialog.h"
@ -30,6 +29,7 @@
#include "model/CoinsProxyModel.h" #include "model/CoinsProxyModel.h"
#include "utils/networking.h" #include "utils/networking.h"
#include "utils/config.h" #include "utils/config.h"
#include "utils/daemonrpc.h"
#include "utils/EventFilter.h" #include "utils/EventFilter.h"
#include "utils/Updater.h" #include "utils/Updater.h"
#include "widgets/CCSWidget.h" #include "widgets/CCSWidget.h"
@ -192,6 +192,7 @@ private slots:
void onWebsocketStatusChanged(bool enabled); void onWebsocketStatusChanged(bool enabled);
void showUpdateNotification(); void showUpdateNotification();
void onProxySettingsChanged(); void onProxySettingsChanged();
void onOfflineMode(bool offline);
private: private:
friend WindowManager; friend WindowManager;
@ -235,7 +236,9 @@ private:
QScopedPointer<Ui::MainWindow> ui; QScopedPointer<Ui::MainWindow> ui;
WindowManager *m_windowManager; WindowManager *m_windowManager;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet = nullptr;
Nodes *m_nodes;
DaemonRpc *m_rpc;
CalcWindow *m_windowCalc = nullptr; CalcWindow *m_windowCalc = nullptr;
SplashDialog *m_splashDialog = nullptr; SplashDialog *m_splashDialog = nullptr;

View file

@ -12,15 +12,15 @@
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "utils/Icons.h" #include "utils/Icons.h"
ReceiveWidget::ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent) ReceiveWidget::ReceiveWidget(Wallet *wallet, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::ReceiveWidget) , ui(new Ui::ReceiveWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
m_model = m_ctx->wallet->subaddressModel(); m_model = m_wallet->subaddressModel();
m_proxyModel = new SubaddressProxyModel(this, m_ctx->wallet->subaddress()); m_proxyModel = new SubaddressProxyModel(this, m_wallet->subaddress());
m_proxyModel->setSourceModel(m_model); m_proxyModel->setSourceModel(m_model);
m_proxyModel->setHiddenAddresses(this->getHiddenAddresses()); m_proxyModel->setHiddenAddresses(this->getHiddenAddresses());
@ -112,7 +112,7 @@ void ReceiveWidget::showContextMenu(const QPoint &point) {
menu->addAction("Hide address", this, &ReceiveWidget::hideAddress); menu->addAction("Hide address", this, &ReceiveWidget::hideAddress);
} }
if (m_ctx->wallet->isHwBacked()) { if (m_wallet->isHwBacked()) {
menu->addAction("Show on device", this, &ReceiveWidget::showOnDevice); 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(); 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(); dialog.exec();
} }
@ -189,13 +189,13 @@ void ReceiveWidget::showAddress()
void ReceiveWidget::showOnDevice() { void ReceiveWidget::showOnDevice() {
Monero::SubaddressRow* row = this->currentEntry(); Monero::SubaddressRow* row = this->currentEntry();
if (!row) return; if (!row) return;
m_ctx->wallet->deviceShowAddressAsync(m_ctx->wallet->currentSubaddressAccount(), row->getRowId(), ""); m_wallet->deviceShowAddressAsync(m_wallet->currentSubaddressAccount(), row->getRowId(), "");
} }
void ReceiveWidget::generateSubaddress() { 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) { 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() { QStringList ReceiveWidget::getHiddenAddresses() {
QString data = m_ctx->wallet->getCacheAttribute("feather.hiddenaddresses"); QString data = m_wallet->getCacheAttribute("feather.hiddenaddresses");
return data.split(","); return data.split(",");
} }
@ -239,14 +239,14 @@ void ReceiveWidget::addHiddenAddress(const QString& address) {
hiddenAddresses.append(address); hiddenAddresses.append(address);
} }
QString data = hiddenAddresses.join(","); QString data = hiddenAddresses.join(",");
m_ctx->wallet->setCacheAttribute("feather.hiddenaddresses", data); m_wallet->setCacheAttribute("feather.hiddenaddresses", data);
} }
void ReceiveWidget::removeHiddenAddress(const QString &address) { void ReceiveWidget::removeHiddenAddress(const QString &address) {
QStringList hiddenAddresses = this->getHiddenAddresses(); QStringList hiddenAddresses = this->getHiddenAddresses();
hiddenAddresses.removeAll(address); hiddenAddresses.removeAll(address);
QString data = hiddenAddresses.join(","); QString data = hiddenAddresses.join(",");
m_ctx->wallet->setCacheAttribute("feather.hiddenaddresses", data); m_wallet->setCacheAttribute("feather.hiddenaddresses", data);
} }
Monero::SubaddressRow* ReceiveWidget::currentEntry() { Monero::SubaddressRow* ReceiveWidget::currentEntry() {

View file

@ -8,8 +8,8 @@
#include <QWidget> #include <QWidget>
#include <QSvgWidget> #include <QSvgWidget>
#include "appcontext.h"
#include "libwalletqt/Subaddress.h" #include "libwalletqt/Subaddress.h"
#include "libwalletqt/Wallet.h"
#include "model/SubaddressProxyModel.h" #include "model/SubaddressProxyModel.h"
#include "model/SubaddressModel.h" #include "model/SubaddressModel.h"
#include "qrcode/QrCode.h" #include "qrcode/QrCode.h"
@ -23,7 +23,7 @@ class ReceiveWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit ReceiveWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit ReceiveWidget(Wallet *wallet, QWidget *parent = nullptr);
~ReceiveWidget() override; ~ReceiveWidget() override;
void setSearchbarVisible(bool visible); void setSearchbarVisible(bool visible);
@ -53,7 +53,7 @@ private slots:
private: private:
QScopedPointer<Ui::ReceiveWidget> ui; QScopedPointer<Ui::ReceiveWidget> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
QMenu *m_headerMenu; QMenu *m_headerMenu;
QAction *m_showFullAddressesAction; QAction *m_showFullAddressesAction;
QAction *m_showUsedAddressesAction; QAction *m_showUsedAddressesAction;

View file

@ -9,7 +9,9 @@
#include "ColorScheme.h" #include "ColorScheme.h"
#include "constants.h" #include "constants.h"
#include "utils/AppData.h" #include "utils/AppData.h"
#include "utils/config.h"
#include "Icons.h" #include "Icons.h"
#include "libwalletqt/WalletManager.h"
#if defined(WITH_SCANNER) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #if defined(WITH_SCANNER) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include "qrcode_scanner/QrCodeScanDialog.h" #include "qrcode_scanner/QrCodeScanDialog.h"
@ -19,10 +21,10 @@
#include <QMediaDevices> #include <QMediaDevices>
#endif #endif
SendWidget::SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent) SendWidget::SendWidget(Wallet *wallet, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::SendWidget) , ui(new Ui::SendWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -32,8 +34,8 @@ SendWidget::SendWidget(QSharedPointer<AppContext> ctx, QWidget *parent)
QValidator *validator = new QRegularExpressionValidator(rx, this); QValidator *validator = new QRegularExpressionValidator(rx, this);
ui->lineAmount->setValidator(validator); ui->lineAmount->setValidator(validator);
connect(m_ctx.get(), &AppContext::initiateTransaction, this, &SendWidget::onInitiateTransaction); connect(m_wallet, &Wallet::initiateTransaction, this, &SendWidget::onInitiateTransaction);
connect(m_ctx.get(), &AppContext::endTransaction, this, &SendWidget::onEndTransaction); connect(m_wallet, &Wallet::endTransaction, this, &SendWidget::onEndTransaction);
connect(WalletManager::instance(), &WalletManager::openAliasResolved, this, &SendWidget::onOpenAliasResolved); connect(WalletManager::instance(), &WalletManager::openAliasResolved, this, &SendWidget::onOpenAliasResolved);
@ -143,14 +145,14 @@ void SendWidget::scanClicked() {
} }
void SendWidget::sendClicked() { void SendWidget::sendClicked() {
if (!m_ctx->wallet->isConnected()) { if (!m_wallet->isConnected()) {
QMessageBox::warning(this, "Error", "Unable to create transaction:\n\n" QMessageBox::warning(this, "Error", "Unable to create transaction:\n\n"
"Wallet is not connected to a node.\n" "Wallet is not connected to a node.\n"
"Go to File -> Settings -> Node to manually connect to a node."); "Go to File -> Settings -> Node to manually connect to a node.");
return; return;
} }
if (!m_ctx->wallet->isSynchronized()) { if (!m_wallet->isSynchronized()) {
QMessageBox::warning(this, "Error", "Wallet is not synchronized, unable to create transaction.\n\n" QMessageBox::warning(this, "Error", "Wallet is not synchronized, unable to create transaction.\n\n"
"Wait for synchronization to complete."); "Wait for synchronization to complete.");
return; return;
@ -189,7 +191,7 @@ void SendWidget::sendClicked() {
amounts.push_back(output.amount); amounts.push_back(output.amount);
} }
m_ctx->onCreateTransactionMultiDest(addresses, amounts, description); m_wallet->createTransactionMultiDest(addresses, amounts, description);
return; return;
} }
@ -207,7 +209,7 @@ void SendWidget::sendClicked() {
amount = WalletManager::amountFromDouble(this->conversionAmount()); amount = WalletManager::amountFromDouble(this->conversionAmount());
} }
m_ctx->onCreateTransaction(recipient, amount, description, sendAll); m_wallet->createTransaction(recipient, amount, description, sendAll);
} }
void SendWidget::aliasClicked() { void SendWidget::aliasClicked() {
@ -347,7 +349,7 @@ void SendWidget::setWebsocketEnabled(bool enabled) {
void SendWidget::onDataPasted(const QString &data) { void SendWidget::onDataPasted(const QString &data) {
if (!data.isEmpty()) { 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")) { if (!uriData.contains("error")) {
ui->lineAddress->setText(uriData.value("address").toString()); ui->lineAddress->setText(uriData.value("address").toString());
ui->lineDescription->setText(uriData.value("tx_description").toString()); ui->lineDescription->setText(uriData.value("tx_description").toString());

View file

@ -6,7 +6,7 @@
#include <QWidget> #include <QWidget>
#include "appcontext.h" #include "libwalletqt/Wallet.h"
#include "widgets/CCSWidget.h" #include "widgets/CCSWidget.h"
namespace Ui { namespace Ui {
@ -18,7 +18,7 @@ class SendWidget : public QWidget
Q_OBJECT Q_OBJECT
public: 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(const QString &address, const QString &description, double amount = 0);
void fill(double amount); void fill(double amount);
void clearFields(); void clearFields();
@ -57,7 +57,7 @@ private:
double conversionAmount(); double conversionAmount();
QScopedPointer<Ui::SendWidget> ui; QScopedPointer<Ui::SendWidget> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
bool m_sendDisabled = false; bool m_sendDisabled = false;
}; };

View file

@ -9,14 +9,16 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include "libwalletqt/WalletManager.h"
#include "utils/AppData.h"
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/WebsocketNotifier.h" #include "utils/WebsocketNotifier.h"
#include "widgets/NetworkProxyWidget.h" #include "widgets/NetworkProxyWidget.h"
Settings::Settings(QSharedPointer<AppContext> ctx, QWidget *parent) Settings::Settings(Nodes *nodes, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::Settings) , ui(new Ui::Settings)
, m_ctx(std::move(ctx)) , m_nodes(nodes)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -150,12 +152,12 @@ void Settings::setupAppearanceTab() {
void Settings::setupNetworkTab() { void Settings::setupNetworkTab() {
// Node // Node
if (m_ctx) { if (m_nodes) {
ui->nodeWidget->setupUI(m_ctx->nodes); ui->nodeWidget->setupUI(m_nodes);
connect(ui->nodeWidget, &NodeWidget::nodeSourceChanged, m_ctx->nodes, &Nodes::onNodeSourceChanged); connect(ui->nodeWidget, &NodeWidget::nodeSourceChanged, m_nodes, &Nodes::onNodeSourceChanged);
connect(ui->nodeWidget, &NodeWidget::connectToNode, m_ctx->nodes, QOverload<const FeatherNode&>::of(&Nodes::connectToNode)); connect(ui->nodeWidget, &NodeWidget::connectToNode, m_nodes, QOverload<const FeatherNode&>::of(&Nodes::connectToNode));
} else { } else {
m_nodes = new Nodes(this); m_nodes = new Nodes(this, nullptr);
ui->nodeWidget->setupUI(m_nodes); ui->nodeWidget->setupUI(m_nodes);
ui->nodeWidget->setCanConnect(false); ui->nodeWidget->setCanConnect(false);
} }

View file

@ -9,7 +9,6 @@
#include <QDialog> #include <QDialog>
#include <QSettings> #include <QSettings>
#include "appcontext.h"
#include "widgets/NodeWidget.h" #include "widgets/NodeWidget.h"
namespace Ui { namespace Ui {
@ -21,7 +20,7 @@ class Settings : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit Settings(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit Settings(Nodes *nodes, QWidget *parent = nullptr);
~Settings() override; ~Settings() override;
void showNetworkProxyTab(); void showNetworkProxyTab();
@ -67,7 +66,6 @@ private:
void enableWebsocket(bool enabled); void enableWebsocket(bool enabled);
QScopedPointer<Ui::Settings> ui; QScopedPointer<Ui::Settings> ui;
QSharedPointer<AppContext> m_ctx;
Nodes *m_nodes = nullptr; Nodes *m_nodes = nullptr;
QStringList m_themes{"Native", "QDarkStyle", "Breeze/Dark", "Breeze/Light"}; QStringList m_themes{"Native", "QDarkStyle", "Breeze/Dark", "Breeze/Light"};

View file

@ -13,11 +13,13 @@
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/NetworkManager.h" #include "utils/NetworkManager.h"
#include "utils/os/tails.h" #include "utils/os/tails.h"
#include "utils/os/whonix.h"
#include "utils/TorManager.h" #include "utils/TorManager.h"
#include "utils/WebsocketNotifier.h" #include "utils/WebsocketNotifier.h"
WindowManager::WindowManager(EventFilter *eventFilter) WindowManager::WindowManager(QObject *parent, EventFilter *eventFilter)
: eventFilter(eventFilter) : QObject(parent)
, eventFilter(eventFilter)
{ {
m_walletManager = WalletManager::instance(); m_walletManager = WalletManager::instance();
m_splashDialog = new SplashDialog; m_splashDialog = new SplashDialog;
@ -83,12 +85,15 @@ void WindowManager::close() {
} }
void WindowManager::closeWindow(MainWindow *window) { void WindowManager::closeWindow(MainWindow *window) {
qDebug() << "closing Window";
m_windows.removeOne(window); m_windows.removeOne(window);
// Move Wallet to a different thread for cleanup so it doesn't block GUI thread // Move Wallet to a different thread for cleanup, so it doesn't block GUI thread
window->m_ctx->wallet->moveToThread(m_cleanupThread); window->m_wallet->moveToThread(m_cleanupThread);
m_cleanupThread->start(); m_cleanupThread->start();
window->m_ctx->wallet->deleteLater(); window->m_wallet->deleteLater();
window->deleteLater();
} }
void WindowManager::restartApplication(const QString &binaryFilename) { void WindowManager::restartApplication(const QString &binaryFilename) {
@ -138,8 +143,8 @@ void WindowManager::raise() {
// ######################## SETTINGS ######################## // ######################## SETTINGS ########################
void WindowManager::showSettings(QSharedPointer<AppContext> ctx, QWidget *parent, bool showProxyTab) { void WindowManager::showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab) {
Settings settings{ctx, parent}; Settings settings{nodes, parent};
connect(&settings, &Settings::preferredFiatCurrencyChanged, [this]{ connect(&settings, &Settings::preferredFiatCurrencyChanged, [this]{
for (const auto &window : m_windows) { 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.seed", seed.mnemonic.join(" "));
wallet->setCacheAttribute("feather.seedoffset", seedOffset); wallet->setCacheAttribute("feather.seedoffset", seedOffset);
wallet->setNewWallet();
this->onWalletOpened(wallet); this->onWalletOpened(wallet);
} }
@ -359,6 +365,7 @@ void WindowManager::onWalletCreated(Wallet *wallet) {
// Currently only called when a wallet is created from device. // Currently only called when a wallet is created from device.
auto state = wallet->status(); auto state = wallet->status();
if (state != Wallet::Status_Ok) { if (state != Wallet::Status_Ok) {
wallet->setNewWallet();
qDebug() << Q_FUNC_INFO << QString("Wallet open error: %1").arg(wallet->errorString()); qDebug() << Q_FUNC_INFO << QString("Wallet open error: %1").arg(wallet->errorString());
this->displayWalletErrorMessage(wallet->errorString()); this->displayWalletErrorMessage(wallet->errorString());
m_splashDialog->hide(); m_splashDialog->hide();

View file

@ -10,6 +10,7 @@
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
#include "MainWindow.h" #include "MainWindow.h"
#include "utils/nodes.h"
#include "wizard/WalletWizard.h" #include "wizard/WalletWizard.h"
class MainWindow; class MainWindow;
@ -17,7 +18,7 @@ class WindowManager : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit WindowManager(EventFilter *eventFilter); explicit WindowManager(QObject *parent, EventFilter *eventFilter);
~WindowManager() override; ~WindowManager() override;
void wizardOpenWallet(); void wizardOpenWallet();
@ -27,7 +28,7 @@ public:
void restartApplication(const QString &binaryFilename); void restartApplication(const QString &binaryFilename);
void raise(); void raise();
void showSettings(QSharedPointer<AppContext> ctx, QWidget *parent, bool showProxyTab = false); void showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab = false);
EventFilter *eventFilter; EventFilter *eventFilter;

View file

@ -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();
}
}

View file

@ -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

BIN
src/assets/tor2/tor Executable file

Binary file not shown.

View file

@ -7,23 +7,25 @@
#include <QMenu> #include <QMenu>
#include "libwalletqt/SubaddressAccount.h" #include "libwalletqt/SubaddressAccount.h"
#include "libwalletqt/WalletManager.h"
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/Utils.h"
AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWidget *parent) AccountSwitcherDialog::AccountSwitcherDialog(Wallet *wallet, QWidget *parent)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::AccountSwitcherDialog) , ui(new Ui::AccountSwitcherDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_model(m_ctx->wallet->subaddressAccountModel()) , m_model(wallet->subaddressAccountModel())
, m_proxyModel(new SubaddressAccountProxyModel(this)) , m_proxyModel(new SubaddressAccountProxyModel(this))
{ {
ui->setupUi(this); ui->setupUi(this);
m_ctx->wallet->subaddressAccount()->refresh(); m_wallet->subaddressAccount()->refresh();
m_proxyModel->setSourceModel(m_model); m_proxyModel->setSourceModel(m_model);
ui->label_totalBalance->setFont(ModelUtils::getMonospaceFont()); 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); this->setWindowModality(Qt::WindowModal);
@ -43,12 +45,12 @@ AccountSwitcherDialog::AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWi
connect(ui->accounts, &QTreeView::customContextMenuRequested, this, &AccountSwitcherDialog::showContextMenu); connect(ui->accounts, &QTreeView::customContextMenuRequested, this, &AccountSwitcherDialog::showContextMenu);
connect(ui->btn_newAccount, &QPushButton::clicked, [this]{ connect(ui->btn_newAccount, &QPushButton::clicked, [this]{
m_ctx->wallet->addSubaddressAccount("New account"); m_wallet->addSubaddressAccount("New account");
m_ctx->wallet->subaddressAccount()->refresh(); m_wallet->subaddressAccount()->refresh();
}); });
connect(m_ctx->wallet, &Wallet::currentSubaddressAccountChanged, this, &AccountSwitcherDialog::updateSelection); connect(m_wallet, &Wallet::currentSubaddressAccountChanged, this, &AccountSwitcherDialog::updateSelection);
connect(m_ctx->wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection); connect(m_wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection);
this->updateSelection(); this->updateSelection();
} }
@ -59,7 +61,7 @@ void AccountSwitcherDialog::switchAccount() {
return; return;
} }
m_ctx->wallet->switchSubaddressAccount(row->getRowId()); m_wallet->switchSubaddressAccount(row->getRowId());
} }
void AccountSwitcherDialog::copyLabel() { void AccountSwitcherDialog::copyLabel() {
@ -81,13 +83,13 @@ void AccountSwitcherDialog::copyBalance() {
} }
void AccountSwitcherDialog::editLabel() { 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->setCurrentIndex(index);
ui->accounts->edit(index); ui->accounts->edit(index);
} }
void AccountSwitcherDialog::updateSelection() { 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); ui->accounts->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
} }
@ -108,7 +110,7 @@ void AccountSwitcherDialog::showContextMenu(const QPoint &point) {
Monero::SubaddressAccountRow* AccountSwitcherDialog::currentEntry() { Monero::SubaddressAccountRow* AccountSwitcherDialog::currentEntry() {
QModelIndex index = m_proxyModel->mapToSource(ui->accounts->currentIndex()); QModelIndex index = m_proxyModel->mapToSource(ui->accounts->currentIndex());
return m_ctx->wallet->subaddressAccountModel()->entryFromIndex(index); return m_wallet->subaddressAccountModel()->entryFromIndex(index);
} }
AccountSwitcherDialog::~AccountSwitcherDialog() = default; AccountSwitcherDialog::~AccountSwitcherDialog() = default;

View file

@ -6,7 +6,7 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h" #include "libwalletqt/Wallet.h"
#include "components.h" #include "components.h"
#include "model/SubaddressAccountModel.h" #include "model/SubaddressAccountModel.h"
@ -19,7 +19,7 @@ class AccountSwitcherDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit AccountSwitcherDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit AccountSwitcherDialog(Wallet *wallet, QWidget *parent = nullptr);
~AccountSwitcherDialog() override; ~AccountSwitcherDialog() override;
private slots: private slots:
@ -35,7 +35,7 @@ private:
Monero::SubaddressAccountRow* currentEntry(); Monero::SubaddressAccountRow* currentEntry();
QScopedPointer<Ui::AccountSwitcherDialog> ui; QScopedPointer<Ui::AccountSwitcherDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
SubaddressAccountModel *m_model; SubaddressAccountModel *m_model;
SubaddressAccountProxyModel *m_proxyModel; SubaddressAccountProxyModel *m_proxyModel;
}; };

View file

@ -5,15 +5,18 @@
#include "ui_DebugInfoDialog.h" #include "ui_DebugInfoDialog.h"
#include "config-feather.h" #include "config-feather.h"
#include "utils/AppData.h"
#include "utils/os/tails.h" #include "utils/os/tails.h"
#include "utils/os/whonix.h"
#include "utils/TorManager.h" #include "utils/TorManager.h"
#include "utils/WebsocketClient.h" #include "utils/WebsocketClient.h"
#include "utils/WebsocketNotifier.h" #include "utils/WebsocketNotifier.h"
DebugInfoDialog::DebugInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent) DebugInfoDialog::DebugInfoDialog(Wallet *wallet, Nodes *nodes, QWidget *parent)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::DebugInfoDialog) , ui(new Ui::DebugInfoDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_nodes(nodes)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -47,16 +50,16 @@ void DebugInfoDialog::updateInfo() {
ui->label_featherVersion->setText(QString("%1-%2").arg(FEATHER_VERSION, FEATHER_COMMIT)); ui->label_featherVersion->setText(QString("%1-%2").arg(FEATHER_VERSION, FEATHER_COMMIT));
ui->label_walletHeight->setText(QString::number(m_ctx->wallet->blockChainHeight())); ui->label_walletHeight->setText(QString::number(m_wallet->blockChainHeight()));
ui->label_daemonHeight->setText(QString::number(m_ctx->wallet->daemonBlockChainHeight())); ui->label_daemonHeight->setText(QString::number(m_wallet->daemonBlockChainHeight()));
ui->label_targetHeight->setText(QString::number(m_ctx->wallet->daemonBlockChainTargetHeight())); ui->label_targetHeight->setText(QString::number(m_wallet->daemonBlockChainTargetHeight()));
QDateTime restoreDate = appData()->restoreHeights[constants::networkType]->heightToDate(m_ctx->wallet->getWalletCreationHeight()); QDateTime restoreDate = appData()->restoreHeights[constants::networkType]->heightToDate(m_wallet->getWalletCreationHeight());
ui->label_restoreHeight->setText(QString("%1 (%2)").arg(QString::number(m_ctx->wallet->getWalletCreationHeight()), restoreDate.toString("yyyy-MM-dd"))); ui->label_restoreHeight->setText(QString("%1 (%2)").arg(QString::number(m_wallet->getWalletCreationHeight()), restoreDate.toString("yyyy-MM-dd")));
ui->label_synchronized->setText(m_ctx->wallet->isSynchronized() ? "True" : "False"); 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_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"); QString websocketStatus = Utils::QtEnumToString(websocketNotifier()->websocketClient.webSocket.state()).remove("State");
if (config()->get(Config::disableWebsocket).toBool()) { if (config()->get(Config::disableWebsocket).toBool()) {
websocketStatus = "Disabled"; websocketStatus = "Disabled";
@ -66,16 +69,16 @@ void DebugInfoDialog::updateInfo() {
ui->label_torLevel->setText(config()->get(Config::torPrivacyLevel).toString()); ui->label_torLevel->setText(config()->get(Config::torPrivacyLevel).toString());
QString seedType = [this](){ QString seedType = [this](){
if (m_ctx->wallet->isHwBacked()) if (m_wallet->isHwBacked())
return QString("Hardware"); return QString("Hardware");
return QString("%1 word").arg(m_ctx->wallet->seedLength()); return QString("%1 word").arg(m_wallet->seedLength());
}(); }();
QString deviceType = [this](){ QString deviceType = [this](){
if (m_ctx->wallet->isHwBacked()) { if (m_wallet->isHwBacked()) {
if (m_ctx->wallet->isLedger()) if (m_wallet->isLedger())
return "Ledger"; return "Ledger";
else if (m_ctx->wallet->isTrezor()) else if (m_wallet->isTrezor())
return "Trezor"; return "Trezor";
else else
return "Unknown"; 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()) { if (config()->get(Config::offlineMode).toBool()) {
networkType += " (offline)"; networkType += " (offline)";
} }
ui->label_netType->setText(networkType); ui->label_netType->setText(networkType);
ui->label_seedType->setText(seedType); ui->label_seedType->setText(seedType);
ui->label_deviceType->setText(deviceType); ui->label_deviceType->setText(deviceType);
ui->label_viewOnly->setText(m_ctx->wallet->viewOnly() ? "True" : "False"); ui->label_viewOnly->setText(m_wallet->viewOnly() ? "True" : "False");
ui->label_primaryOnly->setText(m_ctx->wallet->balance(0) == m_ctx->wallet->balanceAll() ? "True" : "False"); ui->label_primaryOnly->setText(m_wallet->balance(0) == m_wallet->balanceAll() ? "True" : "False");
QString os = QSysInfo::prettyProductName(); QString os = QSysInfo::prettyProductName();
if (TailsOS::detect()) { if (TailsOS::detect()) {

View file

@ -6,9 +6,9 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/Wallet.h" #include "libwalletqt/Wallet.h"
#include "utils/nodes.h"
namespace Ui { namespace Ui {
class DebugInfoDialog; class DebugInfoDialog;
@ -19,7 +19,7 @@ class DebugInfoDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit DebugInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit DebugInfoDialog(Wallet *wallet, Nodes *nodes, QWidget *parent = nullptr);
~DebugInfoDialog() override; ~DebugInfoDialog() override;
private: private:
@ -28,7 +28,8 @@ private:
void updateInfo(); void updateInfo();
QScopedPointer<Ui::DebugInfoDialog> ui; QScopedPointer<Ui::DebugInfoDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
Nodes *m_nodes;
QTimer m_updateTimer; QTimer m_updateTimer;
}; };

View file

@ -4,7 +4,7 @@
#include "KeysDialog.h" #include "KeysDialog.h"
#include "ui_KeysDialog.h" #include "ui_KeysDialog.h"
KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent) KeysDialog::KeysDialog(Wallet *wallet, QWidget *parent)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::KeysDialog) , ui(new Ui::KeysDialog)
{ {
@ -12,12 +12,12 @@ KeysDialog::KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent)
QString unavailable = "Unavailable: Key is stored on hardware device"; QString unavailable = "Unavailable: Key is stored on hardware device";
ui->label_restoreHeight->setText(QString::number(ctx->wallet->getWalletCreationHeight())); ui->label_restoreHeight->setText(QString::number(wallet->getWalletCreationHeight()));
ui->label_primaryAddress->setText(ctx->wallet->address(0, 0)); ui->label_primaryAddress->setText(wallet->address(0, 0));
ui->label_secretSpendKey->setText(ctx->wallet->isHwBacked() ? unavailable : ctx->wallet->getSecretSpendKey()); ui->label_secretSpendKey->setText(wallet->isHwBacked() ? unavailable : wallet->getSecretSpendKey());
ui->label_secretViewKey->setText(ctx->wallet->getSecretViewKey()); ui->label_secretViewKey->setText(wallet->getSecretViewKey());
ui->label_publicSpendKey->setText(ctx->wallet->getPublicSpendKey()); ui->label_publicSpendKey->setText(wallet->getPublicSpendKey());
ui->label_publicViewKey->setText(ctx->wallet->getPublicViewKey()); ui->label_publicViewKey->setText(wallet->getPublicViewKey());
this->adjustSize(); this->adjustSize();
} }

View file

@ -6,8 +6,8 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class KeysDialog; class KeysDialog;
@ -18,7 +18,7 @@ class KeysDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit KeysDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit KeysDialog(Wallet *wallet, QWidget *parent = nullptr);
~KeysDialog() override; ~KeysDialog() override;
private: private:

View file

@ -10,11 +10,12 @@
#include <QRegularExpressionValidator> #include <QRegularExpressionValidator>
#include "WalletManager.h" #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) : WindowModalDialog(parent)
, ui(new Ui::PaymentRequestDialog) , ui(new Ui::PaymentRequestDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_address(std::move(address)) , m_address(std::move(address))
{ {
ui->setupUi(this); ui->setupUi(this);
@ -45,7 +46,7 @@ void PaymentRequestDialog::updatePaymentRequest() {
QString recipient = ui->line_recipient->text(); QString recipient = ui->line_recipient->text();
quint64 amount = WalletManager::amountFromString(ui->line_amountXMR->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->setText(uri);
ui->line_paymentRequestUri->setCursorPosition(0); ui->line_paymentRequestUri->setCursorPosition(0);

View file

@ -6,8 +6,8 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/Wallet.h"
#include "qrcode/QrCode.h" #include "qrcode/QrCode.h"
namespace Ui { namespace Ui {
@ -19,7 +19,7 @@ class PaymentRequestDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit PaymentRequestDialog(QWidget *parent, QSharedPointer<AppContext> ctx, QString address); explicit PaymentRequestDialog(QWidget *parent, Wallet *wallet, QString address);
~PaymentRequestDialog() override; ~PaymentRequestDialog() override;
private slots: private slots:
@ -30,7 +30,7 @@ private slots:
private: private:
QScopedPointer<Ui::PaymentRequestDialog> ui; QScopedPointer<Ui::PaymentRequestDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
QString m_address; QString m_address;
QrCode *m_qrCode; QrCode *m_qrCode;
}; };

View file

@ -6,26 +6,26 @@
#include "constants.h" #include "constants.h"
SeedDialog::SeedDialog(QSharedPointer<AppContext> ctx, QWidget *parent) SeedDialog::SeedDialog(Wallet *wallet, QWidget *parent)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::SeedDialog) , ui(new Ui::SeedDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->label_seedIcon->setPixmap(QPixmap(":/assets/images/seed.png").scaledToWidth(64, Qt::SmoothTransformation)); 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"; 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 seedOffset = m_wallet->getCacheAttribute("feather.seedoffset");
QString seed = m_ctx->wallet->getCacheAttribute("feather.seed"); QString seed = m_wallet->getCacheAttribute("feather.seed");
auto seedLength = m_ctx->wallet->seedLength(); 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) { if (seedLength >= 24) {
ui->check_toggleSeedType->hide(); ui->check_toggleSeedType->hide();

View file

@ -6,8 +6,8 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class SeedDialog; class SeedDialog;
@ -18,14 +18,14 @@ class SeedDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit SeedDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit SeedDialog(Wallet *wallet, QWidget *parent = nullptr);
~SeedDialog() override; ~SeedDialog() override;
private: private:
void setSeed(const QString &seed); void setSeed(const QString &seed);
QScopedPointer<Ui::SeedDialog> ui; QScopedPointer<Ui::SeedDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
}; };

View file

@ -8,14 +8,14 @@
#include "utils/NetworkManager.h" #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) : WindowModalDialog(parent)
, ui(new Ui::TxBroadcastDialog) , ui(new Ui::TxBroadcastDialog)
, m_ctx(std::move(ctx)) , m_nodes(nodes)
{ {
ui->setupUi(this); ui->setupUi(this);
auto node = m_ctx->nodes->connection(); auto node = m_nodes->connection();
m_rpc = new DaemonRpc(this, node.toAddress()); m_rpc = new DaemonRpc(this, node.toAddress());
connect(ui->btn_Broadcast, &QPushButton::clicked, this, &TxBroadcastDialog::broadcastTx); connect(ui->btn_Broadcast, &QPushButton::clicked, this, &TxBroadcastDialog::broadcastTx);
@ -33,7 +33,7 @@ TxBroadcastDialog::TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext>
void TxBroadcastDialog::broadcastTx() { void TxBroadcastDialog::broadcastTx() {
QString tx = ui->transaction->toPlainText(); 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->setDaemonAddress(node.toURL());
m_rpc->sendRawTransaction(tx); m_rpc->sendRawTransaction(tx);

View file

@ -6,9 +6,9 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "utils/daemonrpc.h" #include "utils/daemonrpc.h"
#include "utils/nodes.h"
namespace Ui { namespace Ui {
class TxBroadcastDialog; class TxBroadcastDialog;
@ -19,7 +19,7 @@ class TxBroadcastDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TxBroadcastDialog(QWidget *parent, QSharedPointer<AppContext> ctx, const QString &transactionHex = ""); explicit TxBroadcastDialog(QWidget *parent, Nodes *nodes, const QString &transactionHex = "");
~TxBroadcastDialog() override; ~TxBroadcastDialog() override;
private slots: private slots:
@ -28,7 +28,7 @@ private slots:
private: private:
QScopedPointer<Ui::TxBroadcastDialog> ui; QScopedPointer<Ui::TxBroadcastDialog> ui;
QSharedPointer<AppContext> m_ctx; Nodes *m_nodes;
DaemonRpc *m_rpc; DaemonRpc *m_rpc;
}; };

View file

@ -11,13 +11,17 @@
#include "dialog/QrCodeDialog.h" #include "dialog/QrCodeDialog.h"
#include "libwalletqt/Input.h" #include "libwalletqt/Input.h"
#include "libwalletqt/Transfer.h" #include "libwalletqt/Transfer.h"
#include "libwalletqt/WalletManager.h"
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
#include "qrcode/QrCode.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) : WindowModalDialog(parent)
, ui(new Ui::TxConfAdvDialog) , ui(new Ui::TxConfAdvDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_exportUnsignedMenu(new QMenu(this)) , m_exportUnsignedMenu(new QMenu(this))
, m_exportSignedMenu(new QMenu(this)) , m_exportSignedMenu(new QMenu(this))
, m_exportTxKeyMenu(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 PendingTransactionInfo *ptx = m_tx->transaction(0); //Todo: support split transactions
// TODO: implement hasTxKey() // 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(); ui->btn_exportTxKey->hide();
} }
@ -148,7 +152,7 @@ void TxConfAdvDialog::setupConstructionData(ConstructionInfo *ci) {
for (const auto& o: outputs) { for (const auto& o: outputs) {
auto address = o->address(); auto address = o->address();
auto amount = WalletManager::displayAmount(o->amount()); 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(address, Utils::addressTextFormat(index, o->amount()));
cursor.insertText(QString(" %1").arg(amount), QTextCharFormat()); cursor.insertText(QString(" %1").arg(amount), QTextCharFormat());
cursor.insertBlock(); cursor.insertBlock();
@ -205,7 +209,7 @@ void TxConfAdvDialog::signedCopy() {
} }
void TxConfAdvDialog::txKeyCopy() { 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"); QMessageBox::warning(this, "Unable to get tx private key", "Unable to get tx secret key: wallet is backed by hardware device");
return; return;
} }
@ -218,15 +222,15 @@ void TxConfAdvDialog::signedQrCode() {
void TxConfAdvDialog::broadcastTransaction() { void TxConfAdvDialog::broadcastTransaction() {
if (m_tx == nullptr) return; 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(); QDialog::accept();
} }
void TxConfAdvDialog::closeDialog() { void TxConfAdvDialog::closeDialog() {
if (m_tx != nullptr) if (m_tx != nullptr)
m_ctx->wallet->disposeTransaction(m_tx); m_wallet->disposeTransaction(m_tx);
if (m_utx != nullptr) if (m_utx != nullptr)
m_ctx->wallet->disposeTransaction(m_utx); m_wallet->disposeTransaction(m_utx);
QDialog::reject(); QDialog::reject();
} }

View file

@ -9,9 +9,9 @@
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QTextCharFormat> #include <QTextCharFormat>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/PendingTransaction.h" #include "libwalletqt/PendingTransaction.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class TxConfAdvDialog; class TxConfAdvDialog;
@ -22,7 +22,7 @@ class TxConfAdvDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TxConfAdvDialog(QSharedPointer<AppContext> ctx, const QString &description, QWidget *parent = nullptr); explicit TxConfAdvDialog(Wallet *wallet, const QString &description, QWidget *parent = nullptr);
~TxConfAdvDialog() override; ~TxConfAdvDialog() override;
void setTransaction(PendingTransaction *tx, bool isSigned = true); // #TODO: have libwallet return a UnsignedTransaction, this is just dumb void setTransaction(PendingTransaction *tx, bool isSigned = true); // #TODO: have libwallet return a UnsignedTransaction, this is just dumb
@ -46,7 +46,7 @@ private:
void txKeyCopy(); void txKeyCopy();
QScopedPointer<Ui::TxConfAdvDialog> ui; QScopedPointer<Ui::TxConfAdvDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
PendingTransaction *m_tx = nullptr; PendingTransaction *m_tx = nullptr;
UnsignedTransaction *m_utx = nullptr; UnsignedTransaction *m_utx = nullptr;
QMenu *m_exportUnsignedMenu; QMenu *m_exportUnsignedMenu;

View file

@ -11,11 +11,12 @@
#include "TxConfAdvDialog.h" #include "TxConfAdvDialog.h"
#include "utils/AppData.h" #include "utils/AppData.h"
#include "utils/ColorScheme.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) : WindowModalDialog(parent)
, ui(new Ui::TxConfDialog) , ui(new Ui::TxConfDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_tx(tx) , m_tx(tx)
, m_address(address) , m_address(address)
, m_description(description) , 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_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)); 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; QString addressExtra;
ui->label_address->setText(ModelUtils::displayAddress(address, 2)); ui->label_address->setText(ModelUtils::displayAddress(address, 2));

View file

@ -6,10 +6,10 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/PendingTransaction.h" #include "libwalletqt/PendingTransaction.h"
#include "libwalletqt/WalletManager.h" #include "libwalletqt/WalletManager.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class TxConfDialog; class TxConfDialog;
@ -20,7 +20,7 @@ class TxConfDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: 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; ~TxConfDialog() override;
bool showAdvanced = false; bool showAdvanced = false;
@ -29,7 +29,7 @@ private:
void setShowAdvanced(); void setShowAdvanced();
QScopedPointer<Ui::TxConfDialog> ui; QScopedPointer<Ui::TxConfDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
PendingTransaction *m_tx; PendingTransaction *m_tx;
QString m_address; QString m_address;
QString m_description; QString m_description;

View file

@ -8,10 +8,10 @@
#include "utils/NetworkManager.h" #include "utils/NetworkManager.h"
TxImportDialog::TxImportDialog(QWidget *parent, QSharedPointer<AppContext> ctx) TxImportDialog::TxImportDialog(QWidget *parent, Wallet *wallet)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::TxImportDialog) , ui(new Ui::TxImportDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -23,15 +23,15 @@ TxImportDialog::TxImportDialog(QWidget *parent, QSharedPointer<AppContext> ctx)
void TxImportDialog::onImport() { void TxImportDialog::onImport() {
QString txid = ui->line_txid->text(); 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. " QMessageBox::warning(this, "Warning", "This transaction already exists in the wallet. "
"If you can't find it in your history, " "If you can't find it in your history, "
"check if it belongs to a different account (Wallet -> Account)"); "check if it belongs to a different account (Wallet -> Account)");
return; return;
} }
if (m_ctx->wallet->importTransaction(txid)) { if (m_wallet->importTransaction(txid)) {
if (!m_ctx->wallet->haveTransaction(txid)) { if (!m_wallet->haveTransaction(txid)) {
QMessageBox::warning(this, "Import transaction", "This transaction does not belong to this wallet."); QMessageBox::warning(this, "Import transaction", "This transaction does not belong to this wallet.");
return; return;
} }
@ -39,7 +39,7 @@ void TxImportDialog::onImport() {
} else { } else {
QMessageBox::warning(this, "Import transaction", "Transaction import failed."); QMessageBox::warning(this, "Import transaction", "Transaction import failed.");
} }
m_ctx->refreshModels(); m_wallet->refreshModels();
} }
TxImportDialog::~TxImportDialog() = default; TxImportDialog::~TxImportDialog() = default;

View file

@ -6,9 +6,9 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "utils/daemonrpc.h" #include "utils/daemonrpc.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class TxImportDialog; class TxImportDialog;
@ -19,7 +19,7 @@ class TxImportDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TxImportDialog(QWidget *parent, QSharedPointer<AppContext> ctx); explicit TxImportDialog(QWidget *parent, Wallet *wallet);
~TxImportDialog() override; ~TxImportDialog() override;
private slots: private slots:
@ -27,7 +27,7 @@ private slots:
private: private:
QScopedPointer<Ui::TxImportDialog> ui; QScopedPointer<Ui::TxImportDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
}; };

View file

@ -7,7 +7,6 @@
#include <QMessageBox> #include <QMessageBox>
#include <QScrollBar> #include <QScrollBar>
#include "appcontext.h"
#include "config.h" #include "config.h"
#include "constants.h" #include "constants.h"
#include "libwalletqt/Coins.h" #include "libwalletqt/Coins.h"
@ -19,12 +18,12 @@
#include "Utils.h" #include "Utils.h"
#include "utils/Icons.h" #include "utils/Icons.h"
TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txInfo, QWidget *parent) TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::TxInfoDialog) , ui(new Ui::TxInfoDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_txInfo(txInfo) , m_txInfo(txInfo)
, m_txProofDialog(new TxProofDialog(this, m_ctx, txInfo)) , m_txProofDialog(new TxProofDialog(this, wallet, txInfo))
{ {
ui->setupUi(this); 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_CopyTxKey, &QPushButton::clicked, this, &TxInfoDialog::copyTxKey);
connect(ui->btn_createTxProof, &QPushButton::clicked, this, &TxInfoDialog::createTxProof); 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); this->setData(txInfo);
@ -79,7 +78,7 @@ TxInfoDialog::TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txIn
for (const auto& transfer : transfers) { for (const auto& transfer : transfers) {
auto address = transfer->address(); auto address = transfer->address();
auto amount = WalletManager::displayAmount(transfer->amount()); 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(address, Utils::addressTextFormat(index, transfer->amount()));
cursor.insertText(QString(" %1").arg(amount), QTextCharFormat()); cursor.insertText(QString(" %1").arg(amount), QTextCharFormat());
cursor.insertBlock(); cursor.insertBlock();
@ -151,7 +150,7 @@ void TxInfoDialog::setData(TransactionInfo *tx) {
} }
void TxInfoDialog::updateData() { void TxInfoDialog::updateData() {
TransactionInfo *tx = m_ctx->wallet->history()->transaction(m_txid); TransactionInfo *tx = m_wallet->history()->transaction(m_txid);
if (!tx) return; if (!tx) return;
this->setData(tx); this->setData(tx);
} }
@ -161,12 +160,12 @@ void TxInfoDialog::copyTxID() {
} }
void TxInfoDialog::copyTxKey() { 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"); QMessageBox::warning(this, "Unable to get tx private key", "Unable to get tx secret key: wallet is backed by hardware device");
return; 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(); QString txKey = map.value("tx_key").toString();
if (txKey.isEmpty()) { if (txKey.isEmpty()) {
QMessageBox::warning(this, "Unable to copy transaction key", "Transaction key unknown"); QMessageBox::warning(this, "Unable to copy transaction key", "Transaction key unknown");

View file

@ -9,7 +9,6 @@
#include <QTextEdit> #include <QTextEdit>
#include <QSvgWidget> #include <QSvgWidget>
#include "appcontext.h"
#include "dialog/TxProofDialog.h" #include "dialog/TxProofDialog.h"
namespace Ui { namespace Ui {
@ -21,7 +20,7 @@ class TxInfoDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TxInfoDialog(QSharedPointer<AppContext> ctx, TransactionInfo *txInfo, QWidget *parent = nullptr); explicit TxInfoDialog(Wallet *wallet, TransactionInfo *txInfo, QWidget *parent = nullptr);
~TxInfoDialog() override; ~TxInfoDialog() override;
signals: signals:
@ -37,7 +36,7 @@ private:
void viewOnBlockExplorer(); void viewOnBlockExplorer();
QScopedPointer<Ui::TxInfoDialog> ui; QScopedPointer<Ui::TxInfoDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
TransactionInfo *m_txInfo; TransactionInfo *m_txInfo;
TxProofDialog *m_txProofDialog; TxProofDialog *m_txProofDialog;
QString m_txid; QString m_txid;

View file

@ -10,10 +10,10 @@
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/Utils.h" #include "utils/Utils.h"
TxProofDialog::TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, TransactionInfo *txInfo) TxProofDialog::TxProofDialog(QWidget *parent, Wallet *wallet, TransactionInfo *txInfo)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::TxProofDialog) , ui(new Ui::TxProofDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -26,7 +26,7 @@ TxProofDialog::TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, Tr
} }
for (auto const &s: txInfo->subaddrIndex()) { 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 // 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() { void TxProofDialog::getTxKey() {
if (!m_txKey.isEmpty()) return; 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(); m_txKey = map.value("tx_key").toString();
}); });
} }
@ -75,7 +75,7 @@ void TxProofDialog::selectSpendProof() {
return; return;
} }
if (m_ctx->wallet->isHwBacked()) { if (m_wallet->isHwBacked()) {
this->showWarning("SpendProof creation is not supported on this hardware device."); this->showWarning("SpendProof creation is not supported on this hardware device.");
return; return;
} }
@ -150,7 +150,7 @@ void TxProofDialog::showWarning(const QString &message) {
void TxProofDialog::getFormattedProof() { void TxProofDialog::getFormattedProof() {
QString message = ui->message->toPlainText(); QString message = ui->message->toPlainText();
QString address = ui->combo_address->currentText(); 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 nettype = nettype.replace(0, 1, nettype[0].toUpper()); // Capitalize first letter
TxProof proof = this->getProof(); TxProof proof = this->getProof();
@ -231,12 +231,12 @@ TxProof TxProofDialog::getProof() {
TxProof proof = [this, message, address]{ TxProof proof = [this, message, address]{
switch (m_mode) { switch (m_mode) {
case Mode::SpendProof: { case Mode::SpendProof: {
return m_ctx->wallet->getSpendProof(m_txid, message); return m_wallet->getSpendProof(m_txid, message);
} }
case Mode::OutProof: case Mode::OutProof:
case Mode::InProof: case Mode::InProof:
default: { // Todo: split this into separate functions default: { // Todo: split this into separate functions
return m_ctx->wallet->getTxProof(m_txid, address, message); return m_wallet->getTxProof(m_txid, address, message);
} }
} }
}(); }();

View file

@ -6,9 +6,9 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/TransactionInfo.h" #include "libwalletqt/TransactionInfo.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class TxProofDialog; class TxProofDialog;
@ -19,7 +19,7 @@ class TxProofDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit TxProofDialog(QWidget *parent, QSharedPointer<AppContext> ctx, TransactionInfo *txid); explicit TxProofDialog(QWidget *parent, Wallet *wallet, TransactionInfo *txid);
~TxProofDialog() override; ~TxProofDialog() override;
void setTxId(const QString &txid); void setTxId(const QString &txid);
void getTxKey(); void getTxKey();
@ -45,7 +45,7 @@ private:
void showWarning(const QString &message); void showWarning(const QString &message);
QScopedPointer<Ui::TxProofDialog> ui; QScopedPointer<Ui::TxProofDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
QStringList m_OutDestinations; QStringList m_OutDestinations;
QStringList m_InDestinations; QStringList m_InDestinations;

View file

@ -8,21 +8,23 @@
#include <QInputDialog> #include <QInputDialog>
#include <QMessageBox> #include <QMessageBox>
ViewOnlyDialog::ViewOnlyDialog(QSharedPointer<AppContext> ctx, QWidget *parent) #include "utils/Utils.h"
ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::ViewOnlyDialog) , ui(new Ui::ViewOnlyDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->label_restoreHeight->setText(QString::number(m_ctx->wallet->getWalletCreationHeight())); ui->label_restoreHeight->setText(QString::number(m_wallet->getWalletCreationHeight()));
ui->label_primaryAddress->setText(m_ctx->wallet->address(0, 0)); ui->label_primaryAddress->setText(m_wallet->address(0, 0));
ui->label_secretViewKey->setText(m_ctx->wallet->getSecretViewKey()); ui->label_secretViewKey->setText(m_wallet->getSecretViewKey());
connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboard); connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboard);
connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet); 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->setEnabled(false);
ui->btn_Save->setToolTip("Wallet is already view-only"); ui->btn_Save->setToolTip("Wallet is already view-only");
} }
@ -45,7 +47,7 @@ void ViewOnlyDialog::onWriteViewOnlyWallet(){
if((bool)passwordDialog.exec()) if((bool)passwordDialog.exec())
passwd = passwordDialog.textValue(); 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."); QMessageBox::information(this, "Information", "View-only wallet successfully written to disk.");
} }

View file

@ -6,8 +6,8 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class ViewOnlyDialog; class ViewOnlyDialog;
@ -18,7 +18,7 @@ class ViewOnlyDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit ViewOnlyDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit ViewOnlyDialog(Wallet *wallet, QWidget *parent = nullptr);
~ViewOnlyDialog() override; ~ViewOnlyDialog() override;
private slots: private slots:
@ -28,7 +28,7 @@ private:
void copyToClipboard(); void copyToClipboard();
QScopedPointer<Ui::ViewOnlyDialog> ui; QScopedPointer<Ui::ViewOnlyDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
}; };

View file

@ -8,81 +8,81 @@
#include "model/ModelUtils.h" #include "model/ModelUtils.h"
WalletCacheDebugDialog::WalletCacheDebugDialog(QSharedPointer<AppContext> ctx, QWidget *parent) WalletCacheDebugDialog::WalletCacheDebugDialog(Wallet *wallet, QWidget *parent)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::WalletCacheDebugDialog) , ui(new Ui::WalletCacheDebugDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
ui->output->setFont(ModelUtils::getMonospaceFont()); ui->output->setFont(ModelUtils::getMonospaceFont());
connect(ui->m_blockchain, &QRadioButton::pressed, [this]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ 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]{ connect(ui->m_scanned_pool_txs, &QRadioButton::pressed, [this]{
this->setOutput(m_ctx->wallet->printScannedPoolTxs()); this->setOutput(m_wallet->printScannedPoolTxs());
}); });
this->adjustSize(); this->adjustSize();

View file

@ -6,8 +6,8 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class WalletCacheDebugDialog; class WalletCacheDebugDialog;
@ -18,14 +18,14 @@ class WalletCacheDebugDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit WalletCacheDebugDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit WalletCacheDebugDialog(Wallet *wallet, QWidget *parent = nullptr);
~WalletCacheDebugDialog() override; ~WalletCacheDebugDialog() override;
private: private:
void setOutput(const QString &output); void setOutput(const QString &output);
QScopedPointer<Ui::WalletCacheDebugDialog> ui; QScopedPointer<Ui::WalletCacheDebugDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
}; };

View file

@ -6,22 +6,24 @@
#include <QDesktopServices> #include <QDesktopServices>
WalletInfoDialog::WalletInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent) #include "utils/Utils.h"
WalletInfoDialog::WalletInfoDialog(Wallet *wallet, QWidget *parent)
: WindowModalDialog(parent) : WindowModalDialog(parent)
, ui(new Ui::WalletInfoDialog) , ui(new Ui::WalletInfoDialog)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); 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_walletName->setText(QFileInfo(m_wallet->cachePath()).fileName());
ui->label_netType->setText(Utils::QtEnumToString(m_ctx->wallet->nettype())); ui->label_netType->setText(Utils::QtEnumToString(m_wallet->nettype()));
ui->label_seedType->setText(QString("%1 word").arg(m_ctx->wallet->seedLength())); ui->label_seedType->setText(QString("%1 word").arg(m_wallet->seedLength()));
ui->label_viewOnly->setText(m_ctx->wallet->viewOnly() ? "True" : "False"); ui->label_viewOnly->setText(m_wallet->viewOnly() ? "True" : "False");
ui->label_subaddressLookahead->setText(m_ctx->wallet->getSubaddressLookahead()); ui->label_subaddressLookahead->setText(m_wallet->getSubaddressLookahead());
ui->label_keysFile->setText(m_ctx->wallet->keysPath()); ui->label_keysFile->setText(m_wallet->keysPath());
ui->label_cacheFile->setText(m_ctx->wallet->cachePath()); ui->label_cacheFile->setText(m_wallet->cachePath());
ui->label_cacheSize->setText(QString("%1 MB").arg(QString::number(cache.size() / 1e6, 'f', 2))); ui->label_cacheSize->setText(QString("%1 MB").arg(QString::number(cache.size() / 1e6, 'f', 2)));
connect(ui->btn_openWalletDir, &QPushButton::clicked, this, &WalletInfoDialog::openWalletDir); connect(ui->btn_openWalletDir, &QPushButton::clicked, this, &WalletInfoDialog::openWalletDir);
@ -40,7 +42,7 @@ WalletInfoDialog::WalletInfoDialog(QSharedPointer<AppContext> ctx, QWidget *pare
} }
void WalletInfoDialog::openWalletDir() { void WalletInfoDialog::openWalletDir() {
QFileInfo file(m_ctx->wallet->keysPath()); QFileInfo file(m_wallet->keysPath());
QDesktopServices::openUrl(QUrl::fromLocalFile(file.absolutePath())); QDesktopServices::openUrl(QUrl::fromLocalFile(file.absolutePath()));
} }

View file

@ -6,8 +6,8 @@
#include <QDialog> #include <QDialog>
#include "appcontext.h"
#include "components.h" #include "components.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class WalletInfoDialog; class WalletInfoDialog;
@ -18,14 +18,14 @@ class WalletInfoDialog : public WindowModalDialog
Q_OBJECT Q_OBJECT
public: public:
explicit WalletInfoDialog(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit WalletInfoDialog(Wallet *wallet, QWidget *parent = nullptr);
~WalletInfoDialog() override; ~WalletInfoDialog() override;
private: private:
void openWalletDir(); void openWalletDir();
QScopedPointer<Ui::WalletInfoDialog> ui; QScopedPointer<Ui::WalletInfoDialog> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
}; };
#endif //FEATHER_WALLETINFODIALOG_H #endif //FEATHER_WALLETINFODIALOG_H

File diff suppressed because it is too large Load diff

View file

@ -10,9 +10,9 @@
#include <QList> #include <QList>
#include <QtConcurrent/QtConcurrent> #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 "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 "UnsignedTransaction.h"
#include "utils/networktype.h" #include "utils/networktype.h"
#include "PassphraseHelper.h" #include "PassphraseHelper.h"
@ -86,8 +86,7 @@ class Wallet : public QObject, public PassphrasePrompter
Q_OBJECT Q_OBJECT
public: public:
explicit Wallet(QObject *parent = nullptr); explicit Wallet(Monero::Wallet *w, QObject *parent = nullptr);
explicit Wallet(Monero::Wallet *w, QObject * parent = nullptr);
~Wallet() override; ~Wallet() override;
enum Status { enum Status {
@ -109,9 +108,64 @@ public:
Q_ENUM(ConnectionStatus) Q_ENUM(ConnectionStatus)
// ##### Status #####
//! returns last operation's status
Status status() const;
//! return connection status //! return connection status
ConnectionStatus connectionStatus() const; ConnectionStatus connectionStatus() const;
//! returns true if wallet is currently synchronized
bool isSynchronized() const;
//! return true if wallet is connected to a node
bool isConnected() const;
//! returns last operation's error message
QString errorString() const;
//! returns network type of the wallet.
NetworkType::Type nettype() const;
//! returns if view only wallet
bool viewOnly() const;
//! return true if deterministic keys
bool isDeterministic() const;
// ##### Balance #####
//! returns balance
quint64 balance() const;
quint64 balance(quint32 accountIndex) const;
quint64 balanceAll() const;
//! returns unlocked balance
quint64 unlockedBalance() const;
quint64 unlockedBalance(quint32 accountIndex) const;
quint64 unlockedBalanceAll() const;
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);
quint32 numSubaddressAccounts() const;
quint32 numSubaddresses(quint32 accountIndex) const;
void addSubaddress(const QString& label);
QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId);
QString getSubaddressLookahead() const;
// ##### Seed #####
//! returns mnemonic seed //! returns mnemonic seed
QString getSeed(const QString &seedOffset) const; QString getSeed(const QString &seedOffset) const;
@ -123,115 +177,64 @@ public:
//! set seed language //! set seed language
void setSeedLanguage(const QString &lang); void setSeedLanguage(const QString &lang);
//! returns last operation's status //! Get wallet keys
Status status() const; 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());}
//! returns network type of the wallet. // ##### Node connection #####
NetworkType::Type nettype() const;
//! returns true if wallet was ever synchronized
bool synchronized() const;
//! returns true if wallet is currently synchronized
bool isSynchronized() const;
//! return true if wallet is connected to a node
bool isConnected() const;
void setOffline(bool offline) 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();
//! indicates if daemon is trusted //! indicates if daemon is trusted
void setTrustedDaemon(bool arg); void setTrustedDaemon(bool arg);
//! indicates if ssl should be used to connect to daemon //! indicates if ssl should be used to connect to daemon
void setUseSSL(bool ssl); void setUseSSL(bool ssl);
//! returns balance //! Set daemon rpc user/pass
quint64 balance() const; void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
quint64 balance(quint32 accountIndex) const;
quint64 balanceAll() const;
//! returns unlocked balance //! initializes wallet asynchronously
quint64 unlockedBalance() const; void initAsync(const QString &daemonAddress,
quint64 unlockedBalance(quint32 accountIndex) const; bool trustedDaemon = false,
quint64 unlockedBalanceAll() const; quint64 upperTransactionLimit = 0,
const QString &proxyAddress = "");
//! account/address management // ##### Synchronization (Refresh) #####
quint32 currentSubaddressAccount() const; void startRefresh();
void switchSubaddressAccount(quint32 accountIndex); void pauseRefresh();
void addSubaddressAccount(const QString& label);
quint32 numSubaddressAccounts() const;
quint32 numSubaddresses(quint32 accountIndex) const;
void addSubaddress(const QString& label);
QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId);
QString getSubaddressLookahead() const;
//! hw-device backed wallets //! 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 isHwBacked() const;
bool isLedger() const; bool isLedger() const;
bool isTrezor() const; bool isTrezor() const;
bool isDeviceConnected() const;
//! attempt to reconnect to hw-device //! attempt to reconnect to hw-device
bool reconnectDevice(); bool reconnectDevice();
//! returns if view only wallet // Passphrase entry for hardware wallets
bool viewOnly() const; void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
void onWalletPassphraseNeeded(bool on_device) override;
//! return true if deterministic keys
bool isDeterministic() const;
//! refresh daemon blockchain and target height
bool refreshHeights();
// ##### Import / Export #####
//! export/import key images //! export/import key images
bool exportKeyImages(const QString& path, bool all = false); bool exportKeyImages(const QString& path, bool all = false);
bool importKeyImages(const QString& path); bool importKeyImages(const QString& path);
@ -243,6 +246,35 @@ public:
//! import a transaction //! import a transaction
bool importTransaction(const QString& txid); 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 printBlockchain();
QString printTransfers(); QString printTransfers();
QString printPayments(); QString printPayments();
@ -261,78 +293,26 @@ public:
QString printAddressBook(); QString printAddressBook();
QString printScannedPoolTxs(); QString printScannedPoolTxs();
// ##### Transactions #####
void setSelectedInputs(const QStringList &selected);
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);
void onCreateTransactionError(const QString &msg);
void commitTransaction(PendingTransaction *tx, const QString &description="");
//! deletes transaction and frees memory
void disposeTransaction(PendingTransaction * t);
//! deletes unsigned transaction and frees memory
void disposeTransaction(UnsignedTransaction * t);
// ##### Transaction import #####
//! does wallet have txid //! does wallet have txid
bool haveTransaction(const QString &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);
//! creates async transaction
void createTransactionAsync(const QString &dst_addr, const QString &payment_id,
quint64 amount, quint32 mixin_count,
PendingTransaction::Priority priority, const QStringList &preferredInputs);
//! creates multi-destination transaction
PendingTransaction * createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
PendingTransaction::Priority priority, const QStringList &preferredInputs);
//! 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);
//! creates sweep unmixable transaction
PendingTransaction * createSweepUnmixableTransaction();
//! creates async sweep unmixable transaction
void createSweepUnmixableTransactionAsync();
//! Sign a transfer from file //! Sign a transfer from file
UnsignedTransaction * loadTxFile(const QString &fileName); UnsignedTransaction * loadTxFile(const QString &fileName);
@ -345,136 +325,73 @@ public:
//! Submit a transfer from file //! Submit a transfer from file
bool submitTxFile(const QString &fileName) const; bool submitTxFile(const QString &fileName) const;
//! asynchronous transaction commit // ##### Models #####
void commitTransactionAsync(PendingTransaction * t, const QString &description=""); 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;
//! deletes transaction and frees memory // ##### Transaction proofs #####
void disposeTransaction(PendingTransaction * t);
//! deletes unsigned transaction and frees memory QString getTxKey(const QString &txid) const;
void disposeTransaction(UnsignedTransaction * t); void getTxKeyAsync(const QString &txid, const std::function<void (QVariantMap)> &callback);
// void estimateTransactionFeeAsync(const QString &destination, TxKeyResult checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
// quint64 amount, TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const;
// PendingTransaction::Priority priority, TxProofResult checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
// const QJSValue &callback); void checkTxProofAsync(const QString &txid, const QString &address, const QString &message, const QString &signature);
TxProof getSpendProof(const QString &txid, const QString &message) const;
//! returns transaction history QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
TransactionHistory * history() const; void checkSpendProofAsync(const QString &txid, const QString &message, const QString &signature);
//! 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;
//! integrated address
QString integratedAddress(const QString &paymentId) const;
// ##### Sign / Verify message #####
//! signing a message //! signing a message
QString signMessage(const QString &message, bool filename = false, const QString &address = "") const; QString signMessage(const QString &message, bool filename = false, const QString &address = "") const;
//! verify a signed message //! verify a signed message
bool verifySignedMessage(const QString &message, const QString &address, const QString &signature, bool filename = false) const; 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; 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; QVariantMap parse_uri_to_object(const QString &uri) const;
QString make_uri(const QString &address, quint64 &amount, const QString &description, const QString &recipient) const; QString make_uri(const QString &address, quint64 &amount, const QString &description, const QString &recipient) const;
//! Namespace your cacheAttribute keys to avoid collisions // ##### Misc / Unused #####
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);
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();
// check if fork rules should be used
bool useForkRules(quint8 version, quint64 earlyBlocks = 0) 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());}
quint64 getWalletCreationHeight() const {return m_walletImpl->getRefreshFromBlockHeight();}
void setWalletCreationHeight(quint64 height);
QString getDaemonLogPath() const;
// 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);
// Rings
QString getRing(const QString &key_image);
QString getRings(const QString &txid);
bool setRing(const QString &key_image, const QString &ring, bool relative);
// key reuse mitigation options
void segregatePreForkOutputs(bool segregate);
void segregationHeight(quint64 height);
void keyReuseMitigation2(bool mitigation);
// Passphrase entry for hardware wallets
void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
void onWalletPassphraseNeeded(bool on_device) override;
quint64 getBytesReceived() const; quint64 getBytesReceived() const;
quint64 getBytesSent() const; quint64 getBytesSent() const;
bool isDeviceConnected() const; QString getDaemonLogPath() const;
bool setRingDatabase(const QString &path); bool setRingDatabase(const QString &path);
// TODO: setListener() when it implemented in API quint64 getWalletCreationHeight() const {return m_walletImpl->getRefreshFromBlockHeight();}
void setWalletCreationHeight(quint64 height);
//! Rescan spent outputs
bool rescanSpent();
//! Indicates that the wallet is new
void setNewWallet();
//! create a view only wallet
bool createViewOnly(const QString &path, const QString &password) const;
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
QString tmpTxDescription; // TODO: remove the need for this var
bool refreshedOnce = false;
void onHeightsRefreshed(bool success, quint64 daemonHeight, quint64 targetHeight);
signals: signals:
// emitted on every event happened with wallet // emitted on every event happened with wallet
// (money sent/received, new block) // (money sent/received, new block)
@ -488,15 +405,12 @@ signals:
void moneyReceived(const QString &txId, quint64 amount); void moneyReceived(const QString &txId, quint64 amount);
void unconfirmedMoneyReceived(const QString &txId, quint64 amount); void unconfirmedMoneyReceived(const QString &txId, quint64 amount);
void newBlock(quint64 height, quint64 targetHeight); void newBlock(quint64 height, quint64 targetHeight);
void addressBookChanged() const;
void historyModelChanged() const;
void walletCreationHeightChanged(); void walletCreationHeightChanged();
void deviceButtonRequest(quint64 buttonCode); void deviceButtonRequest(quint64 buttonCode);
void deviceButtonPressed(); void deviceButtonPressed();
void deviceError(const QString &message); void deviceError(const QString &message);
void walletPassphraseNeeded(bool onDevice); void walletPassphraseNeeded(bool onDevice);
void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid); void transactionCommitted(bool status, PendingTransaction *t, const QStringList& txid);
void heightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) const;
void deviceShowAddressShowed(); void deviceShowAddressShowed();
void transactionProofVerified(TxProofResult result); void transactionProofVerified(TxProofResult result);
void spendProofVerified(QPair<bool, bool> result); void spendProofVerified(QPair<bool, bool> result);
@ -506,72 +420,82 @@ signals:
void connectionStatusChanged(int status) const; void connectionStatusChanged(int status) const;
void currentSubaddressAccountChanged() const; void currentSubaddressAccountChanged() const;
void disconnectedChanged() const;
void proxyAddressChanged() const; void refreshSync(int height, int target);
void refreshingChanged() const; 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: private:
//! initializes wallet // ###### Status ######
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 setConnectionStatus(ConnectionStatus value); void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const;
void setProxyAddress(QString address);
void startRefreshThread();
// ##### Synchronization (Refresh) #####
void startRefreshThread();
void onNewBlock(uint64_t height); void onNewBlock(uint64_t height);
void onUpdated();
void onRefreshed(bool success, const QString &message);
// ##### Transactions #####
void onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address);
private: private:
friend class WalletManager; friend class WalletManager;
friend class WalletListenerImpl; 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; 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;
bool m_disconnected;
mutable bool m_initialized;
uint32_t m_currentSubaddressAccount; uint32_t m_currentSubaddressAccount;
Subaddress * m_subaddress; Subaddress *m_subaddress;
mutable SubaddressModel * m_subaddressModel; SubaddressModel *m_subaddressModel;
SubaddressAccount * m_subaddressAccount; SubaddressAccount *m_subaddressAccount;
mutable SubaddressAccountModel * m_subaddressAccountModel; SubaddressAccountModel *m_subaddressAccountModel;
Coins * m_coins;
mutable CoinsModel * m_coinsModel; Coins *m_coins;
CoinsModel *m_coinsModel;
QMutex m_asyncMutex; QMutex m_asyncMutex;
QString m_daemonUsername; QString m_daemonUsername;
QString m_daemonPassword; QString m_daemonPassword;
QString m_proxyAddress;
mutable QMutex m_proxyMutex; QMutex m_proxyMutex;
std::atomic<bool> m_refreshNow; std::atomic<bool> m_refreshNow;
std::atomic<bool> m_refreshEnabled; std::atomic<bool> m_refreshEnabled;
std::atomic<bool> m_refreshing;
WalletListenerImpl *m_walletListener; WalletListenerImpl *m_walletListener;
FutureScheduler m_scheduler; FutureScheduler m_scheduler;
int m_connectionTimeout = 30;
bool m_useSSL; bool m_useSSL;
bool donationSending = false;
bool m_newWallet = false;
QTimer *m_storeTimer = nullptr;
std::set<std::string> m_selectedInputs;
}; };

View file

@ -3,6 +3,7 @@
#include "WalletListenerImpl.h" #include "WalletListenerImpl.h"
#include "Wallet.h" #include "Wallet.h"
#include "WalletManager.h"
WalletListenerImpl::WalletListenerImpl(Wallet * w) WalletListenerImpl::WalletListenerImpl(Wallet * w)
: m_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) void WalletListenerImpl::moneySpent(const std::string &txId, uint64_t amount)
{ {
qDebug() << __FUNCTION__; // Outgoing tx included in a block
emit m_wallet->moneySpent(QString::fromStdString(txId), amount); 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) void WalletListenerImpl::moneyReceived(const std::string &txId, uint64_t amount)
{ {
qDebug() << __FUNCTION__; // Incoming tx included in a block.
emit m_wallet->moneyReceived(QString::fromStdString(txId), amount); 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) void WalletListenerImpl::unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
{ {
qDebug() << __FUNCTION__; // Incoming tx in pool
emit m_wallet->unconfirmedMoneyReceived(QString::fromStdString(txId), amount); 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) void WalletListenerImpl::newBlock(uint64_t height)
{ {
// qDebug() << __FUNCTION__; // Called whenever a new block gets scanned by the wallet
m_wallet->onNewBlock(height);
emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight()); emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
} }
@ -45,7 +58,6 @@ void WalletListenerImpl::updated()
void WalletListenerImpl::refreshed(bool success) void WalletListenerImpl::refreshed(bool success)
{ {
QString message = m_wallet->errorString(); QString message = m_wallet->errorString();
m_wallet->onRefreshed(success);
emit m_wallet->refreshed(success, message); emit m_wallet->refreshed(success, message);
} }

View file

@ -232,7 +232,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
EventFilter filter; EventFilter filter;
app.installEventFilter(&filter); app.installEventFilter(&filter);
WindowManager windowManager(&filter); WindowManager windowManager(QCoreApplication::instance(), &filter);
QObject::connect(&app, &SingleApplication::instanceStarted, [&windowManager]() { QObject::connect(&app, &SingleApplication::instanceStarted, [&windowManager]() {
windowManager.raise(); windowManager.raise();

View file

@ -7,9 +7,10 @@
#include <QDesktopServices> #include <QDesktopServices>
#include <QRegularExpression> #include <QRegularExpression>
#include "utils/config.h"
#include "utils/Utils.h" #include "utils/Utils.h"
#include "utils/os/tails.h" #include "utils/os/tails.h"
#include "appcontext.h" #include "utils/os/whonix.h"
#include "config-feather.h" #include "config-feather.h"
TorManager::TorManager(QObject *parent) TorManager::TorManager(QObject *parent)
@ -313,4 +314,8 @@ TorManager* TorManager::instance()
} }
return m_instance; return m_instance;
} }
TorManager::~TorManager() {
qDebug() << "~TorManager";
}

View file

@ -18,6 +18,7 @@ Q_OBJECT
public: public:
explicit TorManager(QObject *parent = nullptr); explicit TorManager(QObject *parent = nullptr);
~TorManager() override;
void init(); void init();
void start(); void start();

View file

@ -4,9 +4,10 @@
#include <QObject> #include <QObject>
#include "nodes.h" #include "nodes.h"
#include "utils/AppData.h"
#include "utils/Utils.h" #include "utils/Utils.h"
#include "utils/os/tails.h" #include "utils/os/tails.h"
#include "appcontext.h" #include "utils/os/whonix.h"
#include "constants.h" #include "constants.h"
#include "utils/WebsocketNotifier.h" #include "utils/WebsocketNotifier.h"
#include "utils/TorManager.h" #include "utils/TorManager.h"
@ -94,21 +95,21 @@ void NodeList::ensureStructure(QJsonObject &obj, NetworkType::Type networkType)
obj[networkTypeStr] = netTypeObj; obj[networkTypeStr] = netTypeObj;
} }
Nodes::Nodes(QObject *parent) Nodes::Nodes(QObject *parent, Wallet *wallet)
: QObject(parent) : QObject(parent)
, modelWebsocket(new NodeModel(NodeSource::websocket, this)) , modelWebsocket(new NodeModel(NodeSource::websocket, this))
, modelCustom(new NodeModel(NodeSource::custom, this)) , modelCustom(new NodeModel(NodeSource::custom, this))
, m_connection(FeatherNode()) , m_connection(FeatherNode())
, m_wallet(wallet)
{ {
// TODO: This class is in desperate need of refactoring // TODO: This class is in desperate need of refactoring
this->loadConfig(); this->loadConfig();
connect(websocketNotifier(), &WebsocketNotifier::NodesReceived, this, &Nodes::onWSNodesReceived); connect(websocketNotifier(), &WebsocketNotifier::NodesReceived, this, &Nodes::onWSNodesReceived);
}
void Nodes::setContext(AppContext *ctx) { if (m_wallet) {
m_ctx = ctx; connect(m_wallet, &Wallet::walletRefreshed, this, &Nodes::onWalletRefreshed);
connect(m_ctx, &AppContext::walletRefreshed, this, &Nodes::onWalletRefreshed); }
} }
void Nodes::loadConfig() { void Nodes::loadConfig() {
@ -195,7 +196,11 @@ void Nodes::connectToNode() {
} }
void Nodes::connectToNode(const FeatherNode &node) { void Nodes::connectToNode(const FeatherNode &node) {
if (!m_ctx) { if (!m_wallet) {
return;
}
if (!m_allowConnection) {
return; 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"); qInfo() << QString("Attempting to connect to %1 (%2)").arg(node.toAddress(), node.custom ? "custom" : "ws");
if (!node.url.userName().isEmpty() && !node.url.password().isEmpty()) { 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 // Don't use SSL over Tor/i2p
m_ctx->wallet->setUseSSL(!node.isAnonymityNetwork()); m_wallet->setUseSSL(!node.isAnonymityNetwork());
QString proxyAddress; QString proxyAddress;
if (useSocks5Proxy(node)) { 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 = node;
m_connection.isActive = false; m_connection.isActive = false;
@ -244,16 +249,16 @@ void Nodes::connectToNode(const FeatherNode &node) {
} }
void Nodes::autoConnect(bool forceReconnect) { void Nodes::autoConnect(bool forceReconnect) {
if (!m_ctx) { if (!m_wallet) {
return; return;
} }
// this function is responsible for automatically connecting to a daemon. // this function is responsible for automatically connecting to a daemon.
if (m_ctx->wallet == nullptr || !m_enableAutoconnect) { if (m_wallet == nullptr || !m_enableAutoconnect) {
return; return;
} }
Wallet::ConnectionStatus status = m_ctx->wallet->connectionStatus(); Wallet::ConnectionStatus status = m_wallet->connectionStatus();
bool wsMode = (this->source() == NodeSource::websocket); bool wsMode = (this->source() == NodeSource::websocket);
if (wsMode && !m_wsNodesReceived && websocketNodes().count() == 0) { if (wsMode && !m_wsNodesReceived && websocketNodes().count() == 0) {
@ -423,7 +428,7 @@ bool Nodes::useOnionNodes() {
} }
if (privacyLevel == Config::allTorExceptInitSync) { if (privacyLevel == Config::allTorExceptInitSync) {
if (m_ctx && m_ctx->refreshed) { if (m_wallet && m_wallet->refreshedOnce) {
return true; return true;
} }
@ -431,7 +436,7 @@ bool Nodes::useOnionNodes() {
int initSyncThreshold = config()->get(Config::initSyncThreshold).toInt(); int initSyncThreshold = config()->get(Config::initSyncThreshold).toInt();
int networkHeight = appData()->heights[constants::networkType]; 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; return true;
} }
} }
@ -584,4 +589,12 @@ int Nodes::modeHeight(const QList<FeatherNode> &nodes) {
} }
return mode_height; return mode_height;
} }
void Nodes::allowConnection() {
m_allowConnection = true;
}
Nodes::~Nodes() {
qDebug() << "~Nodes";
}

View file

@ -118,9 +118,11 @@ class Nodes : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit Nodes(QObject *parent = nullptr); explicit Nodes(QObject *parent, Wallet *wallet);
void setContext(AppContext *ctx); ~Nodes() override;
void loadConfig(); void loadConfig();
void allowConnection();
NodeSource source(); NodeSource source();
FeatherNode connection(); FeatherNode connection();
@ -144,7 +146,7 @@ private slots:
void onWalletRefreshed(); void onWalletRefreshed();
private: private:
AppContext *m_ctx = nullptr; Wallet *m_wallet = nullptr;
QJsonObject m_configJson; QJsonObject m_configJson;
NodeList m_nodes; NodeList m_nodes;
@ -159,6 +161,8 @@ private:
bool m_wsNodesReceived = false; bool m_wsNodesReceived = false;
bool m_enableAutoconnect = true; bool m_enableAutoconnect = true;
bool m_allowConnection = false;
FeatherNode pickEligibleNode(); FeatherNode pickEligibleNode();
bool useOnionNodes(); bool useOnionNodes();

View file

@ -4,10 +4,10 @@
#include <QScreen> #include <QScreen>
#include <QDesktopServices> #include <QDesktopServices>
#include "utils/config.h"
#include "utils/Utils.h" #include "utils/Utils.h"
#include "utils/xmrig.h" #include "utils/xmrig.h"
#include "utils/TorManager.h" #include "utils/TorManager.h"
#include "appcontext.h"
XmRig::XmRig(const QString &configDir, QObject *parent) XmRig::XmRig(const QString &configDir, QObject *parent)
: QObject(parent) : QObject(parent)

View file

@ -9,6 +9,7 @@
#include <QTableWidget> #include <QTableWidget>
#include "CCSProgressDelegate.h" #include "CCSProgressDelegate.h"
#include "utils/Utils.h"
CCSWidget::CCSWidget(QWidget *parent) CCSWidget::CCSWidget(QWidget *parent)
: QWidget(parent) : QWidget(parent)
@ -37,8 +38,9 @@ void CCSWidget::linkClicked() {
QModelIndex index = ui->tableView->currentIndex(); QModelIndex index = ui->tableView->currentIndex();
auto entry = m_model->entry(index.row()); auto entry = m_model->entry(index.row());
if (entry) if (entry) {
Utils::externalLinkWarning(this, entry->url); Utils::externalLinkWarning(this, entry->url);
}
} }
void CCSWidget::donateClicked() { void CCSWidget::donateClicked() {

View file

@ -10,7 +10,6 @@
#include <QProgressBar> #include <QProgressBar>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "model/CCSModel.h" #include "model/CCSModel.h"
#include "widgets/CCSEntry.h" #include "widgets/CCSEntry.h"

View file

@ -13,10 +13,10 @@
#include "utils/NetworkManager.h" #include "utils/NetworkManager.h"
#include "utils/WebsocketNotifier.h" #include "utils/WebsocketNotifier.h"
LocalMoneroWidget::LocalMoneroWidget(QWidget *parent, QSharedPointer<AppContext> ctx) LocalMoneroWidget::LocalMoneroWidget(QWidget *parent, Wallet *wallet)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::LocalMoneroWidget) , ui(new Ui::LocalMoneroWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);

View file

@ -7,8 +7,8 @@
#include <QWidget> #include <QWidget>
#include "api/LocalMoneroApi.h" #include "api/LocalMoneroApi.h"
#include "appcontext.h"
#include "model/LocalMoneroModel.h" #include "model/LocalMoneroModel.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class LocalMoneroWidget; class LocalMoneroWidget;
@ -19,7 +19,7 @@ class LocalMoneroWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit LocalMoneroWidget(QWidget *parent, QSharedPointer<AppContext> ctx); explicit LocalMoneroWidget(QWidget *parent, Wallet *wallet);
~LocalMoneroWidget() override; ~LocalMoneroWidget() override;
public slots: public slots:
@ -42,7 +42,7 @@ private:
void updatePaymentMethods(); void updatePaymentMethods();
QScopedPointer<Ui::LocalMoneroWidget> ui; QScopedPointer<Ui::LocalMoneroWidget> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
int m_currentPage = 0; int m_currentPage = 0;

View file

@ -8,7 +8,6 @@
#include <QTreeView> #include <QTreeView>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "model/NodeModel.h" #include "model/NodeModel.h"
#include "utils/nodes.h" #include "utils/nodes.h"

View file

@ -6,11 +6,12 @@
#include "constants.h" #include "constants.h"
#include "utils/AppData.h" #include "utils/AppData.h"
#include "utils/config.h"
TickerWidgetBase::TickerWidgetBase(QWidget *parent, QSharedPointer<AppContext> ctx) TickerWidgetBase::TickerWidgetBase(QWidget *parent, Wallet *wallet)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::TickerWidget) , ui(new Ui::TickerWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -53,8 +54,8 @@ void TickerWidgetBase::setDisplayText(const QString &text) {
} }
// BalanceTickerWidget // BalanceTickerWidget
BalanceTickerWidget::BalanceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, bool totalBalance) BalanceTickerWidget::BalanceTickerWidget(QWidget *parent, Wallet *wallet, bool totalBalance)
: TickerWidgetBase(parent, std::move(ctx)) : TickerWidgetBase(parent, wallet)
, m_totalBalance(totalBalance) , m_totalBalance(totalBalance)
{ {
if (totalBalance) if (totalBalance)
@ -64,13 +65,13 @@ BalanceTickerWidget::BalanceTickerWidget(QWidget *parent, QSharedPointer<AppCont
this->setPercentageVisible(false); 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);
connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &BalanceTickerWidget::updateDisplay); connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &BalanceTickerWidget::updateDisplay);
} }
void 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(); QString fiatCurrency = config()->get(Config::preferredFiatCurrency).toString();
double balanceFiatAmount = appData()->prices.convert("XMR", fiatCurrency, balance); double balanceFiatAmount = appData()->prices.convert("XMR", fiatCurrency, balance);
if (balanceFiatAmount < 0) if (balanceFiatAmount < 0)
@ -79,8 +80,8 @@ void BalanceTickerWidget::updateDisplay() {
} }
// PriceTickerWidget // PriceTickerWidget
PriceTickerWidget::PriceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol) PriceTickerWidget::PriceTickerWidget(QWidget *parent, Wallet *wallet, QString symbol)
: TickerWidgetBase(parent, std::move(ctx)) : TickerWidgetBase(parent, wallet)
, m_symbol(std::move(symbol)) , m_symbol(std::move(symbol))
{ {
this->setTitle(m_symbol); this->setTitle(m_symbol);
@ -107,8 +108,8 @@ void PriceTickerWidget::updateDisplay() {
} }
//RatioTickerWidget //RatioTickerWidget
RatioTickerWidget::RatioTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol1, QString symbol2) RatioTickerWidget::RatioTickerWidget(QWidget *parent, Wallet *wallet, QString symbol1, QString symbol2)
: TickerWidgetBase(parent, std::move(ctx)) : TickerWidgetBase(parent, wallet)
, m_symbol1(std::move(symbol1)) , m_symbol1(std::move(symbol1))
, m_symbol2(std::move(symbol2)) , m_symbol2(std::move(symbol2))
{ {

View file

@ -6,7 +6,7 @@
#include <QWidget> #include <QWidget>
#include "appcontext.h" #include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class TickerWidget; class TickerWidget;
@ -17,7 +17,7 @@ class TickerWidgetBase : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit TickerWidgetBase(QWidget *parent, QSharedPointer<AppContext> ctx); explicit TickerWidgetBase(QWidget *parent, Wallet *wallet);
~TickerWidgetBase() override; ~TickerWidgetBase() override;
void setTitle(const QString &title); void setTitle(const QString &title);
@ -34,7 +34,7 @@ private:
QScopedPointer<Ui::TickerWidget> ui; QScopedPointer<Ui::TickerWidget> ui;
protected: protected:
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
}; };
class BalanceTickerWidget : public TickerWidgetBase class BalanceTickerWidget : public TickerWidgetBase
@ -42,7 +42,7 @@ class BalanceTickerWidget : public TickerWidgetBase
Q_OBJECT Q_OBJECT
public: public:
explicit BalanceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, bool totalBalance); explicit BalanceTickerWidget(QWidget *parent, Wallet *wallet, bool totalBalance);
public slots: public slots:
void updateDisplay() override; void updateDisplay() override;
@ -56,7 +56,7 @@ class PriceTickerWidget : public TickerWidgetBase
Q_OBJECT Q_OBJECT
public: public:
explicit PriceTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol); explicit PriceTickerWidget(QWidget *parent, Wallet *wallet, QString symbol);
public slots: public slots:
void updateDisplay() override; void updateDisplay() override;
@ -70,7 +70,7 @@ class RatioTickerWidget : public TickerWidgetBase
Q_OBJECT Q_OBJECT
public: public:
explicit RatioTickerWidget(QWidget *parent, QSharedPointer<AppContext> ctx, QString symbol1, QString symbol2); explicit RatioTickerWidget(QWidget *parent, Wallet *wallet, QString symbol1, QString symbol2);
public slots: public slots:
void updateDisplay() override; void updateDisplay() override;

View file

@ -13,11 +13,12 @@
#include <QTableWidget> #include <QTableWidget>
#include "utils/Icons.h" #include "utils/Icons.h"
#include "utils/Utils.h"
XMRigWidget::XMRigWidget(QSharedPointer<AppContext> ctx, QWidget *parent) XMRigWidget::XMRigWidget(Wallet *wallet, QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::XMRigWidget) , ui(new Ui::XMRigWidget)
, m_ctx(std::move(ctx)) , m_wallet(wallet)
, m_XMRig(new XmRig(Config::defaultConfigDir().path())) , m_XMRig(new XmRig(Config::defaultConfigDir().path()))
, m_model(new QStandardItemModel(this)) , m_model(new QStandardItemModel(this))
, m_contextMenu(new QMenu(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()); ui->relayTor->setChecked(config()->get(Config::xmrigNetworkTor).toBool());
// Receiving address // Receiving address
auto username = m_ctx->wallet->getCacheAttribute("feather.xmrig_username"); auto username = m_wallet->getCacheAttribute("feather.xmrig_username");
if (!username.isEmpty()) { if (!username.isEmpty()) {
ui->lineEdit_address->setText(username); ui->lineEdit_address->setText(username);
} }
connect(ui->lineEdit_address, &QLineEdit::textChanged, [=]() { 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); connect(ui->btn_fillPrimaryAddress, &QPushButton::clicked, this, &XMRigWidget::onUsePrimaryAddressClicked);
// Password // Password
auto password = m_ctx->wallet->getCacheAttribute("feather.xmrig_password"); auto password = m_wallet->getCacheAttribute("feather.xmrig_password");
if (!password.isEmpty()) { if (!password.isEmpty()) {
ui->lineEdit_password->setText(password); ui->lineEdit_password->setText(password);
} else { } else {
ui->lineEdit_password->setText("featherwallet"); 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, [=]() { 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 // [Status] tab
@ -171,7 +172,7 @@ void XMRigWidget::onClearClicked() {
} }
void XMRigWidget::onUsePrimaryAddressClicked() { 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() { void XMRigWidget::onStartClicked() {
@ -193,8 +194,8 @@ void XMRigWidget::onStartClicked() {
} }
// username is receiving address usually // username is receiving address usually
auto username = m_ctx->wallet->getCacheAttribute("feather.xmrig_username"); auto username = m_wallet->getCacheAttribute("feather.xmrig_username");
auto password = m_ctx->wallet->getCacheAttribute("feather.xmrig_password"); auto password = m_wallet->getCacheAttribute("feather.xmrig_password");
if (username.isEmpty()) { if (username.isEmpty()) {
ui->console->appendPlainText("Please specify a receiving address on the Settings screen."); 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(".")) { if (address.contains("cryptonote.social") && !username.contains(".")) {
// cryptonote social requires <addr>.<username>, we'll just grab a few chars from primary addy // 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(); int threads = ui->threadSlider->value();

View file

@ -7,10 +7,11 @@
#include <QMenu> #include <QMenu>
#include <QWidget> #include <QWidget>
#include <QItemSelection> #include <QItemSelection>
#include <QStandardItemModel>
#include "appcontext.h"
#include "utils/xmrig.h" #include "utils/xmrig.h"
#include "utils/config.h" #include "utils/config.h"
#include "libwalletqt/Wallet.h"
namespace Ui { namespace Ui {
class XMRigWidget; class XMRigWidget;
@ -21,7 +22,7 @@ class XMRigWidget : public QWidget
Q_OBJECT Q_OBJECT
public: public:
explicit XMRigWidget(QSharedPointer<AppContext> ctx, QWidget *parent = nullptr); explicit XMRigWidget(Wallet *wallet, QWidget *parent = nullptr);
~XMRigWidget() override; ~XMRigWidget() override;
QStandardItemModel *model(); QStandardItemModel *model();
@ -63,7 +64,7 @@ private:
bool checkXMRigPath(); bool checkXMRigPath();
QScopedPointer<Ui::XMRigWidget> ui; QScopedPointer<Ui::XMRigWidget> ui;
QSharedPointer<AppContext> m_ctx; Wallet *m_wallet;
XmRig *m_XMRig; XmRig *m_XMRig;
QStandardItemModel *m_model; QStandardItemModel *m_model;
QMenu *m_contextMenu; QMenu *m_contextMenu;

View file

@ -9,7 +9,6 @@
#include <QWidget> #include <QWidget>
#include <QDir> #include <QDir>
#include "appcontext.h"
#include "WalletWizard.h" #include "WalletWizard.h"
namespace Ui { namespace Ui {

View file

@ -8,8 +8,6 @@
#include <QWizardPage> #include <QWizardPage>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
namespace Ui { namespace Ui {
class PageMenu; class PageMenu;
} }

View file

@ -8,7 +8,6 @@
#include <QWizardPage> #include <QWizardPage>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "utils/nodes.h" #include "utils/nodes.h"
namespace Ui { namespace Ui {

View file

@ -6,8 +6,6 @@
#include <QWizardPage> #include <QWizardPage>
#include "appcontext.h"
namespace Ui { namespace Ui {
class PageNetworkProxy; class PageNetworkProxy;
} }

View file

@ -6,8 +6,6 @@
#include <QWizardPage> #include <QWizardPage>
#include "appcontext.h"
namespace Ui { namespace Ui {
class PageNetworkWebsocket; class PageNetworkWebsocket;
} }

View file

@ -5,10 +5,10 @@
#define FEATHER_OPENWALLET_H #define FEATHER_OPENWALLET_H
#include <QLabel> #include <QLabel>
#include <QStandardItemModel>
#include <QWizardPage> #include <QWizardPage>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "model/WalletKeysFilesModel.h" #include "model/WalletKeysFilesModel.h"
namespace Ui { namespace Ui {

View file

@ -7,7 +7,6 @@
#include <QWizardPage> #include <QWizardPage>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "WalletWizard.h" #include "WalletWizard.h"
namespace Ui { namespace Ui {

View file

@ -7,7 +7,6 @@
#include <QWizardPage> #include <QWizardPage>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "WalletWizard.h" #include "WalletWizard.h"
namespace Ui { namespace Ui {

View file

@ -7,7 +7,6 @@
#include <QWizardPage> #include <QWizardPage>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "WalletWizard.h" #include "WalletWizard.h"
namespace Ui { namespace Ui {

View file

@ -7,7 +7,6 @@
#include <QWizardPage> #include <QWizardPage>
#include <QWidget> #include <QWidget>
#include "appcontext.h"
#include "WalletWizard.h" #include "WalletWizard.h"
namespace Ui { namespace Ui {

View file

@ -9,8 +9,6 @@
#include <QWidget> #include <QWidget>
#include <QDir> #include <QDir>
#include "appcontext.h"
namespace Ui { namespace Ui {
class PageWalletFile; class PageWalletFile;
} }

View file

@ -11,6 +11,7 @@
#include "WalletWizard.h" #include "WalletWizard.h"
#include "constants.h" #include "constants.h"
#include "libwalletqt/WalletManager.h"
PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *parent) PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *parent)
: QWizardPage(parent) : QWizardPage(parent)

View file

@ -10,7 +10,6 @@
#include <QTextEdit> #include <QTextEdit>
#include <QCompleter> #include <QCompleter>
#include "appcontext.h"
#include "WalletWizard.h" #include "WalletWizard.h"
namespace Ui { namespace Ui {

View file

@ -11,7 +11,6 @@
#include <QCompleter> #include <QCompleter>
#include "utils/textedit.h" #include "utils/textedit.h"
#include "appcontext.h"
namespace Ui { namespace Ui {
class PageWalletRestoreSeed; class PageWalletRestoreSeed;

View file

@ -8,10 +8,10 @@
#include <QLabel> #include <QLabel>
#include <QRadioButton> #include <QRadioButton>
#include "appcontext.h"
#include "model/WalletKeysFilesModel.h" #include "model/WalletKeysFilesModel.h"
#include "utils/RestoreHeightLookup.h" #include "utils/RestoreHeightLookup.h"
#include "utils/config.h" #include "utils/config.h"
#include "utils/Seed.h"
#include "constants.h" #include "constants.h"
enum WizardMode { enum WizardMode {