mirror of
https://github.com/wownero/wowlet.git
synced 2026-10-21 09:08:41 +02:00
Allow opening multiple windows
This commit is contained in:
+76
-389
@@ -5,7 +5,7 @@
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "appcontext.h"
|
||||
#include "globals.h"
|
||||
#include "constants.h"
|
||||
|
||||
// libwalletqt
|
||||
#include "libwalletqt/TransactionHistory.h"
|
||||
@@ -17,44 +17,32 @@
|
||||
#include "utils/WebsocketClient.h"
|
||||
#include "utils/WebsocketNotifier.h"
|
||||
|
||||
WalletKeysFilesModel *AppContext::wallets = nullptr;
|
||||
QMap<QString, QString> AppContext::txCache;
|
||||
// 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(QCommandLineParser *cmdargs) {
|
||||
this->cmdargs = cmdargs;
|
||||
AppContext::AppContext(Wallet *wallet)
|
||||
: wallet(wallet)
|
||||
, nodes(new Nodes(this, this))
|
||||
, networkType(constants::networkType)
|
||||
, m_rpc(new DaemonRpc{this, getNetworkTor(), ""})
|
||||
{
|
||||
connect(this->wallet.get(), &Wallet::moneySpent, this, &AppContext::onMoneySpent);
|
||||
connect(this->wallet.get(), &Wallet::moneyReceived, this, &AppContext::onMoneyReceived);
|
||||
connect(this->wallet.get(), &Wallet::unconfirmedMoneyReceived, this, &AppContext::onUnconfirmedMoneyReceived);
|
||||
connect(this->wallet.get(), &Wallet::newBlock, this, &AppContext::onWalletNewBlock);
|
||||
connect(this->wallet.get(), &Wallet::updated, this, &AppContext::onWalletUpdate);
|
||||
connect(this->wallet.get(), &Wallet::refreshed, this, &AppContext::onWalletRefreshed);
|
||||
connect(this->wallet.get(), &Wallet::transactionCommitted, this, &AppContext::onTransactionCommitted);
|
||||
connect(this->wallet.get(), &Wallet::heightRefreshed, this, &AppContext::onHeightRefreshed);
|
||||
connect(this->wallet.get(), &Wallet::transactionCreated, this, &AppContext::onTransactionCreated);
|
||||
connect(this->wallet.get(), &Wallet::deviceError, this, &AppContext::onDeviceError);
|
||||
connect(this->wallet.get(), &Wallet::deviceButtonRequest, this, &AppContext::onDeviceButtonRequest);
|
||||
connect(this->wallet.get(), &Wallet::connectionStatusChanged, [this]{
|
||||
this->nodes->autoConnect();
|
||||
});
|
||||
|
||||
this->isTails = TailsOS::detect();
|
||||
this->isWhonix = WhonixOS::detect();
|
||||
|
||||
// ----------------- Setup Paths -----------------
|
||||
|
||||
QString configDir = Config::defaultConfigDir().path();
|
||||
createConfigDirectory(configDir);
|
||||
|
||||
QString walletDir = config()->get(Config::walletDirectory).toString();
|
||||
if (walletDir.isEmpty()) {
|
||||
walletDir = Utils::defaultWalletDir();
|
||||
}
|
||||
this->defaultWalletDir = walletDir;
|
||||
if (!QDir().mkpath(defaultWalletDir))
|
||||
qCritical() << "Unable to create dir: " << defaultWalletDir;
|
||||
|
||||
// ----------------- Network Type -----------------
|
||||
|
||||
if (this->cmdargs->isSet("stagenet")) {
|
||||
this->networkType = NetworkType::STAGENET;
|
||||
config()->set(Config::networkType, NetworkType::STAGENET);
|
||||
}
|
||||
else if (this->cmdargs->isSet("testnet")) {
|
||||
this->networkType = NetworkType::TESTNET;
|
||||
config()->set(Config::networkType, NetworkType::TESTNET);
|
||||
}
|
||||
else {
|
||||
this->networkType = NetworkType::MAINNET;
|
||||
config()->set(Config::networkType, NetworkType::MAINNET);
|
||||
}
|
||||
|
||||
this->nodes = new Nodes(this, this);
|
||||
connect(this, &AppContext::createTransactionError, this, &AppContext::onCreateTransactionError);
|
||||
|
||||
// Store the wallet every 2 minutes
|
||||
m_storeTimer.start(2 * 60 * 1000);
|
||||
@@ -62,71 +50,26 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
||||
this->storeWallet();
|
||||
});
|
||||
|
||||
this->walletManager = WalletManager::instance();
|
||||
QString logPath = QString("%1/daemon.log").arg(configDir);
|
||||
Monero::Utils::onStartup();
|
||||
Monero::Wallet::init("", "feather", logPath.toStdString(), true);
|
||||
this->updateBalance();
|
||||
|
||||
bool logLevelFromEnv;
|
||||
int logLevel = qEnvironmentVariableIntValue("MONERO_LOG_LEVEL", &logLevelFromEnv);
|
||||
if (this->cmdargs->isSet("quiet"))
|
||||
this->walletManager->setLogLevel(-1);
|
||||
else if (logLevelFromEnv && logLevel >= 0 && logLevel <= Monero::WalletManagerFactory::LogLevel_Max)
|
||||
Monero::WalletManagerFactory::setLogLevel(logLevel);
|
||||
|
||||
connect(this, &AppContext::createTransactionError, this, &AppContext::onCreateTransactionError);
|
||||
|
||||
// libwallet connects
|
||||
connect(this->walletManager, &WalletManager::walletOpened, this, &AppContext::onWalletOpened);
|
||||
connect(this->walletManager, &WalletManager::walletCreated, this, &AppContext::onWalletCreated);
|
||||
connect(this->walletManager, &WalletManager::deviceButtonRequest, this, &AppContext::onDeviceButtonRequest);
|
||||
connect(this->walletManager, &WalletManager::deviceError, this, &AppContext::onDeviceError);
|
||||
|
||||
// TODO: move me
|
||||
connect(websocketNotifier(), &WebsocketNotifier::NodesReceived, this->nodes, &Nodes::onWSNodesReceived);
|
||||
|
||||
m_rpc = new DaemonRpc{this, getNetworkTor(), ""};
|
||||
}
|
||||
|
||||
void AppContext::initTor() {
|
||||
if (this->cmdargs->isSet("tor-host"))
|
||||
config()->set(Config::socks5Host, this->cmdargs->value("tor-host"));
|
||||
if (this->cmdargs->isSet("tor-port"))
|
||||
config()->set(Config::socks5Port, this->cmdargs->value("tor-port"));
|
||||
if (this->cmdargs->isSet("use-local-tor"))
|
||||
config()->set(Config::useLocalTor, true);
|
||||
|
||||
torManager()->init();
|
||||
torManager()->start();
|
||||
|
||||
connect(torManager(), &TorManager::connectionStateChanged, &websocketNotifier()->websocketClient, &WebsocketClient::onToggleConnect);
|
||||
|
||||
this->onTorSettingsChanged();
|
||||
}
|
||||
|
||||
void AppContext::initWS() {
|
||||
websocketNotifier()->websocketClient.start();
|
||||
// force trigger preferredFiat signal for history model
|
||||
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
|
||||
}
|
||||
|
||||
void AppContext::onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address) {
|
||||
// tx cancelled by user
|
||||
double amount = tx->amount() / globals::cdiv;
|
||||
double amount = tx->amount() / constants::cdiv;
|
||||
emit createTransactionCancelled(address, amount);
|
||||
this->currentWallet->disposeTransaction(tx);
|
||||
this->wallet->disposeTransaction(tx);
|
||||
}
|
||||
|
||||
void AppContext::onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) {
|
||||
if(this->currentWallet == nullptr){
|
||||
qCritical() << "Cannot create transaction; no wallet loaded";
|
||||
return;
|
||||
}
|
||||
|
||||
if (churn) {
|
||||
address = this->currentWallet->address(0, 0); // primary address
|
||||
address = this->wallet->address(0, 0); // primary address
|
||||
}
|
||||
|
||||
qCritical() << "Creating transaction";
|
||||
this->currentWallet->createTransactionSingleAsync(keyImage, address, outputs, this->tx_priority);
|
||||
this->wallet->createTransactionSingleAsync(keyImage, address, outputs, this->tx_priority);
|
||||
|
||||
emit initiateTransaction();
|
||||
}
|
||||
@@ -135,17 +78,12 @@ void AppContext::onCreateTransaction(const QString &address, quint64 amount, con
|
||||
// tx creation
|
||||
this->tmpTxDescription = description;
|
||||
|
||||
if(this->currentWallet == nullptr) {
|
||||
emit createTransactionError("Cannot create transaction; no wallet loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!all && amount == 0) {
|
||||
emit createTransactionError("Cannot send nothing");
|
||||
return;
|
||||
}
|
||||
|
||||
auto unlocked_balance = this->currentWallet->unlockedBalance();
|
||||
auto unlocked_balance = this->wallet->unlockedBalance();
|
||||
if(!all && amount > unlocked_balance) {
|
||||
emit createTransactionError("Not enough money to spend");
|
||||
return;
|
||||
@@ -154,11 +92,11 @@ void AppContext::onCreateTransaction(const QString &address, quint64 amount, con
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "creating tx";
|
||||
qDebug() << "Creating tx";
|
||||
if (all)
|
||||
this->currentWallet->createTransactionAllAsync(address, "", globals::mixin, this->tx_priority);
|
||||
this->wallet->createTransactionAllAsync(address, "", constants::mixin, this->tx_priority);
|
||||
else
|
||||
this->currentWallet->createTransactionAsync(address, "", amount, globals::mixin, this->tx_priority);
|
||||
this->wallet->createTransactionAsync(address, "", amount, constants::mixin, this->tx_priority);
|
||||
|
||||
emit initiateTransaction();
|
||||
}
|
||||
@@ -166,23 +104,18 @@ void AppContext::onCreateTransaction(const QString &address, quint64 amount, con
|
||||
void AppContext::onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description) {
|
||||
this->tmpTxDescription = description;
|
||||
|
||||
if (this->currentWallet == nullptr) {
|
||||
emit createTransactionError("Cannot create transaction; no wallet loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
quint64 total_amount = 0;
|
||||
for (auto &amount : amounts) {
|
||||
total_amount += amount;
|
||||
}
|
||||
|
||||
auto unlocked_balance = this->currentWallet->unlockedBalance();
|
||||
auto unlocked_balance = this->wallet->unlockedBalance();
|
||||
if (total_amount > unlocked_balance) {
|
||||
emit createTransactionError("Not enough money to spend");
|
||||
}
|
||||
|
||||
qDebug() << "Creating tx";
|
||||
this->currentWallet->createTransactionMultiDestAsync(addresses, amounts, this->tx_priority);
|
||||
this->wallet->createTransactionMultiDestAsync(addresses, amounts, this->tx_priority);
|
||||
|
||||
emit initiateTransaction();
|
||||
}
|
||||
@@ -192,68 +125,15 @@ void AppContext::onCreateTransactionError(const QString &msg) {
|
||||
emit endTransaction();
|
||||
}
|
||||
|
||||
void AppContext::closeWallet(bool emitClosedSignal, bool storeWallet) {
|
||||
if (this->currentWallet == nullptr)
|
||||
return;
|
||||
|
||||
emit walletAboutToClose();
|
||||
|
||||
if (storeWallet) {
|
||||
this->storeWallet();
|
||||
}
|
||||
|
||||
this->currentWallet->disconnect();
|
||||
this->walletManager->closeWallet();
|
||||
this->currentWallet = nullptr;
|
||||
|
||||
if (emitClosedSignal)
|
||||
emit walletClosed();
|
||||
}
|
||||
|
||||
void AppContext::onOpenWallet(const QString &path, const QString &password){
|
||||
if(this->currentWallet != nullptr){
|
||||
emit walletOpenedError("There is an active wallet opened.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!Utils::fileExists(path)) {
|
||||
emit walletOpenedError(QString("Wallet not found: %1").arg(path));
|
||||
return;
|
||||
}
|
||||
|
||||
if (password.isEmpty()) {
|
||||
this->walletPassword = "";
|
||||
}
|
||||
|
||||
config()->set(Config::firstRun, false);
|
||||
|
||||
this->walletPath = path;
|
||||
this->walletManager->openWalletAsync(path, password, this->networkType, 1);
|
||||
}
|
||||
|
||||
void AppContext::onWalletCreated(Wallet * wallet) {
|
||||
// Currently only called when a wallet is created from device.
|
||||
auto state = wallet->status();
|
||||
if (state != Wallet::Status_Ok) {
|
||||
emit walletCreatedError(wallet->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
this->onWalletOpened(wallet);
|
||||
}
|
||||
|
||||
void AppContext::onPreferredFiatCurrencyChanged(const QString &symbol) {
|
||||
if(this->currentWallet) {
|
||||
auto *model = this->currentWallet->transactionHistoryModel();
|
||||
if(model != nullptr) {
|
||||
model->preferredFiatSymbol = symbol;
|
||||
}
|
||||
auto *model = this->wallet->transactionHistoryModel();
|
||||
if (model != nullptr) {
|
||||
model->preferredFiatSymbol = symbol;
|
||||
}
|
||||
}
|
||||
|
||||
void AppContext::onAmountPrecisionChanged(int precision) {
|
||||
if (!this->currentWallet) return;
|
||||
auto *model = this->currentWallet->transactionHistoryModel();
|
||||
auto *model = this->wallet->transactionHistoryModel();
|
||||
if (!model) return;
|
||||
model->amountPrecision = precision;
|
||||
}
|
||||
@@ -265,12 +145,12 @@ void AppContext::commitTransaction(PendingTransaction *tx) {
|
||||
this->onMultiBroadcast(tx);
|
||||
}
|
||||
|
||||
this->currentWallet->commitTransactionAsync(tx);
|
||||
this->wallet->commitTransactionAsync(tx);
|
||||
}
|
||||
|
||||
void AppContext::onMultiBroadcast(PendingTransaction *tx) {
|
||||
int count = tx->txCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
quint64 count = tx->txCount();
|
||||
for (quint64 i = 0; i < count; i++) {
|
||||
QString txData = tx->signedTxToHex(i);
|
||||
|
||||
for (const auto& node: this->nodes->websocketNodes()) {
|
||||
@@ -294,205 +174,37 @@ void AppContext::onDeviceError(const QString &message) {
|
||||
}
|
||||
|
||||
void AppContext::onTorSettingsChanged() {
|
||||
if (WhonixOS::detect() || Utils::isTorsocks()) {
|
||||
if (Utils::isTorsocks()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// use local tor -> bundled tor
|
||||
QString host = config()->get(Config::socks5Host).toString();
|
||||
quint16 port = config()->get(Config::socks5Port).toString().toUShort();
|
||||
if (!torManager()->isLocalTor()) {
|
||||
host = torManager()->featherTorHost;
|
||||
port = torManager()->featherTorPort;
|
||||
}
|
||||
|
||||
QNetworkProxy proxy{QNetworkProxy::Socks5Proxy, host, port};
|
||||
getNetworkTor()->setProxy(proxy);
|
||||
websocketNotifier()->websocketClient.webSocket.setProxy(proxy);
|
||||
|
||||
this->nodes->connectToNode();
|
||||
|
||||
auto privacyLevel = config()->get(Config::torPrivacyLevel).toInt();
|
||||
qDebug() << "Changed privacyLevel to " << privacyLevel;
|
||||
}
|
||||
|
||||
void AppContext::onInitialNetworkConfigured() {
|
||||
this->initTor();
|
||||
this->initWS();
|
||||
}
|
||||
|
||||
void AppContext::onWalletOpened(Wallet *wallet) {
|
||||
auto state = wallet->status();
|
||||
if (state != Wallet::Status_Ok) {
|
||||
auto errMsg = wallet->errorString();
|
||||
if (state == Wallet::Status_BadPassword) {
|
||||
this->closeWallet(false);
|
||||
// Don't show incorrect password when we try with empty password for the first time
|
||||
bool showIncorrectPassword = m_openWalletTriedOnce;
|
||||
m_openWalletTriedOnce = true;
|
||||
emit walletOpenPasswordNeeded(showIncorrectPassword, wallet->path());
|
||||
}
|
||||
else if (errMsg == QString("basic_string::_M_replace_aux") || errMsg == QString("std::bad_alloc")) {
|
||||
qCritical() << errMsg;
|
||||
this->walletManager->clearWalletCache(this->walletPath);
|
||||
errMsg = QString("%1\n\nAttempted to clean wallet cache. Please restart Feather.").arg(errMsg);
|
||||
this->closeWallet(false);
|
||||
emit walletOpenedError(errMsg);
|
||||
} else {
|
||||
this->closeWallet(false);
|
||||
emit walletOpenedError(errMsg);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_openWalletTriedOnce = false;
|
||||
this->refreshed = false;
|
||||
this->currentWallet = wallet;
|
||||
this->walletPath = this->currentWallet->path() + ".keys";
|
||||
this->walletPassword = this->currentWallet->getPassword();
|
||||
config()->set(Config::walletPath, this->walletPath);
|
||||
|
||||
connect(this->currentWallet, &Wallet::moneySpent, this, &AppContext::onMoneySpent);
|
||||
connect(this->currentWallet, &Wallet::moneyReceived, this, &AppContext::onMoneyReceived);
|
||||
connect(this->currentWallet, &Wallet::unconfirmedMoneyReceived, this, &AppContext::onUnconfirmedMoneyReceived);
|
||||
connect(this->currentWallet, &Wallet::newBlock, this, &AppContext::onWalletNewBlock);
|
||||
connect(this->currentWallet, &Wallet::updated, this, &AppContext::onWalletUpdate);
|
||||
connect(this->currentWallet, &Wallet::refreshed, this, &AppContext::onWalletRefreshed);
|
||||
connect(this->currentWallet, &Wallet::transactionCommitted, this, &AppContext::onTransactionCommitted);
|
||||
connect(this->currentWallet, &Wallet::heightRefreshed, this, &AppContext::onHeightRefreshed);
|
||||
connect(this->currentWallet, &Wallet::transactionCreated, this, &AppContext::onTransactionCreated);
|
||||
connect(this->currentWallet, &Wallet::deviceError, this, &AppContext::onDeviceError);
|
||||
connect(this->currentWallet, &Wallet::deviceButtonRequest, this, &AppContext::onDeviceButtonRequest);
|
||||
|
||||
emit walletOpened();
|
||||
|
||||
connect(this->currentWallet, &Wallet::connectionStatusChanged, [this]{
|
||||
this->nodes->autoConnect();
|
||||
});
|
||||
this->nodes->connectToNode();
|
||||
this->updateBalance();
|
||||
|
||||
#ifdef DONATE_BEG
|
||||
this->donateBeg();
|
||||
#endif
|
||||
|
||||
// force trigger preferredFiat signal for history model
|
||||
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
|
||||
}
|
||||
|
||||
void AppContext::createConfigDirectory(const QString &dir) {
|
||||
QString config_dir_tor = QString("%1/%2").arg(dir).arg("tor");
|
||||
QString config_dir_tordata = QString("%1/%2").arg(dir).arg("tor/data");
|
||||
|
||||
QStringList createDirs({dir, config_dir_tor, config_dir_tordata});
|
||||
for(const auto &d: createDirs) {
|
||||
if(!Utils::dirExists(d)) {
|
||||
qDebug() << QString("Creating directory: %1").arg(d);
|
||||
if (!QDir().mkpath(d)) {
|
||||
qCritical() << "Could not create directory " << d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppContext::createWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedOffset) {
|
||||
if(Utils::fileExists(path)) {
|
||||
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
|
||||
qCritical() << err;
|
||||
emit walletCreatedError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(seed.mnemonic.isEmpty()) {
|
||||
emit walletCreatedError("Mnemonic seed error. Failed to write wallet.");
|
||||
return;
|
||||
}
|
||||
|
||||
Wallet *wallet = nullptr;
|
||||
if (seed.seedType == SeedType::TEVADOR) {
|
||||
wallet = this->walletManager->createDeterministicWalletFromSpendKey(path, password, seed.language, this->networkType, seed.spendKey, seed.restoreHeight, globals::kdfRounds, seedOffset);
|
||||
wallet->setCacheAttribute("feather.seed", seed.mnemonic.join(" "));
|
||||
wallet->setCacheAttribute("feather.seedoffset", seedOffset);
|
||||
}
|
||||
if (seed.seedType == SeedType::MONERO) {
|
||||
wallet = this->walletManager->recoveryWallet(path, password, seed.mnemonic.join(" "), seedOffset, this->networkType, seed.restoreHeight, globals::kdfRounds);
|
||||
}
|
||||
|
||||
this->currentWallet = wallet;
|
||||
if(this->currentWallet == nullptr) {
|
||||
emit walletCreatedError("Failed to write wallet");
|
||||
return;
|
||||
}
|
||||
|
||||
this->onWalletOpened(wallet);
|
||||
}
|
||||
|
||||
void AppContext::createWalletFromDevice(const QString &path, const QString &password, int restoreHeight) {
|
||||
if(Utils::fileExists(path)) {
|
||||
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
|
||||
qCritical() << err;
|
||||
emit walletCreatedError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
this->walletManager->createWalletFromDeviceAsync(path, password, this->networkType, "Ledger", restoreHeight);
|
||||
}
|
||||
|
||||
void AppContext::createWalletFromKeys(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight, bool deterministic) {
|
||||
if(Utils::fileExists(path)) {
|
||||
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
|
||||
qCritical() << err;
|
||||
emit walletCreatedError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!WalletManager::addressValid(address, this->networkType)) {
|
||||
auto err = QString("Failed to create wallet. Invalid address provided.").arg(path);
|
||||
qCritical() << err;
|
||||
emit walletCreatedError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!this->walletManager->keyValid(viewkey, address, true, this->networkType)) {
|
||||
auto err = QString("Failed to create wallet. Invalid viewkey provided.").arg(path);
|
||||
qCritical() << err;
|
||||
emit walletCreatedError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!spendkey.isEmpty() && !this->walletManager->keyValid(spendkey, address, false, this->networkType)) {
|
||||
auto err = QString("Failed to create wallet. Invalid spendkey provided.").arg(path);
|
||||
qCritical() << err;
|
||||
emit walletCreatedError(err);
|
||||
return;
|
||||
}
|
||||
|
||||
Wallet *wallet = this->walletManager->createWalletFromKeys(path, password, this->seedLanguage, this->networkType, address, viewkey, spendkey, restoreHeight);
|
||||
this->walletManager->walletOpened(wallet);
|
||||
}
|
||||
|
||||
void AppContext::onSetRestoreHeight(quint64 height){
|
||||
auto seed = this->currentWallet->getCacheAttribute("feather.seed");
|
||||
auto seed = this->wallet->getCacheAttribute("feather.seed");
|
||||
if(!seed.isEmpty()) {
|
||||
const auto msg = "This wallet has a 14 word mnemonic seed which has the restore height embedded.";
|
||||
emit setRestoreHeightError(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
this->currentWallet->setWalletCreationHeight(height);
|
||||
this->currentWallet->setPassword(this->currentWallet->getPassword()); // trigger .keys write
|
||||
this->wallet->setWalletCreationHeight(height);
|
||||
this->wallet->setPassword(this->wallet->getPassword()); // trigger .keys write
|
||||
|
||||
// nuke wallet cache
|
||||
const auto fn = this->currentWallet->path();
|
||||
this->walletManager->clearWalletCache(fn);
|
||||
const auto fn = this->wallet->cachePath();
|
||||
WalletManager::clearWalletCache(fn);
|
||||
|
||||
emit customRestoreHeightSet(height);
|
||||
}
|
||||
|
||||
void AppContext::onOpenAliasResolve(const QString &openAlias) {
|
||||
// @TODO: calling this freezes for about 1-2 seconds :/
|
||||
const auto result = this->walletManager->resolveOpenAlias(openAlias);
|
||||
const auto result = WalletManager::instance()->resolveOpenAlias(openAlias);; // TODO: async call
|
||||
const auto spl = result.split("|");
|
||||
auto msg = QString("");
|
||||
if(spl.count() != 2) {
|
||||
@@ -503,7 +215,7 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
|
||||
|
||||
const auto &status = spl.at(0);
|
||||
const auto &address = spl.at(1);
|
||||
const auto valid = this->walletManager->addressValid(address, this->networkType);
|
||||
const auto valid = WalletManager::addressValid(address, constants::networkType);
|
||||
if(status == "false"){
|
||||
if(valid){
|
||||
msg = "Address found, but the DNSSEC signatures could not be verified, so this address may be spoofed";
|
||||
@@ -532,50 +244,32 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
|
||||
emit openAliasResolveError(msg);
|
||||
}
|
||||
|
||||
void AppContext::donateBeg() {
|
||||
if (this->currentWallet == nullptr) return;
|
||||
if (this->networkType != NetworkType::Type::MAINNET) return;
|
||||
if (this->currentWallet->viewOnly()) return;
|
||||
|
||||
auto donationCounter = config()->get(Config::donateBeg).toInt();
|
||||
if (donationCounter == -1)
|
||||
return; // previously donated
|
||||
|
||||
donationCounter += 1;
|
||||
if (donationCounter % globals::donationBoundary == 0) {
|
||||
emit donationNag();
|
||||
}
|
||||
config()->set(Config::donateBeg, donationCounter);
|
||||
}
|
||||
|
||||
AppContext::~AppContext() = default;
|
||||
|
||||
// ############################################## LIBWALLET QT #########################################################
|
||||
// ########################################## LIBWALLET QT SIGNALS ####################################################
|
||||
|
||||
void AppContext::onMoneySpent(const QString &txId, quint64 amount) {
|
||||
auto amount_num = amount / globals::cdiv;
|
||||
auto amount_num = amount / constants::cdiv;
|
||||
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
|
||||
}
|
||||
|
||||
void AppContext::onMoneyReceived(const QString &txId, quint64 amount) {
|
||||
// Incoming tx included in a block.
|
||||
auto amount_num = amount / globals::cdiv;
|
||||
auto amount_num = amount / constants::cdiv;
|
||||
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
|
||||
}
|
||||
|
||||
void AppContext::onUnconfirmedMoneyReceived(const QString &txId, quint64 amount) {
|
||||
// Incoming transaction in pool
|
||||
auto amount_num = amount / globals::cdiv;
|
||||
auto amount_num = amount / constants::cdiv;
|
||||
qDebug() << Q_FUNC_INFO << txId << " " << QString::number(amount_num);
|
||||
|
||||
if(this->currentWallet->synchronized()) {
|
||||
if(this->wallet->synchronized()) {
|
||||
auto notify = QString("%1 XMR (pending)").arg(amount_num);
|
||||
Utils::desktopNotify("Payment received", notify, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
void AppContext::onWalletUpdate() {
|
||||
if (this->currentWallet->synchronized()) {
|
||||
if (this->wallet->synchronized()) {
|
||||
this->refreshModels();
|
||||
this->storeWallet();
|
||||
}
|
||||
@@ -595,7 +289,7 @@ void AppContext::onWalletRefreshed(bool success, const QString &message) {
|
||||
this->refreshed = true;
|
||||
emit walletRefreshed();
|
||||
// store wallet immediately upon finishing synchronization
|
||||
this->currentWallet->store();
|
||||
this->wallet->store();
|
||||
}
|
||||
|
||||
qDebug() << "Wallet refresh status: " << success;
|
||||
@@ -605,10 +299,9 @@ void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
|
||||
// Called whenever a new block gets scanned by the wallet
|
||||
this->syncStatusUpdated(blockheight, targetHeight);
|
||||
|
||||
if (!this->currentWallet) return;
|
||||
if (this->currentWallet->isSynchronized()) {
|
||||
this->currentWallet->coins()->refreshUnlocked();
|
||||
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
if (this->wallet->isSynchronized()) {
|
||||
this->wallet->coins()->refreshUnlocked();
|
||||
this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
|
||||
// Todo: only refresh tx confirmations
|
||||
}
|
||||
}
|
||||
@@ -616,7 +309,7 @@ void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
|
||||
void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, quint64 targetHeight) {
|
||||
qDebug() << Q_FUNC_INFO << walletHeight << daemonHeight << targetHeight;
|
||||
|
||||
if (this->currentWallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected)
|
||||
if (this->wallet->connectionStatus() == Wallet::ConnectionStatus_Disconnected)
|
||||
return;
|
||||
|
||||
if (daemonHeight < targetHeight) {
|
||||
@@ -631,7 +324,7 @@ void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QStr
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
for (auto &addr : address) {
|
||||
if (addr == globals::donationAddress) {
|
||||
if (addr == constants::donationAddress) {
|
||||
this->donationSending = true;
|
||||
}
|
||||
}
|
||||
@@ -646,16 +339,16 @@ void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QStr
|
||||
void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, const QStringList& txid){
|
||||
if (status) {
|
||||
for (const auto &entry: txid) {
|
||||
this->currentWallet->setUserNote(entry, this->tmpTxDescription);
|
||||
this->wallet->setUserNote(entry, this->tmpTxDescription);
|
||||
}
|
||||
this->tmpTxDescription = "";
|
||||
}
|
||||
|
||||
// Store wallet immediately so we don't risk losing tx key if wallet crashes
|
||||
this->currentWallet->store();
|
||||
this->wallet->store();
|
||||
|
||||
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
this->currentWallet->coins()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
|
||||
this->wallet->coins()->refresh(this->wallet->currentSubaddressAccount());
|
||||
|
||||
this->updateBalance();
|
||||
|
||||
@@ -670,19 +363,16 @@ void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, con
|
||||
|
||||
void AppContext::storeWallet() {
|
||||
// Do not store a synchronizing wallet: store() is NOT thread safe and may crash the wallet
|
||||
if (this->currentWallet == nullptr || !this->currentWallet->isSynchronized())
|
||||
if (!this->wallet->isSynchronized())
|
||||
return;
|
||||
|
||||
qDebug() << "Storing wallet";
|
||||
this->currentWallet->store();
|
||||
this->wallet->store();
|
||||
}
|
||||
|
||||
void AppContext::updateBalance() {
|
||||
if (!this->currentWallet)
|
||||
return;
|
||||
|
||||
quint64 balance = this->currentWallet->balance();
|
||||
quint64 spendable = this->currentWallet->unlockedBalance();
|
||||
quint64 balance = this->wallet->balance();
|
||||
quint64 spendable = this->wallet->unlockedBalance();
|
||||
|
||||
emit balanceUpdated(balance, spendable);
|
||||
}
|
||||
@@ -698,11 +388,8 @@ void AppContext::syncStatusUpdated(quint64 height, quint64 target) {
|
||||
}
|
||||
|
||||
void AppContext::refreshModels() {
|
||||
if (!this->currentWallet)
|
||||
return;
|
||||
|
||||
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
this->currentWallet->subaddress()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
this->currentWallet->coins()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||
this->wallet->history()->refresh(this->wallet->currentSubaddressAccount());
|
||||
this->wallet->subaddress()->refresh(this->wallet->currentSubaddressAccount());
|
||||
this->wallet->coins()->refresh(this->wallet->currentSubaddressAccount());
|
||||
// Todo: set timer for refreshes
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user