mirror of
https://github.com/feather-wallet/feather.git
synced 2025-01-08 20:09:43 +00:00
Misc fixes
This commit is contained in:
parent
fcf764e03c
commit
401ae0971f
28 changed files with 555 additions and 361 deletions
|
@ -29,7 +29,7 @@ if(DEBUG)
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(MONERO_HEAD "52acbb68c1a4cc67ee539325a8febc2c144596c4")
|
set(MONERO_HEAD "41327974116dedccc2f9709d8ad3a8a1f591faed")
|
||||||
set(BUILD_GUI_DEPS ON)
|
set(BUILD_GUI_DEPS ON)
|
||||||
set(ARCH "x86-64")
|
set(ARCH "x86-64")
|
||||||
set(BUILD_64 ON)
|
set(BUILD_64 ON)
|
||||||
|
|
|
@ -42,9 +42,9 @@ RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
|
|
||||||
RUN git clone -b tor-0.4.5.6 --depth 1 https://git.torproject.org/tor.git && \
|
RUN git clone -b tor-0.4.5.7 --depth 1 https://git.torproject.org/tor.git && \
|
||||||
cd tor && \
|
cd tor && \
|
||||||
git reset --hard b36a00e9a9d3eb4b2949951afaa72e45fb7e68cd && \
|
git reset --hard 83f895c015de55201e5f226f84a866f30f5ee14b && \
|
||||||
./autogen.sh && \
|
./autogen.sh && \
|
||||||
./configure \
|
./configure \
|
||||||
--disable-asciidoc \
|
--disable-asciidoc \
|
||||||
|
|
|
@ -146,9 +146,9 @@ RUN wget https://github.com/libevent/libevent/releases/download/release-2.1.11-s
|
||||||
make -j$THREADS install && \
|
make -j$THREADS install && \
|
||||||
rm -rf $(pwd)
|
rm -rf $(pwd)
|
||||||
|
|
||||||
RUN git clone -b tor-0.4.5.6 --depth 1 https://git.torproject.org/tor.git && \
|
RUN git clone -b tor-0.4.5.7 --depth 1 https://git.torproject.org/tor.git && \
|
||||||
cd tor && \
|
cd tor && \
|
||||||
git reset --hard b36a00e9a9d3eb4b2949951afaa72e45fb7e68cd && \
|
git reset --hard 83f895c015de55201e5f226f84a866f30f5ee14b && \
|
||||||
./autogen.sh && \
|
./autogen.sh && \
|
||||||
./configure --host=x86_64-w64-mingw32 \
|
./configure --host=x86_64-w64-mingw32 \
|
||||||
--disable-asciidoc \
|
--disable-asciidoc \
|
||||||
|
|
2
monero
2
monero
|
@ -1 +1 @@
|
||||||
Subproject commit 52acbb68c1a4cc67ee539325a8febc2c144596c4
|
Subproject commit 41327974116dedccc2f9709d8ad3a8a1f591faed
|
|
@ -287,7 +287,7 @@ void AppContext::onMultiBroadcast(PendingTransaction *tx) {
|
||||||
if (!node.online) continue;
|
if (!node.online) continue;
|
||||||
|
|
||||||
QString address = node.as_url();
|
QString address = node.as_url();
|
||||||
qDebug() << QString("Relaying to: %1").arg(address);
|
qDebug() << QString("Relaying %1 to: %2").arg(tx->txid()[i], address);
|
||||||
rpc->setDaemonAddress(address);
|
rpc->setDaemonAddress(address);
|
||||||
rpc->sendRawTransaction(txData);
|
rpc->sendRawTransaction(txData);
|
||||||
}
|
}
|
||||||
|
@ -363,35 +363,13 @@ void AppContext::setWindowTitle(bool mining) {
|
||||||
void AppContext::onWSMessage(const QJsonObject &msg) {
|
void AppContext::onWSMessage(const QJsonObject &msg) {
|
||||||
QString cmd = msg.value("cmd").toString();
|
QString cmd = msg.value("cmd").toString();
|
||||||
|
|
||||||
if(cmd == "blockheights") {
|
if (cmd == "blockheights") {
|
||||||
auto heights = msg.value("data").toObject();
|
QJsonObject data = msg.value("data").toObject();
|
||||||
auto mainnet = heights.value("mainnet").toInt();
|
int mainnet = data.value("mainnet").toInt();
|
||||||
auto stagenet = heights.value("stagenet").toInt();
|
int stagenet = data.value("stagenet").toInt();
|
||||||
auto changed = false;
|
|
||||||
|
|
||||||
if(!this->heights.contains("mainnet")) {
|
this->heights[NetworkType::MAINNET] = mainnet;
|
||||||
this->heights["mainnet"] = mainnet;
|
this->heights[NetworkType::STAGENET] = stagenet;
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (mainnet > this->heights["mainnet"]) {
|
|
||||||
this->heights["mainnet"] = mainnet;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!this->heights.contains("stagenet")) {
|
|
||||||
this->heights["stagenet"] = stagenet;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (stagenet > this->heights["stagenet"]) {
|
|
||||||
this->heights["stagenet"] = stagenet;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(changed)
|
|
||||||
emit blockHeightWSUpdated(this->heights);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(cmd == "nodes") {
|
else if(cmd == "nodes") {
|
||||||
|
@ -507,15 +485,16 @@ void AppContext::onWSCCS(const QJsonArray &ccs_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppContext::createConfigDirectory(const QString &dir) {
|
void AppContext::createConfigDirectory(const QString &dir) {
|
||||||
QString config_dir_tor = QString("%1%2").arg(dir).arg("tor");
|
QString config_dir_tor = QString("%1/%2").arg(dir).arg("tor");
|
||||||
QString config_dir_tordata = QString("%1%2").arg(dir).arg("tor/data");
|
QString config_dir_tordata = QString("%1/%2").arg(dir).arg("tor/data");
|
||||||
|
|
||||||
QStringList createDirs({dir, config_dir_tor, config_dir_tordata});
|
QStringList createDirs({dir, config_dir_tor, config_dir_tordata});
|
||||||
for(const auto &d: createDirs) {
|
for(const auto &d: createDirs) {
|
||||||
if(!Utils::dirExists(d)) {
|
if(!Utils::dirExists(d)) {
|
||||||
qDebug() << QString("Creating directory: %1").arg(d);
|
qDebug() << QString("Creating directory: %1").arg(d);
|
||||||
if (!QDir().mkpath(d))
|
if (!QDir().mkpath(d)) {
|
||||||
throw std::runtime_error("Could not create directory " + d.toStdString());
|
qCritical() << "Could not create directory " << d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -719,14 +698,14 @@ void AppContext::onWalletRefreshed(bool success) {
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Wallet refresh status: " << success;
|
qDebug() << "Wallet refresh status: " << success;
|
||||||
|
|
||||||
this->currentWallet->refreshHeightAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
|
void AppContext::onWalletNewBlock(quint64 blockheight, quint64 targetHeight) {
|
||||||
|
// Called whenever a new block gets scanned by the wallet
|
||||||
this->syncStatusUpdated(blockheight, targetHeight);
|
this->syncStatusUpdated(blockheight, targetHeight);
|
||||||
|
|
||||||
if (this->currentWallet->synchronized()) {
|
if (!this->currentWallet) return;
|
||||||
|
if (this->currentWallet->isSynchronized()) {
|
||||||
this->currentWallet->coins()->refreshUnlocked();
|
this->currentWallet->coins()->refreshUnlocked();
|
||||||
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());
|
this->currentWallet->history()->refresh(this->currentWallet->currentSubaddressAccount());
|
||||||
// Todo: only refresh tx confirmations
|
// Todo: only refresh tx confirmations
|
||||||
|
@ -788,7 +767,7 @@ void AppContext::onTransactionCommitted(bool status, PendingTransaction *tx, con
|
||||||
|
|
||||||
void AppContext::storeWallet() {
|
void AppContext::storeWallet() {
|
||||||
// Do not store a synchronizing wallet: store() is NOT thread safe and may crash the wallet
|
// Do not store a synchronizing wallet: store() is NOT thread safe and may crash the wallet
|
||||||
if (this->currentWallet == nullptr || !this->currentWallet->synchronized())
|
if (this->currentWallet == nullptr || !this->currentWallet->isSynchronized())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qDebug() << "Storing wallet";
|
qDebug() << "Storing wallet";
|
||||||
|
|
|
@ -54,7 +54,7 @@ public:
|
||||||
QString walletPassword = "";
|
QString walletPassword = "";
|
||||||
NetworkType::Type networkType;
|
NetworkType::Type networkType;
|
||||||
|
|
||||||
QMap<QString, int> heights;
|
QMap<NetworkType::Type, int> heights;
|
||||||
QMap<NetworkType::Type, RestoreHeightLookup*> restoreHeights;
|
QMap<NetworkType::Type, RestoreHeightLookup*> restoreHeights;
|
||||||
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
|
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
|
||||||
QString seedLanguage = "English"; // 14 word `monero-seed` only has English
|
QString seedLanguage = "English"; // 14 word `monero-seed` only has English
|
||||||
|
@ -138,7 +138,6 @@ signals:
|
||||||
void blockchainSync(int height, int target);
|
void blockchainSync(int height, int target);
|
||||||
void refreshSync(int height, int target);
|
void refreshSync(int height, int target);
|
||||||
void synchronized();
|
void synchronized();
|
||||||
void blockHeightWSUpdated(QMap<QString, int> heights);
|
|
||||||
void walletRefreshed();
|
void walletRefreshed();
|
||||||
void walletOpened();
|
void walletOpened();
|
||||||
void walletCreatedError(const QString &msg);
|
void walletCreatedError(const QString &msg);
|
||||||
|
|
|
@ -1455,3 +1455,58 @@
|
||||||
1599426969:2181000
|
1599426969:2181000
|
||||||
1599604157:2182500
|
1599604157:2182500
|
||||||
1599786817:2184000
|
1599786817:2184000
|
||||||
|
1599969318:2185500
|
||||||
|
1600147688:2187000
|
||||||
|
1600327569:2188500
|
||||||
|
1600510218:2190000
|
||||||
|
1600688674:2191500
|
||||||
|
1600867919:2193000
|
||||||
|
1601047108:2194500
|
||||||
|
1601226981:2196000
|
||||||
|
1601404059:2197500
|
||||||
|
1601584064:2199000
|
||||||
|
1601762823:2200500
|
||||||
|
1601946046:2202000
|
||||||
|
1602123016:2203500
|
||||||
|
1602302020:2205000
|
||||||
|
1602480047:2206500
|
||||||
|
1602640101:2208000
|
||||||
|
1602834791:2209500
|
||||||
|
1603025260:2211000
|
||||||
|
1603202279:2212500
|
||||||
|
1603383969:2214000
|
||||||
|
1603566322:2215500
|
||||||
|
1603746737:2217000
|
||||||
|
1603927129:2218500
|
||||||
|
1604112554:2220000
|
||||||
|
1604289877:2221500
|
||||||
|
1604474365:2223000
|
||||||
|
1604653260:2224500
|
||||||
|
1604830135:2226000
|
||||||
|
1605007197:2227500
|
||||||
|
1605185169:2229000
|
||||||
|
1605372544:2230500
|
||||||
|
1605551973:2232000
|
||||||
|
1605734501:2233500
|
||||||
|
1605910469:2235000
|
||||||
|
1606091151:2236500
|
||||||
|
1606276021:2238000
|
||||||
|
1606452893:2239500
|
||||||
|
1606627629:2241000
|
||||||
|
1606811187:2242500
|
||||||
|
1606991795:2244000
|
||||||
|
1607172363:2245500
|
||||||
|
1607353315:2247000
|
||||||
|
1607530844:2248500
|
||||||
|
1607716100:2250000
|
||||||
|
1607890493:2251500
|
||||||
|
1608067069:2253000
|
||||||
|
1608249924:2254500
|
||||||
|
1608429171:2256000
|
||||||
|
1608613290:2257500
|
||||||
|
1608791286:2259000
|
||||||
|
1608972563:2260500
|
||||||
|
1609151786:2262000
|
||||||
|
1609331787:2263500
|
||||||
|
1609513572:2265000
|
||||||
|
1609692129:2266500
|
|
@ -442,3 +442,90 @@
|
||||||
1599636188:661500
|
1599636188:661500
|
||||||
1599809533:663000
|
1599809533:663000
|
||||||
1600001474:664500
|
1600001474:664500
|
||||||
|
1600168506:666000
|
||||||
|
1600360911:667500
|
||||||
|
1600585502:669000
|
||||||
|
1600723074:670500
|
||||||
|
1600989712:672000
|
||||||
|
1601126870:673500
|
||||||
|
1601342006:675000
|
||||||
|
1601531952:676500
|
||||||
|
1601712860:678000
|
||||||
|
1601888075:679500
|
||||||
|
1602072633:681000
|
||||||
|
1602210804:682500
|
||||||
|
1602390469:684000
|
||||||
|
1602588519:685500
|
||||||
|
1602759479:687000
|
||||||
|
1602934491:688500
|
||||||
|
1603134321:690000
|
||||||
|
1603296351:691500
|
||||||
|
1603486625:693000
|
||||||
|
1603689061:694500
|
||||||
|
1603841411:696000
|
||||||
|
1604017061:697500
|
||||||
|
1604195275:699000
|
||||||
|
1604379244:700500
|
||||||
|
1604562487:702000
|
||||||
|
1604737907:703500
|
||||||
|
1604923764:705000
|
||||||
|
1605103115:706500
|
||||||
|
1605286071:708000
|
||||||
|
1605470071:709500
|
||||||
|
1605639278:711000
|
||||||
|
1605823578:712500
|
||||||
|
1606010900:714000
|
||||||
|
1606188630:715500
|
||||||
|
1606366871:717000
|
||||||
|
1606530937:718500
|
||||||
|
1606743518:720000
|
||||||
|
1606899734:721500
|
||||||
|
1607074620:723000
|
||||||
|
1607295957:724500
|
||||||
|
1607480999:726000
|
||||||
|
1607660787:727500
|
||||||
|
1607840859:729000
|
||||||
|
1608022934:730500
|
||||||
|
1608202441:732000
|
||||||
|
1608382317:733500
|
||||||
|
1608563014:735000
|
||||||
|
1608760731:736500
|
||||||
|
1608941535:738000
|
||||||
|
1609125279:739500
|
||||||
|
1609300581:741000
|
||||||
|
1609479221:742500
|
||||||
|
1609663165:744000
|
||||||
|
1609842526:745500
|
||||||
|
1610017591:747000
|
||||||
|
1610178062:748500
|
||||||
|
1610393422:750000
|
||||||
|
1610574236:751500
|
||||||
|
1610755343:753000
|
||||||
|
1610932059:754500
|
||||||
|
1611119735:756000
|
||||||
|
1611303782:757500
|
||||||
|
1611475083:759000
|
||||||
|
1611663782:760500
|
||||||
|
1611847193:762000
|
||||||
|
1611996841:763500
|
||||||
|
1612304524:765000
|
||||||
|
1612476234:766500
|
||||||
|
1612666606:768000
|
||||||
|
1612877927:769500
|
||||||
|
1613072065:771000
|
||||||
|
1613256943:772500
|
||||||
|
1613446398:774000
|
||||||
|
1613622490:775500
|
||||||
|
1613798350:777000
|
||||||
|
1614039651:778500
|
||||||
|
1614217602:780000
|
||||||
|
1614432073:781500
|
||||||
|
1614557574:783000
|
||||||
|
1614817212:784500
|
||||||
|
1615014204:786000
|
||||||
|
1615200863:787500
|
||||||
|
1615390786:789000
|
||||||
|
1615573554:790500
|
||||||
|
1615731420:792000
|
||||||
|
1615933315:793500
|
||||||
|
1616104918:795000
|
|
@ -47,7 +47,7 @@ void DebugInfoDialog::updateInfo() {
|
||||||
ui->label_daemonHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainHeight()));
|
ui->label_daemonHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainHeight()));
|
||||||
ui->label_targetHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainTargetHeight()));
|
ui->label_targetHeight->setText(QString::number(m_ctx->currentWallet->daemonBlockChainTargetHeight()));
|
||||||
ui->label_restoreHeight->setText(QString::number(m_ctx->currentWallet->getWalletCreationHeight()));
|
ui->label_restoreHeight->setText(QString::number(m_ctx->currentWallet->getWalletCreationHeight()));
|
||||||
ui->label_synchronized->setText(m_ctx->currentWallet->synchronized() ? "True" : "False");
|
ui->label_synchronized->setText(m_ctx->currentWallet->isSynchronized() ? "True" : "False");
|
||||||
|
|
||||||
auto node = m_ctx->nodes->connection();
|
auto node = m_ctx->nodes->connection();
|
||||||
ui->label_remoteNode->setText(node.full);
|
ui->label_remoteNode->setText(node.full);
|
||||||
|
@ -75,12 +75,14 @@ QString DebugInfoDialog::statusToString(Wallet::ConnectionStatus status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case Wallet::ConnectionStatus_Disconnected:
|
case Wallet::ConnectionStatus_Disconnected:
|
||||||
return "Disconnected";
|
return "Disconnected";
|
||||||
case Wallet::ConnectionStatus_Connected:
|
|
||||||
return "Connected";
|
|
||||||
case Wallet::ConnectionStatus_WrongVersion:
|
case Wallet::ConnectionStatus_WrongVersion:
|
||||||
return "Daemon wrong version";
|
return "Daemon wrong version";
|
||||||
case Wallet::ConnectionStatus_Connecting:
|
case Wallet::ConnectionStatus_Connecting:
|
||||||
return "Connecting";
|
return "Connecting";
|
||||||
|
case Wallet::ConnectionStatus_Synchronizing:
|
||||||
|
return "Synchronizing";
|
||||||
|
case Wallet::ConnectionStatus_Synchronized:
|
||||||
|
return "Synchronized";
|
||||||
default:
|
default:
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,11 @@ void HistoryWidget::setModel(TransactionHistoryProxyModel *model, Wallet *wallet
|
||||||
m_wallet->transactionHistoryModel()->amountPrecision = config()->get(Config::amountPrecision).toInt();
|
m_wallet->transactionHistoryModel()->amountPrecision = config()->get(Config::amountPrecision).toInt();
|
||||||
|
|
||||||
// Load view state
|
// Load view state
|
||||||
ui->history->setViewState(QByteArray::fromBase64(config()->get(Config::GUI_HistoryViewState).toByteArray()));
|
QByteArray historyViewState = QByteArray::fromBase64(config()->get(Config::GUI_HistoryViewState).toByteArray());
|
||||||
|
|
||||||
|
if (!historyViewState.isEmpty()) {
|
||||||
|
ui->history->setViewState(historyViewState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::resetModel()
|
void HistoryWidget::resetModel()
|
||||||
|
|
|
@ -18,10 +18,6 @@
|
||||||
#include "utils/ScopeGuard.h"
|
#include "utils/ScopeGuard.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
|
|
||||||
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
|
|
||||||
static const int WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS = 5;
|
|
||||||
|
|
||||||
static constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] = "feather.subaddress_account";
|
static constexpr char ATTRIBUTE_SUBADDRESS_ACCOUNT[] = "feather.subaddress_account";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,10 +74,6 @@ void Wallet::refreshingSet(bool value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::setConnectionTimeout(int timeout) {
|
|
||||||
m_connectionTimeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wallet::setConnectionStatus(ConnectionStatus value)
|
void Wallet::setConnectionStatus(ConnectionStatus value)
|
||||||
{
|
{
|
||||||
if (m_connectionStatus == value)
|
if (m_connectionStatus == value)
|
||||||
|
@ -102,6 +94,17 @@ void Wallet::setConnectionStatus(ConnectionStatus value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Wallet::onNewBlock(uint64_t walletHeight) {
|
||||||
|
// Called whenever a new block gets scanned by the wallet
|
||||||
|
quint64 daemonHeight = m_daemonBlockChainTargetHeight;
|
||||||
|
|
||||||
|
if (walletHeight < (daemonHeight - 1)) {
|
||||||
|
setConnectionStatus(ConnectionStatus_Synchronizing);
|
||||||
|
} else {
|
||||||
|
setConnectionStatus(ConnectionStatus_Synchronized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString Wallet::getProxyAddress() const
|
QString Wallet::getProxyAddress() const
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_proxyMutex);
|
QMutexLocker locker(&m_proxyMutex);
|
||||||
|
@ -127,9 +130,21 @@ void Wallet::setProxyAddress(QString address)
|
||||||
|
|
||||||
bool Wallet::synchronized() const
|
bool Wallet::synchronized() const
|
||||||
{
|
{
|
||||||
|
// Misleading: this will return true if wallet has synchronized at least once even if it isn't currently synchronized
|
||||||
return m_walletImpl->synchronized();
|
return m_walletImpl->synchronized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Wallet::isSynchronized() const
|
||||||
|
{
|
||||||
|
return connectionStatus() == ConnectionStatus_Synchronized;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Wallet::isConnected() const
|
||||||
|
{
|
||||||
|
auto status = connectionStatus();
|
||||||
|
return status == ConnectionStatus_Synchronizing || status == ConnectionStatus_Synchronized;
|
||||||
|
}
|
||||||
|
|
||||||
QString Wallet::errorString() const
|
QString Wallet::errorString() const
|
||||||
{
|
{
|
||||||
return QString::fromStdString(m_walletImpl->errorString());
|
return QString::fromStdString(m_walletImpl->errorString());
|
||||||
|
@ -211,7 +226,6 @@ bool Wallet::init(const QString &daemonAddress, bool trustedDaemon, quint64 uppe
|
||||||
}
|
}
|
||||||
emit proxyAddressChanged();
|
emit proxyAddressChanged();
|
||||||
|
|
||||||
setTrustedDaemon(trustedDaemon);
|
|
||||||
setTrustedDaemon(trustedDaemon);
|
setTrustedDaemon(trustedDaemon);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -239,7 +253,6 @@ void Wallet::initAsync(
|
||||||
{
|
{
|
||||||
emit walletCreationHeightChanged();
|
emit walletCreationHeightChanged();
|
||||||
qDebug() << "init async finished - starting refresh";
|
qDebug() << "init async finished - starting refresh";
|
||||||
refreshHeightAsync();
|
|
||||||
startRefresh();
|
startRefresh();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -249,6 +262,12 @@ void Wallet::initAsync(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Wallet::setDaemon(const QString &daemonAddress)
|
||||||
|
{
|
||||||
|
qDebug() << "setDaemon: " + daemonAddress;
|
||||||
|
return m_walletImpl->setDaemon(daemonAddress.toStdString(), m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), m_useSSL);
|
||||||
|
}
|
||||||
|
|
||||||
bool Wallet::isHwBacked() const
|
bool Wallet::isHwBacked() const
|
||||||
{
|
{
|
||||||
return m_walletImpl->getDeviceType() != Monero::Wallet::Device_Software;
|
return m_walletImpl->getDeviceType() != Monero::Wallet::Device_Software;
|
||||||
|
@ -380,37 +399,53 @@ void Wallet::deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::refreshHeightAsync()
|
bool Wallet::refreshHeights()
|
||||||
{
|
{
|
||||||
m_scheduler.run([this] {
|
// daemonHeight and targetHeight will be 0 if call to get_info fails
|
||||||
quint64 daemonHeight;
|
|
||||||
QPair<bool, QFuture<void>> daemonHeightFuture = m_scheduler.run([this, &daemonHeight] {
|
|
||||||
daemonHeight = daemonBlockChainHeight();
|
|
||||||
});
|
|
||||||
if (!daemonHeightFuture.first)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 targetHeight;
|
quint64 daemonHeight;
|
||||||
|
QPair<bool, QFuture<void>> daemonHeightFuture = m_scheduler.run([this, &daemonHeight] {
|
||||||
|
daemonHeight = m_walletImpl->daemonBlockChainHeight();;
|
||||||
|
});
|
||||||
|
if (!daemonHeightFuture.first)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// We must wait here for get_info to return, otherwise targetHeight will get cache value of 0
|
||||||
|
daemonHeightFuture.second.waitForFinished();
|
||||||
|
bool success = daemonHeight > 0;
|
||||||
|
|
||||||
|
quint64 targetHeight = 0;
|
||||||
|
if (success) {
|
||||||
QPair<bool, QFuture<void>> targetHeightFuture = m_scheduler.run([this, &targetHeight] {
|
QPair<bool, QFuture<void>> targetHeightFuture = m_scheduler.run([this, &targetHeight] {
|
||||||
targetHeight = daemonBlockChainTargetHeight();
|
targetHeight = m_walletImpl->daemonBlockChainTargetHeight();
|
||||||
});
|
});
|
||||||
if (!targetHeightFuture.first)
|
if (!targetHeightFuture.first)
|
||||||
{
|
{
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 walletHeight = blockChainHeight();
|
|
||||||
daemonHeightFuture.second.waitForFinished();
|
|
||||||
targetHeightFuture.second.waitForFinished();
|
targetHeightFuture.second.waitForFinished();
|
||||||
|
}
|
||||||
|
|
||||||
if (daemonHeight > 0 && targetHeight > 0) {
|
m_daemonBlockChainHeight = daemonHeight;
|
||||||
emit heightRefreshed(walletHeight, daemonHeight, targetHeight);
|
m_daemonBlockChainTargetHeight = targetHeight;
|
||||||
qDebug() << "Setting connection status from refreshHeightAsync";
|
|
||||||
setConnectionStatus(ConnectionStatus_Connected);
|
success = (daemonHeight > 0 && targetHeight > 0);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
quint64 walletHeight = blockChainHeight();
|
||||||
|
emit heightRefreshed(walletHeight, daemonHeight, targetHeight);
|
||||||
|
|
||||||
|
if (walletHeight < (daemonHeight - 1)) {
|
||||||
|
setConnectionStatus(ConnectionStatus_Synchronizing);
|
||||||
|
} else {
|
||||||
|
setConnectionStatus(ConnectionStatus_Synchronized);
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
|
setConnectionStatus(ConnectionStatus_Disconnected);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 Wallet::blockChainHeight() const
|
quint64 Wallet::blockChainHeight() const
|
||||||
|
@ -420,32 +455,13 @@ quint64 Wallet::blockChainHeight() const
|
||||||
|
|
||||||
quint64 Wallet::daemonBlockChainHeight() const
|
quint64 Wallet::daemonBlockChainHeight() const
|
||||||
{
|
{
|
||||||
// cache daemon blockchain height for some time (60 seconds by default)
|
// Can not block UI
|
||||||
|
|
||||||
if (m_daemonBlockChainHeight == 0
|
|
||||||
|| m_daemonBlockChainHeightTime.elapsed() / 1000 > m_daemonBlockChainHeightTtl)
|
|
||||||
{
|
|
||||||
m_daemonBlockChainHeight = m_walletImpl->daemonBlockChainHeight();
|
|
||||||
m_daemonBlockChainHeightTime.restart();
|
|
||||||
}
|
|
||||||
return m_daemonBlockChainHeight;
|
return m_daemonBlockChainHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 Wallet::daemonBlockChainTargetHeight() const
|
quint64 Wallet::daemonBlockChainTargetHeight() const
|
||||||
{
|
{
|
||||||
if (m_daemonBlockChainTargetHeight <= 1
|
// Can not block UI
|
||||||
|| m_daemonBlockChainTargetHeightTime.elapsed() / 1000 > m_daemonBlockChainTargetHeightTtl)
|
|
||||||
{
|
|
||||||
m_daemonBlockChainTargetHeight = m_walletImpl->daemonBlockChainTargetHeight();
|
|
||||||
|
|
||||||
// Target height is set to 0 if daemon is synced.
|
|
||||||
// Use current height from daemon when target height < current height
|
|
||||||
if (m_daemonBlockChainTargetHeight < m_daemonBlockChainHeight){
|
|
||||||
m_daemonBlockChainTargetHeight = m_daemonBlockChainHeight;
|
|
||||||
}
|
|
||||||
m_daemonBlockChainTargetHeightTime.restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_daemonBlockChainTargetHeight;
|
return m_daemonBlockChainTargetHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,11 +600,15 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
|
||||||
quint64 amount, quint32 mixin_count,
|
quint64 amount, quint32 mixin_count,
|
||||||
PendingTransaction::Priority priority)
|
PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
|
pauseRefresh();
|
||||||
|
|
||||||
std::set<uint32_t> subaddr_indices;
|
std::set<uint32_t> subaddr_indices;
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||||
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
|
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
|
||||||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
||||||
PendingTransaction * result = new PendingTransaction(ptImpl,0);
|
PendingTransaction * result = new PendingTransaction(ptImpl,0);
|
||||||
|
|
||||||
|
startRefresh();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,6 +626,8 @@ void Wallet::createTransactionAsync(const QString &dst_addr, const QString &paym
|
||||||
PendingTransaction* Wallet::createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
PendingTransaction* Wallet::createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||||
PendingTransaction::Priority priority)
|
PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
|
pauseRefresh();
|
||||||
|
|
||||||
std::vector<std::string> dests;
|
std::vector<std::string> dests;
|
||||||
for (auto &addr : dst_addr) {
|
for (auto &addr : dst_addr) {
|
||||||
dests.push_back(addr.toStdString());
|
dests.push_back(addr.toStdString());
|
||||||
|
@ -619,6 +641,8 @@ PendingTransaction* Wallet::createTransactionMultiDest(const QVector<QString> &d
|
||||||
// TODO: remove mixin count
|
// TODO: remove mixin count
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionMultDest(dests, "", amounts, 11, static_cast<Monero::PendingTransaction::Priority>(priority));
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionMultDest(dests, "", amounts, 11, static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||||
PendingTransaction * result = new PendingTransaction(ptImpl);
|
PendingTransaction * result = new PendingTransaction(ptImpl);
|
||||||
|
|
||||||
|
startRefresh();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,11 +662,15 @@ void Wallet::createTransactionMultiDestAsync(const QVector<QString> &dst_addr, c
|
||||||
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||||
quint32 mixin_count, PendingTransaction::Priority priority)
|
quint32 mixin_count, PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
|
pauseRefresh();
|
||||||
|
|
||||||
std::set<uint32_t> subaddr_indices;
|
std::set<uint32_t> subaddr_indices;
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||||
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
|
dst_addr.toStdString(), payment_id.toStdString(), Monero::optional<uint64_t>(), mixin_count,
|
||||||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
||||||
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||||
|
|
||||||
|
startRefresh();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,9 +688,13 @@ void Wallet::createTransactionAllAsync(const QString &dst_addr, const QString &p
|
||||||
PendingTransaction *Wallet::createTransactionSingle(const QString &key_image, const QString &dst_addr, const size_t outputs,
|
PendingTransaction *Wallet::createTransactionSingle(const QString &key_image, const QString &dst_addr, const size_t outputs,
|
||||||
PendingTransaction::Priority priority)
|
PendingTransaction::Priority priority)
|
||||||
{
|
{
|
||||||
|
pauseRefresh();
|
||||||
|
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionSingle(key_image.toStdString(), dst_addr.toStdString(),
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionSingle(key_image.toStdString(), dst_addr.toStdString(),
|
||||||
outputs, static_cast<Monero::PendingTransaction::Priority>(priority));
|
outputs, static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||||
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||||
|
|
||||||
|
startRefresh();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,8 +710,12 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
|
||||||
|
|
||||||
PendingTransaction *Wallet::createSweepUnmixableTransaction()
|
PendingTransaction *Wallet::createSweepUnmixableTransaction()
|
||||||
{
|
{
|
||||||
|
pauseRefresh();
|
||||||
|
|
||||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createSweepUnmixableTransaction();
|
Monero::PendingTransaction * ptImpl = m_walletImpl->createSweepUnmixableTransaction();
|
||||||
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||||
|
|
||||||
|
startRefresh();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,16 +906,6 @@ QString Wallet::integratedAddress(const QString &paymentId) const
|
||||||
return QString::fromStdString(m_walletImpl->integratedAddress(paymentId.toStdString()));
|
return QString::fromStdString(m_walletImpl->integratedAddress(paymentId.toStdString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Wallet::paymentId() const
|
|
||||||
{
|
|
||||||
return m_paymentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wallet::setPaymentId(const QString &paymentId)
|
|
||||||
{
|
|
||||||
m_paymentId = paymentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Wallet::getCacheAttribute(const QString &key) const {
|
QString Wallet::getCacheAttribute(const QString &key) const {
|
||||||
return QString::fromStdString(m_walletImpl->getCacheAttribute(key.toStdString()));
|
return QString::fromStdString(m_walletImpl->getCacheAttribute(key.toStdString()));
|
||||||
}
|
}
|
||||||
|
@ -1221,11 +1247,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||||
, m_addressBook(nullptr)
|
, m_addressBook(nullptr)
|
||||||
, m_addressBookModel(nullptr)
|
, m_addressBookModel(nullptr)
|
||||||
, m_daemonBlockChainHeight(0)
|
, m_daemonBlockChainHeight(0)
|
||||||
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
|
|
||||||
, m_daemonBlockChainTargetHeight(0)
|
, m_daemonBlockChainTargetHeight(0)
|
||||||
, m_daemonBlockChainTargetHeightTtl(DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS)
|
|
||||||
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
|
, m_connectionStatus(Wallet::ConnectionStatus_Disconnected)
|
||||||
, m_connectionStatusTtl(WALLET_CONNECTION_STATUS_CACHE_TTL_SECONDS)
|
|
||||||
, m_disconnected(true)
|
, m_disconnected(true)
|
||||||
, m_currentSubaddressAccount(0)
|
, m_currentSubaddressAccount(0)
|
||||||
, m_subaddress(nullptr)
|
, m_subaddress(nullptr)
|
||||||
|
@ -1248,11 +1271,7 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
|
||||||
m_walletImpl->setListener(m_walletListener);
|
m_walletImpl->setListener(m_walletListener);
|
||||||
m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
|
m_currentSubaddressAccount = getCacheAttribute(ATTRIBUTE_SUBADDRESS_ACCOUNT).toUInt();
|
||||||
// start cache timers
|
// start cache timers
|
||||||
m_connectionStatusTime.start();
|
|
||||||
m_daemonBlockChainHeightTime.start();
|
|
||||||
m_daemonBlockChainTargetHeightTime.start();
|
|
||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
m_connectionStatusRunning = false;
|
|
||||||
m_daemonUsername = "";
|
m_daemonUsername = "";
|
||||||
m_daemonPassword = "";
|
m_daemonPassword = "";
|
||||||
|
|
||||||
|
@ -1313,7 +1332,12 @@ void Wallet::startRefreshThread()
|
||||||
if (elapsed >= refreshInterval || m_refreshNow)
|
if (elapsed >= refreshInterval || m_refreshNow)
|
||||||
{
|
{
|
||||||
m_refreshNow = false;
|
m_refreshNow = false;
|
||||||
refresh(false);
|
// Don't call refresh function if we don't have the daemon and target height
|
||||||
|
// We do this to prevent to UI from getting confused about the amount of blocks that are still remaining
|
||||||
|
bool haveHeights = refreshHeights();
|
||||||
|
if (haveHeights) {
|
||||||
|
refresh(false);
|
||||||
|
}
|
||||||
last = std::chrono::steady_clock::now();
|
last = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1328,9 +1352,7 @@ void Wallet::startRefreshThread()
|
||||||
}
|
}
|
||||||
|
|
||||||
void Wallet::onRefreshed(bool success) {
|
void Wallet::onRefreshed(bool success) {
|
||||||
if (success) {
|
if (!success) {
|
||||||
setConnectionStatus(ConnectionStatus_Connected);
|
|
||||||
} else {
|
|
||||||
setConnectionStatus(ConnectionStatus_Disconnected);
|
setConnectionStatus(ConnectionStatus_Disconnected);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -74,37 +74,9 @@ struct TxProofResult {
|
||||||
class Wallet : public QObject, public PassprasePrompter
|
class Wallet : public QObject, public PassprasePrompter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
|
|
||||||
Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
|
|
||||||
Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
|
|
||||||
Q_PROPERTY(Status status READ status)
|
|
||||||
Q_PROPERTY(NetworkType::Type nettype READ nettype)
|
|
||||||
Q_PROPERTY(ConnectionStatus connectionStatus READ connectionStatus)
|
|
||||||
Q_PROPERTY(quint32 currentSubaddressAccount READ currentSubaddressAccount NOTIFY currentSubaddressAccountChanged)
|
|
||||||
Q_PROPERTY(bool synchronized READ synchronized)
|
|
||||||
Q_PROPERTY(QString errorString READ errorString)
|
|
||||||
Q_PROPERTY(TransactionHistory * history READ history)
|
|
||||||
Q_PROPERTY(QString paymentId READ paymentId WRITE setPaymentId)
|
|
||||||
Q_PROPERTY(TransactionHistoryProxyModel * historyModel READ historyModel NOTIFY historyModelChanged)
|
|
||||||
Q_PROPERTY(QString path READ path)
|
|
||||||
Q_PROPERTY(AddressBookModel * addressBookModel READ addressBookModel)
|
|
||||||
Q_PROPERTY(AddressBook * addressBook READ addressBook NOTIFY addressBookChanged)
|
|
||||||
Q_PROPERTY(SubaddressModel * subaddressModel READ subaddressModel)
|
|
||||||
Q_PROPERTY(Subaddress * subaddress READ subaddress)
|
|
||||||
Q_PROPERTY(SubaddressAccountModel * subaddressAccountModel READ subaddressAccountModel)
|
|
||||||
Q_PROPERTY(SubaddressAccount * subaddressAccount READ subaddressAccount)
|
|
||||||
Q_PROPERTY(bool viewOnly READ viewOnly)
|
|
||||||
Q_PROPERTY(QString secretViewKey READ getSecretViewKey)
|
|
||||||
Q_PROPERTY(QString publicViewKey READ getPublicViewKey)
|
|
||||||
Q_PROPERTY(QString secretSpendKey READ getSecretSpendKey)
|
|
||||||
Q_PROPERTY(QString publicSpendKey READ getPublicSpendKey)
|
|
||||||
Q_PROPERTY(QString daemonLogPath READ getDaemonLogPath CONSTANT)
|
|
||||||
Q_PROPERTY(QString proxyAddress READ getProxyAddress WRITE setProxyAddress NOTIFY proxyAddressChanged)
|
|
||||||
Q_PROPERTY(quint64 walletCreationHeight READ getWalletCreationHeight WRITE setWalletCreationHeight NOTIFY walletCreationHeightChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
Status_Ok = Monero::Wallet::Status_Ok,
|
Status_Ok = Monero::Wallet::Status_Ok,
|
||||||
Status_Error = Monero::Wallet::Status_Error,
|
Status_Error = Monero::Wallet::Status_Error,
|
||||||
|
@ -115,9 +87,10 @@ public:
|
||||||
|
|
||||||
enum ConnectionStatus {
|
enum ConnectionStatus {
|
||||||
ConnectionStatus_Disconnected = Monero::Wallet::ConnectionStatus_Disconnected,
|
ConnectionStatus_Disconnected = Monero::Wallet::ConnectionStatus_Disconnected,
|
||||||
ConnectionStatus_Connected = Monero::Wallet::ConnectionStatus_Connected,
|
|
||||||
ConnectionStatus_WrongVersion = Monero::Wallet::ConnectionStatus_WrongVersion,
|
ConnectionStatus_WrongVersion = Monero::Wallet::ConnectionStatus_WrongVersion,
|
||||||
ConnectionStatus_Connecting
|
ConnectionStatus_Connecting = 9,
|
||||||
|
ConnectionStatus_Synchronizing = 10,
|
||||||
|
ConnectionStatus_Synchronized = 11
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_ENUM(ConnectionStatus)
|
Q_ENUM(ConnectionStatus)
|
||||||
|
@ -132,7 +105,7 @@ public:
|
||||||
QString getSeedLanguage() const;
|
QString getSeedLanguage() const;
|
||||||
|
|
||||||
//! set seed language
|
//! set seed language
|
||||||
Q_INVOKABLE void setSeedLanguage(const QString &lang);
|
void setSeedLanguage(const QString &lang);
|
||||||
|
|
||||||
//! returns last operation's status
|
//! returns last operation's status
|
||||||
Status status() const;
|
Status status() const;
|
||||||
|
@ -143,32 +116,37 @@ public:
|
||||||
//! returns true if wallet was ever synchronized
|
//! returns true if wallet was ever synchronized
|
||||||
bool synchronized() const;
|
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;
|
||||||
|
|
||||||
//! returns last operation's error message
|
//! returns last operation's error message
|
||||||
QString errorString() const;
|
QString errorString() const;
|
||||||
|
|
||||||
//! changes the password using existing parameters (path, seed, seed lang)
|
//! changes the password using existing parameters (path, seed, seed lang)
|
||||||
Q_INVOKABLE bool setPassword(const QString &password);
|
bool setPassword(const QString &password);
|
||||||
|
|
||||||
//! get current wallet password
|
//! get current wallet password
|
||||||
Q_INVOKABLE QString getPassword();
|
QString getPassword();
|
||||||
|
|
||||||
//! returns wallet's public address
|
//! returns wallet's public address
|
||||||
Q_INVOKABLE QString address(quint32 accountIndex, quint32 addressIndex) const;
|
QString address(quint32 accountIndex, quint32 addressIndex) const;
|
||||||
|
|
||||||
//! returns the subaddress index of the address
|
//! returns the subaddress index of the address
|
||||||
Q_INVOKABLE SubaddressIndex subaddressIndex(const QString &address) const;
|
SubaddressIndex subaddressIndex(const QString &address) const;
|
||||||
|
|
||||||
//! returns wallet file's path
|
//! returns wallet file's path
|
||||||
QString path() const;
|
QString path() const;
|
||||||
|
|
||||||
//! saves wallet to the file by given path
|
//! saves wallet to the file by given path
|
||||||
//! empty path stores in current location
|
//! empty path stores in current location
|
||||||
Q_INVOKABLE void store(const QString &path = "");
|
void store(const QString &path = "");
|
||||||
// Q_INVOKABLE void storeAsync(const QJSValue &callback, const QString &path = "");
|
// void storeAsync(const QJSValue &callback, const QString &path = "");
|
||||||
|
|
||||||
//! initializes wallet asynchronously
|
//! initializes wallet asynchronously
|
||||||
Q_INVOKABLE void initAsync(
|
void initAsync(
|
||||||
const QString &daemonAddress,
|
const QString &daemonAddress,
|
||||||
bool trustedDaemon = false,
|
bool trustedDaemon = false,
|
||||||
quint64 upperTransactionLimit = 0,
|
quint64 upperTransactionLimit = 0,
|
||||||
|
@ -177,167 +155,167 @@ public:
|
||||||
quint64 restoreHeight = 0,
|
quint64 restoreHeight = 0,
|
||||||
const QString &proxyAddress = "");
|
const QString &proxyAddress = "");
|
||||||
|
|
||||||
|
bool setDaemon(const QString &daemonAddress);
|
||||||
|
|
||||||
// Set daemon rpc user/pass
|
// Set daemon rpc user/pass
|
||||||
Q_INVOKABLE void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
|
void setDaemonLogin(const QString &daemonUsername = "", const QString &daemonPassword = "");
|
||||||
|
|
||||||
//! create a view only wallet
|
//! create a view only wallet
|
||||||
Q_INVOKABLE bool createViewOnly(const QString &path, const QString &password) const;
|
bool createViewOnly(const QString &path, const QString &password) const;
|
||||||
|
|
||||||
//! connects to daemon
|
//! connects to daemon
|
||||||
Q_INVOKABLE bool connectToDaemon();
|
bool connectToDaemon();
|
||||||
|
|
||||||
//! set connect to daemon timeout
|
|
||||||
Q_INVOKABLE void setConnectionTimeout(int timeout);
|
|
||||||
|
|
||||||
//! indicates if daemon is trusted
|
//! indicates if daemon is trusted
|
||||||
Q_INVOKABLE 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
|
||||||
Q_INVOKABLE void setUseSSL(bool ssl);
|
void setUseSSL(bool ssl);
|
||||||
|
|
||||||
//! returns balance
|
//! returns balance
|
||||||
Q_INVOKABLE quint64 balance() const;
|
quint64 balance() const;
|
||||||
Q_INVOKABLE quint64 balance(quint32 accountIndex) const;
|
quint64 balance(quint32 accountIndex) const;
|
||||||
Q_INVOKABLE quint64 balanceAll() const;
|
quint64 balanceAll() const;
|
||||||
|
|
||||||
//! returns unlocked balance
|
//! returns unlocked balance
|
||||||
Q_INVOKABLE quint64 unlockedBalance() const;
|
quint64 unlockedBalance() const;
|
||||||
Q_INVOKABLE quint64 unlockedBalance(quint32 accountIndex) const;
|
quint64 unlockedBalance(quint32 accountIndex) const;
|
||||||
Q_INVOKABLE quint64 unlockedBalanceAll() const;
|
quint64 unlockedBalanceAll() const;
|
||||||
|
|
||||||
//! account/address management
|
//! account/address management
|
||||||
quint32 currentSubaddressAccount() const;
|
quint32 currentSubaddressAccount() const;
|
||||||
Q_INVOKABLE void switchSubaddressAccount(quint32 accountIndex);
|
void switchSubaddressAccount(quint32 accountIndex);
|
||||||
Q_INVOKABLE void addSubaddressAccount(const QString& label);
|
void addSubaddressAccount(const QString& label);
|
||||||
Q_INVOKABLE quint32 numSubaddressAccounts() const;
|
quint32 numSubaddressAccounts() const;
|
||||||
Q_INVOKABLE quint32 numSubaddresses(quint32 accountIndex) const;
|
quint32 numSubaddresses(quint32 accountIndex) const;
|
||||||
Q_INVOKABLE void addSubaddress(const QString& label);
|
void addSubaddress(const QString& label);
|
||||||
Q_INVOKABLE QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
|
QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
|
||||||
Q_INVOKABLE void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
|
void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
|
||||||
Q_INVOKABLE void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId);
|
void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId);
|
||||||
|
|
||||||
//! hw-device backed wallets
|
//! hw-device backed wallets
|
||||||
Q_INVOKABLE bool isHwBacked() const;
|
bool isHwBacked() const;
|
||||||
Q_INVOKABLE bool isLedger() const;
|
bool isLedger() const;
|
||||||
Q_INVOKABLE bool isTrezor() const;
|
bool isTrezor() const;
|
||||||
|
|
||||||
//! returns if view only wallet
|
//! returns if view only wallet
|
||||||
Q_INVOKABLE bool viewOnly() const;
|
bool viewOnly() const;
|
||||||
|
|
||||||
//! return true if deterministic keys
|
//! return true if deterministic keys
|
||||||
Q_INVOKABLE bool isDeterministic() const;
|
bool isDeterministic() const;
|
||||||
|
|
||||||
Q_INVOKABLE void refreshHeightAsync();
|
//! refresh daemon blockchain and target height
|
||||||
|
bool refreshHeights();
|
||||||
|
|
||||||
//! export/import key images
|
//! export/import key images
|
||||||
Q_INVOKABLE bool exportKeyImages(const QString& path, bool all = false);
|
bool exportKeyImages(const QString& path, bool all = false);
|
||||||
Q_INVOKABLE bool importKeyImages(const QString& path);
|
bool importKeyImages(const QString& path);
|
||||||
|
|
||||||
//! export/import outputs
|
//! export/import outputs
|
||||||
Q_INVOKABLE bool exportOutputs(const QString& path, bool all = false);
|
bool exportOutputs(const QString& path, bool all = false);
|
||||||
Q_INVOKABLE bool importOutputs(const QString& path);
|
bool importOutputs(const QString& path);
|
||||||
|
|
||||||
//! import a transaction
|
//! import a transaction
|
||||||
Q_INVOKABLE bool importTransaction(const QString& txid, const QVector<quint64>& output_indeces, quint64 height, quint64 timestamp, bool miner_tx, bool pool, bool double_spend_seen);
|
bool importTransaction(const QString& txid, const QVector<quint64>& output_indeces, quint64 height, quint64 timestamp, bool miner_tx, bool pool, bool double_spend_seen);
|
||||||
|
|
||||||
Q_INVOKABLE QString printBlockchain();
|
QString printBlockchain();
|
||||||
Q_INVOKABLE QString printTransfers();
|
QString printTransfers();
|
||||||
Q_INVOKABLE QString printPayments();
|
QString printPayments();
|
||||||
Q_INVOKABLE QString printUnconfirmedPayments();
|
QString printUnconfirmedPayments();
|
||||||
Q_INVOKABLE QString printConfirmedTransferDetails();
|
QString printConfirmedTransferDetails();
|
||||||
Q_INVOKABLE QString printUnconfirmedTransferDetails();
|
QString printUnconfirmedTransferDetails();
|
||||||
Q_INVOKABLE QString printPubKeys();
|
QString printPubKeys();
|
||||||
Q_INVOKABLE QString printTxNotes();
|
QString printTxNotes();
|
||||||
Q_INVOKABLE QString printSubaddresses();
|
QString printSubaddresses();
|
||||||
Q_INVOKABLE QString printSubaddressLabels();
|
QString printSubaddressLabels();
|
||||||
Q_INVOKABLE QString printAdditionalTxKeys();
|
QString printAdditionalTxKeys();
|
||||||
Q_INVOKABLE QString printAttributes();
|
QString printAttributes();
|
||||||
Q_INVOKABLE QString printKeyImages();
|
QString printKeyImages();
|
||||||
Q_INVOKABLE QString printAccountTags();
|
QString printAccountTags();
|
||||||
Q_INVOKABLE QString printTxKeys();
|
QString printTxKeys();
|
||||||
Q_INVOKABLE QString printAddressBook();
|
QString printAddressBook();
|
||||||
Q_INVOKABLE QString printScannedPoolTxs();
|
QString printScannedPoolTxs();
|
||||||
|
|
||||||
//! refreshes the wallet
|
//! refreshes the wallet
|
||||||
Q_INVOKABLE bool refresh(bool historyAndSubaddresses = false);
|
bool refresh(bool historyAndSubaddresses = false);
|
||||||
|
|
||||||
// pause/resume refresh
|
// pause/resume refresh
|
||||||
Q_INVOKABLE void startRefresh();
|
void startRefresh();
|
||||||
Q_INVOKABLE void pauseRefresh();
|
void pauseRefresh();
|
||||||
|
|
||||||
//! returns current wallet's block height
|
//! returns current wallet's block height
|
||||||
//! (can be less than daemon's blockchain height when wallet sync in progress)
|
//! (can be less than daemon's blockchain height when wallet sync in progress)
|
||||||
Q_INVOKABLE quint64 blockChainHeight() const;
|
quint64 blockChainHeight() const;
|
||||||
|
|
||||||
//! returns daemon's blockchain height
|
//! returns daemon's blockchain height
|
||||||
Q_INVOKABLE quint64 daemonBlockChainHeight() const;
|
quint64 daemonBlockChainHeight() const;
|
||||||
|
|
||||||
//! returns daemon's blockchain target height
|
//! returns daemon's blockchain target height
|
||||||
Q_INVOKABLE quint64 daemonBlockChainTargetHeight() const;
|
quint64 daemonBlockChainTargetHeight() const;
|
||||||
|
|
||||||
//! creates transaction
|
//! creates transaction
|
||||||
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
|
PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
|
||||||
quint64 amount, quint32 mixin_count,
|
quint64 amount, quint32 mixin_count,
|
||||||
PendingTransaction::Priority priority);
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates async transaction
|
//! creates async transaction
|
||||||
Q_INVOKABLE void createTransactionAsync(const QString &dst_addr, const QString &payment_id,
|
void createTransactionAsync(const QString &dst_addr, const QString &payment_id,
|
||||||
quint64 amount, quint32 mixin_count,
|
quint64 amount, quint32 mixin_count,
|
||||||
PendingTransaction::Priority priority);
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates multi-destination transaction
|
//! creates multi-destination transaction
|
||||||
Q_INVOKABLE PendingTransaction * createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
PendingTransaction * createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||||
PendingTransaction::Priority priority);
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates async multi-destination transaction
|
//! creates async multi-destination transaction
|
||||||
Q_INVOKABLE void createTransactionMultiDestAsync(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
void createTransactionMultiDestAsync(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||||
PendingTransaction::Priority priority);
|
PendingTransaction::Priority priority);
|
||||||
|
|
||||||
|
|
||||||
//! creates transaction with all outputs
|
//! creates transaction with all outputs
|
||||||
Q_INVOKABLE PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
PendingTransaction * createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||||
quint32 mixin_count, PendingTransaction::Priority priority);
|
quint32 mixin_count, PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates async transaction with all outputs
|
//! creates async transaction with all outputs
|
||||||
Q_INVOKABLE void createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
|
void createTransactionAllAsync(const QString &dst_addr, const QString &payment_id,
|
||||||
quint32 mixin_count, PendingTransaction::Priority priority);
|
quint32 mixin_count, PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates transaction with single input
|
//! creates transaction with single input
|
||||||
Q_INVOKABLE PendingTransaction * createTransactionSingle(const QString &key_image, const QString &dst_addr,
|
PendingTransaction * createTransactionSingle(const QString &key_image, const QString &dst_addr,
|
||||||
size_t outputs, PendingTransaction::Priority priority);
|
size_t outputs, PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates async transaction with single input
|
//! creates async transaction with single input
|
||||||
Q_INVOKABLE void createTransactionSingleAsync(const QString &key_image, const QString &dst_addr,
|
void createTransactionSingleAsync(const QString &key_image, const QString &dst_addr,
|
||||||
size_t outputs, PendingTransaction::Priority priority);
|
size_t outputs, PendingTransaction::Priority priority);
|
||||||
|
|
||||||
//! creates sweep unmixable transaction
|
//! creates sweep unmixable transaction
|
||||||
Q_INVOKABLE PendingTransaction * createSweepUnmixableTransaction();
|
PendingTransaction * createSweepUnmixableTransaction();
|
||||||
|
|
||||||
//! creates async sweep unmixable transaction
|
//! creates async sweep unmixable transaction
|
||||||
Q_INVOKABLE void createSweepUnmixableTransactionAsync();
|
void createSweepUnmixableTransactionAsync();
|
||||||
|
|
||||||
//! Sign a transfer from file
|
//! Sign a transfer from file
|
||||||
Q_INVOKABLE UnsignedTransaction * loadTxFile(const QString &fileName);
|
UnsignedTransaction * loadTxFile(const QString &fileName);
|
||||||
|
|
||||||
//! Load an unsigned transaction from a base64 encoded string
|
//! Load an unsigned transaction from a base64 encoded string
|
||||||
Q_INVOKABLE UnsignedTransaction * loadTxFromBase64Str(const QString &unsigned_tx);
|
UnsignedTransaction * loadTxFromBase64Str(const QString &unsigned_tx);
|
||||||
|
|
||||||
//! Load a signed transaction from file
|
//! Load a signed transaction from file
|
||||||
Q_INVOKABLE PendingTransaction * loadSignedTxFile(const QString &fileName);
|
PendingTransaction * loadSignedTxFile(const QString &fileName);
|
||||||
|
|
||||||
//! Submit a transfer from file
|
//! Submit a transfer from file
|
||||||
Q_INVOKABLE bool submitTxFile(const QString &fileName) const;
|
bool submitTxFile(const QString &fileName) const;
|
||||||
|
|
||||||
//! asynchronous transaction commit
|
//! asynchronous transaction commit
|
||||||
Q_INVOKABLE void commitTransactionAsync(PendingTransaction * t);
|
void commitTransactionAsync(PendingTransaction * t);
|
||||||
|
|
||||||
//! deletes transaction and frees memory
|
//! deletes transaction and frees memory
|
||||||
Q_INVOKABLE void disposeTransaction(PendingTransaction * t);
|
void disposeTransaction(PendingTransaction * t);
|
||||||
|
|
||||||
//! deletes unsigned transaction and frees memory
|
//! deletes unsigned transaction and frees memory
|
||||||
Q_INVOKABLE void disposeTransaction(UnsignedTransaction * t);
|
void disposeTransaction(UnsignedTransaction * t);
|
||||||
|
|
||||||
// Q_INVOKABLE void estimateTransactionFeeAsync(const QString &destination,
|
// void estimateTransactionFeeAsync(const QString &destination,
|
||||||
// quint64 amount,
|
// quint64 amount,
|
||||||
// PendingTransaction::Priority priority,
|
// PendingTransaction::Priority priority,
|
||||||
// const QJSValue &callback);
|
// const QJSValue &callback);
|
||||||
|
@ -376,46 +354,41 @@ public:
|
||||||
CoinsModel *coinsModel() const;
|
CoinsModel *coinsModel() const;
|
||||||
|
|
||||||
//! generate payment id
|
//! generate payment id
|
||||||
Q_INVOKABLE QString generatePaymentId() const;
|
QString generatePaymentId() const;
|
||||||
|
|
||||||
//! integrated address
|
//! integrated address
|
||||||
Q_INVOKABLE QString integratedAddress(const QString &paymentId) const;
|
QString integratedAddress(const QString &paymentId) const;
|
||||||
|
|
||||||
//! signing a message
|
//! signing a message
|
||||||
Q_INVOKABLE 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
|
||||||
Q_INVOKABLE 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
|
//! Parse URI
|
||||||
Q_INVOKABLE 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);
|
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);
|
||||||
|
|
||||||
//! saved payment id
|
|
||||||
QString paymentId() const;
|
|
||||||
|
|
||||||
void setPaymentId(const QString &paymentId);
|
|
||||||
|
|
||||||
//! Namespace your cacheAttribute keys to avoid collisions
|
//! Namespace your cacheAttribute keys to avoid collisions
|
||||||
Q_INVOKABLE bool setCacheAttribute(const QString &key, const QString &val);
|
bool setCacheAttribute(const QString &key, const QString &val);
|
||||||
Q_INVOKABLE QString getCacheAttribute(const QString &key) const;
|
QString getCacheAttribute(const QString &key) const;
|
||||||
|
|
||||||
Q_INVOKABLE bool setUserNote(const QString &txid, const QString ¬e);
|
bool setUserNote(const QString &txid, const QString ¬e);
|
||||||
Q_INVOKABLE QString getUserNote(const QString &txid) const;
|
QString getUserNote(const QString &txid) const;
|
||||||
Q_INVOKABLE QString getTxKey(const QString &txid) const;
|
QString getTxKey(const QString &txid) const;
|
||||||
//Q_INVOKABLE void getTxKeyAsync(const QString &txid, const QJSValue &callback);
|
//void getTxKeyAsync(const QString &txid, const QJSValue &callback);
|
||||||
Q_INVOKABLE QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
|
QString checkTxKey(const QString &txid, const QString &tx_key, const QString &address);
|
||||||
Q_INVOKABLE TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const;
|
TxProof getTxProof(const QString &txid, const QString &address, const QString &message) const;
|
||||||
// Q_INVOKABLE void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback);
|
// void getTxProofAsync(const QString &txid, const QString &address, const QString &message, const QJSValue &callback);
|
||||||
//Q_INVOKABLE QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
|
//QString checkTxProof(const QString &txid, const QString &address, const QString &message, const QString &signature);
|
||||||
Q_INVOKABLE TxProofResult 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);
|
||||||
Q_INVOKABLE TxProof getSpendProof(const QString &txid, const QString &message) const;
|
TxProof getSpendProof(const QString &txid, const QString &message) const;
|
||||||
// Q_INVOKABLE void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback);
|
// void getSpendProofAsync(const QString &txid, const QString &message, const QJSValue &callback);
|
||||||
Q_INVOKABLE QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
|
QPair<bool, bool> checkSpendProof(const QString &txid, const QString &message, const QString &signature) const;
|
||||||
// Rescan spent outputs
|
// Rescan spent outputs
|
||||||
Q_INVOKABLE bool rescanSpent();
|
bool rescanSpent();
|
||||||
|
|
||||||
// check if fork rules should be used
|
// check if fork rules should be used
|
||||||
Q_INVOKABLE bool useForkRules(quint8 version, quint64 earlyBlocks = 0) const;
|
bool useForkRules(quint8 version, quint64 earlyBlocks = 0) const;
|
||||||
|
|
||||||
//! Get wallet keys
|
//! Get wallet keys
|
||||||
QString getSecretViewKey() const {return QString::fromStdString(m_walletImpl->secretViewKey());}
|
QString getSecretViewKey() const {return QString::fromStdString(m_walletImpl->secretViewKey());}
|
||||||
|
@ -427,30 +400,29 @@ public:
|
||||||
void setWalletCreationHeight(quint64 height);
|
void setWalletCreationHeight(quint64 height);
|
||||||
|
|
||||||
QString getDaemonLogPath() const;
|
QString getDaemonLogPath() const;
|
||||||
QString getWalletLogPath() const;
|
|
||||||
|
|
||||||
// Blackalled outputs
|
// Blackalled outputs
|
||||||
Q_INVOKABLE bool blackballOutput(const QString &amount, const QString &offset);
|
bool blackballOutput(const QString &amount, const QString &offset);
|
||||||
Q_INVOKABLE bool blackballOutputs(const QList<QString> &outputs, bool add);
|
bool blackballOutputs(const QList<QString> &outputs, bool add);
|
||||||
Q_INVOKABLE bool blackballOutputs(const QString &filename, bool add);
|
bool blackballOutputs(const QString &filename, bool add);
|
||||||
Q_INVOKABLE bool unblackballOutput(const QString &amount, const QString &offset);
|
bool unblackballOutput(const QString &amount, const QString &offset);
|
||||||
|
|
||||||
// Rings
|
// Rings
|
||||||
Q_INVOKABLE QString getRing(const QString &key_image);
|
QString getRing(const QString &key_image);
|
||||||
Q_INVOKABLE QString getRings(const QString &txid);
|
QString getRings(const QString &txid);
|
||||||
Q_INVOKABLE bool setRing(const QString &key_image, const QString &ring, bool relative);
|
bool setRing(const QString &key_image, const QString &ring, bool relative);
|
||||||
|
|
||||||
// key reuse mitigation options
|
// key reuse mitigation options
|
||||||
Q_INVOKABLE void segregatePreForkOutputs(bool segregate);
|
void segregatePreForkOutputs(bool segregate);
|
||||||
Q_INVOKABLE void segregationHeight(quint64 height);
|
void segregationHeight(quint64 height);
|
||||||
Q_INVOKABLE void keyReuseMitigation2(bool mitigation);
|
void keyReuseMitigation2(bool mitigation);
|
||||||
|
|
||||||
// Passphrase entry for hardware wallets
|
// Passphrase entry for hardware wallets
|
||||||
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
|
void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
|
||||||
virtual void onWalletPassphraseNeeded(bool on_device) override;
|
virtual void onWalletPassphraseNeeded(bool on_device) override;
|
||||||
|
|
||||||
Q_INVOKABLE quint64 getBytesReceived() const;
|
quint64 getBytesReceived() const;
|
||||||
Q_INVOKABLE quint64 getBytesSent() const;
|
quint64 getBytesSent() const;
|
||||||
|
|
||||||
// TODO: setListenter() when it implemented in API
|
// TODO: setListenter() when it implemented in API
|
||||||
signals:
|
signals:
|
||||||
|
@ -510,6 +482,8 @@ private:
|
||||||
void setProxyAddress(QString address);
|
void setProxyAddress(QString address);
|
||||||
void startRefreshThread();
|
void startRefreshThread();
|
||||||
|
|
||||||
|
void onNewBlock(uint64_t height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class WalletManager;
|
friend class WalletManager;
|
||||||
friend class WalletListenerImpl;
|
friend class WalletListenerImpl;
|
||||||
|
@ -523,17 +497,13 @@ private:
|
||||||
QString m_paymentId;
|
QString m_paymentId;
|
||||||
AddressBook * m_addressBook;
|
AddressBook * m_addressBook;
|
||||||
mutable AddressBookModel * m_addressBookModel;
|
mutable AddressBookModel * m_addressBookModel;
|
||||||
mutable QElapsedTimer m_daemonBlockChainHeightTime;
|
|
||||||
mutable quint64 m_daemonBlockChainHeight;
|
mutable quint64 m_daemonBlockChainHeight;
|
||||||
int m_daemonBlockChainHeightTtl;
|
|
||||||
mutable QElapsedTimer m_daemonBlockChainTargetHeightTime;
|
|
||||||
mutable quint64 m_daemonBlockChainTargetHeight;
|
mutable quint64 m_daemonBlockChainTargetHeight;
|
||||||
int m_daemonBlockChainTargetHeightTtl;
|
|
||||||
mutable ConnectionStatus m_connectionStatus;
|
mutable ConnectionStatus m_connectionStatus;
|
||||||
int m_connectionStatusTtl;
|
|
||||||
mutable QElapsedTimer m_connectionStatusTime;
|
|
||||||
bool m_disconnected;
|
bool m_disconnected;
|
||||||
mutable bool m_initialized;
|
mutable bool m_initialized;
|
||||||
uint32_t m_currentSubaddressAccount;
|
uint32_t m_currentSubaddressAccount;
|
||||||
Subaddress * m_subaddress;
|
Subaddress * m_subaddress;
|
||||||
mutable SubaddressModel * m_subaddressModel;
|
mutable SubaddressModel * m_subaddressModel;
|
||||||
|
@ -542,8 +512,6 @@ private:
|
||||||
Coins * m_coins;
|
Coins * m_coins;
|
||||||
mutable CoinsModel * m_coinsModel;
|
mutable CoinsModel * m_coinsModel;
|
||||||
QMutex m_asyncMutex;
|
QMutex m_asyncMutex;
|
||||||
QMutex m_connectionStatusMutex;
|
|
||||||
bool m_connectionStatusRunning;
|
|
||||||
QString m_daemonUsername;
|
QString m_daemonUsername;
|
||||||
QString m_daemonPassword;
|
QString m_daemonPassword;
|
||||||
QString m_proxyAddress;
|
QString m_proxyAddress;
|
||||||
|
|
|
@ -32,6 +32,7 @@ void WalletListenerImpl::unconfirmedMoneyReceived(const std::string &txId, uint6
|
||||||
void WalletListenerImpl::newBlock(uint64_t height)
|
void WalletListenerImpl::newBlock(uint64_t height)
|
||||||
{
|
{
|
||||||
// qDebug() << __FUNCTION__;
|
// qDebug() << __FUNCTION__;
|
||||||
|
m_wallet->onNewBlock(height);
|
||||||
emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
|
emit m_wallet->newBlock(height, m_wallet->daemonBlockChainTargetHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -481,3 +481,26 @@ void WalletManager::onPassphraseEntered(const QString &passphrase, bool enter_on
|
||||||
m_passphraseReceiver->onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
m_passphraseReceiver->onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString WalletManager::proxyAddress() const
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_proxyMutex);
|
||||||
|
return m_proxyAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletManager::setProxyAddress(QString address)
|
||||||
|
{
|
||||||
|
m_scheduler.run([this, address] {
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_proxyMutex);
|
||||||
|
|
||||||
|
if (!m_pimpl->setProxy(address.toStdString()))
|
||||||
|
{
|
||||||
|
qCritical() << "Failed to set proxy address" << address;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_proxyAddress = std::move(address);
|
||||||
|
}
|
||||||
|
emit proxyAddressChanged();
|
||||||
|
});
|
||||||
|
}
|
|
@ -172,6 +172,9 @@ public:
|
||||||
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
|
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort=false);
|
||||||
virtual void onWalletPassphraseNeeded(bool on_device) override;
|
virtual void onWalletPassphraseNeeded(bool on_device) override;
|
||||||
|
|
||||||
|
QString proxyAddress() const;
|
||||||
|
void setProxyAddress(QString address);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void walletOpened(Wallet * wallet);
|
void walletOpened(Wallet * wallet);
|
||||||
|
@ -186,6 +189,7 @@ signals:
|
||||||
const QString &firstSigner,
|
const QString &firstSigner,
|
||||||
const QString &secondSigner) const;
|
const QString &secondSigner) const;
|
||||||
void miningStatus(bool isMining) const;
|
void miningStatus(bool isMining) const;
|
||||||
|
void proxyAddressChanged() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
private:
|
private:
|
||||||
|
@ -202,6 +206,8 @@ private:
|
||||||
QPointer<Wallet> m_currentWallet;
|
QPointer<Wallet> m_currentWallet;
|
||||||
PassphraseReceiver * m_passphraseReceiver;
|
PassphraseReceiver * m_passphraseReceiver;
|
||||||
QMutex m_mutex_passphraseReceiver;
|
QMutex m_mutex_passphraseReceiver;
|
||||||
|
QString m_proxyAddress;
|
||||||
|
mutable QMutex m_proxyMutex;
|
||||||
FutureScheduler m_scheduler;
|
FutureScheduler m_scheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -102,9 +102,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
|
|
||||||
if(cliMode) {
|
if(cliMode) {
|
||||||
QCoreApplication cli_app(argc, argv);
|
QCoreApplication cli_app(argc, argv);
|
||||||
QCoreApplication::setApplicationName("feather");
|
QCoreApplication::setApplicationName("FeatherWallet");
|
||||||
QCoreApplication::setOrganizationDomain("featherwallet.org");
|
|
||||||
QCoreApplication::setOrganizationName("featherwallet.org");
|
|
||||||
|
|
||||||
auto *ctx = new AppContext(&parser);
|
auto *ctx = new AppContext(&parser);
|
||||||
|
|
||||||
|
@ -136,9 +134,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||||
|
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
QApplication::setApplicationName("feather");
|
QApplication::setApplicationName("FeatherWallet");
|
||||||
QApplication::setOrganizationDomain("featherwallet.org");
|
|
||||||
QApplication::setOrganizationName("featherwallet.org");
|
|
||||||
|
|
||||||
parser.process(app); // Parse again for --help and --version
|
parser.process(app); // Parse again for --help and --version
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "dialog/txconfdialog.h"
|
#include "dialog/txconfdialog.h"
|
||||||
|
@ -37,6 +38,12 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
|
||||||
pMainWindow = this;
|
pMainWindow = this;
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// Preload icons for better performance
|
||||||
|
m_statusDisconnected = QIcon(":/assets/images/status_disconnected.svg");
|
||||||
|
m_statusConnecting = QIcon(":/assets/images/status_lagging.svg");
|
||||||
|
m_statusSynchronizing = QIcon(":/assets/images/status_waiting.svg");
|
||||||
|
m_statusSynchronized = QIcon(":/assets/images/status_connected.svg");
|
||||||
|
|
||||||
m_windowSettings = new Settings(this);
|
m_windowSettings = new Settings(this);
|
||||||
m_aboutDialog = new AboutDialog(this);
|
m_aboutDialog = new AboutDialog(this);
|
||||||
m_windowCalc = new CalcWindow(this);
|
m_windowCalc = new CalcWindow(this);
|
||||||
|
@ -244,7 +251,11 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
|
||||||
if(config()->get(Config::warnOnAlpha).toBool()) {
|
if(config()->get(Config::warnOnAlpha).toBool()) {
|
||||||
QString warning = "Feather Wallet is currently in beta.\n\nPlease report any bugs "
|
QString warning = "Feather Wallet is currently in beta.\n\nPlease report any bugs "
|
||||||
"you encounter on our Git repository, IRC or on /r/FeatherWallet.";
|
"you encounter on our Git repository, IRC or on /r/FeatherWallet.";
|
||||||
QMessageBox::warning(this, "Beta Warning", warning);
|
QMessageBox warningMb(this);
|
||||||
|
warningMb.setWindowTitle("Beta Warning");
|
||||||
|
warningMb.setText(warning);
|
||||||
|
this->centerWidget(warningMb);
|
||||||
|
warningMb.exec();
|
||||||
config()->set(Config::warnOnAlpha, false);
|
config()->set(Config::warnOnAlpha, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,10 +371,14 @@ void MainWindow::initMain() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->setEnabled(false);
|
this->setEnabled(true);
|
||||||
this->show();
|
this->show();
|
||||||
m_wizard = this->createWizard(WalletWizard::Page_Menu);
|
m_wizard = this->createWizard(WalletWizard::Page_Menu);
|
||||||
m_wizard->show();
|
m_wizard->show();
|
||||||
|
|
||||||
|
// wizard won't spawn on top of MainWindow without this dumb pattern
|
||||||
|
this->setEnabled(false);
|
||||||
|
m_wizard->setEnabled(true);
|
||||||
this->touchbarShowWizard();
|
this->touchbarShowWizard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,7 +673,6 @@ void MainWindow::setStatusText(const QString &text, bool override, int timeout)
|
||||||
void MainWindow::onSynchronized() {
|
void MainWindow::onSynchronized() {
|
||||||
this->updateNetStats();
|
this->updateNetStats();
|
||||||
this->setStatusText("Synchronized");
|
this->setStatusText("Synchronized");
|
||||||
this->onConnectionStatusChanged(Wallet::ConnectionStatus_Connected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onBlockchainSync(int height, int target) {
|
void MainWindow::onBlockchainSync(int height, int target) {
|
||||||
|
@ -679,34 +693,32 @@ void MainWindow::onConnectionStatusChanged(int status)
|
||||||
|
|
||||||
// Update connection info in status bar.
|
// Update connection info in status bar.
|
||||||
|
|
||||||
QString statusIcon;
|
QIcon *icon;
|
||||||
QString statusMsg;
|
|
||||||
switch(status){
|
switch(status){
|
||||||
case Wallet::ConnectionStatus_Disconnected:
|
case Wallet::ConnectionStatus_Disconnected:
|
||||||
statusIcon = ":/assets/images/status_disconnected.svg";
|
icon = &m_statusDisconnected;
|
||||||
this->setStatusText("Disconnected");
|
this->setStatusText("Disconnected");
|
||||||
break;
|
break;
|
||||||
case Wallet::ConnectionStatus_Connected:
|
|
||||||
if (m_ctx->currentWallet->synchronized()) {
|
|
||||||
statusIcon = ":/assets/images/status_connected.svg";
|
|
||||||
} else {
|
|
||||||
statusIcon = ":/assets/images/status_waiting.svg";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Wallet::ConnectionStatus_Connecting:
|
case Wallet::ConnectionStatus_Connecting:
|
||||||
statusIcon = ":/assets/images/status_lagging.svg";
|
icon = &m_statusConnecting;
|
||||||
this->setStatusText("Connecting to daemon");
|
this->setStatusText("Connecting to node");
|
||||||
break;
|
break;
|
||||||
case Wallet::ConnectionStatus_WrongVersion:
|
case Wallet::ConnectionStatus_WrongVersion:
|
||||||
statusIcon = ":/assets/images/status_disconnected.svg";
|
icon = &m_statusDisconnected;
|
||||||
this->setStatusText("Incompatible daemon");
|
this->setStatusText("Incompatible node");
|
||||||
|
break;
|
||||||
|
case Wallet::ConnectionStatus_Synchronizing:
|
||||||
|
icon = &m_statusSynchronizing;
|
||||||
|
break;
|
||||||
|
case Wallet::ConnectionStatus_Synchronized:
|
||||||
|
icon = &m_statusSynchronized;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
statusIcon = ":/assets/images/status_disconnected.svg";
|
icon = &m_statusDisconnected;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_statusBtnConnectionStatusIndicator->setIcon(QIcon(statusIcon));
|
m_statusBtnConnectionStatusIndicator->setIcon(*icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address) {
|
void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVector<QString> &address) {
|
||||||
|
@ -854,20 +866,13 @@ void MainWindow::showSeedDialog() {
|
||||||
|
|
||||||
void MainWindow::showConnectionStatusDialog() {
|
void MainWindow::showConnectionStatusDialog() {
|
||||||
auto status = m_ctx->currentWallet->connectionStatus();
|
auto status = m_ctx->currentWallet->connectionStatus();
|
||||||
bool synchronized = m_ctx->currentWallet->synchronized();
|
bool synchronized = m_ctx->currentWallet->isSynchronized();
|
||||||
|
|
||||||
QString statusMsg;
|
QString statusMsg;
|
||||||
switch(status){
|
switch(status){
|
||||||
case Wallet::ConnectionStatus_Disconnected:
|
case Wallet::ConnectionStatus_Disconnected:
|
||||||
statusMsg = "Wallet is disconnected from daemon.";
|
statusMsg = "Wallet is disconnected from daemon.";
|
||||||
break;
|
break;
|
||||||
case Wallet::ConnectionStatus_Connected: {
|
|
||||||
auto node = m_ctx->nodes->connection();
|
|
||||||
statusMsg = QString("Wallet is connected to %1").arg(node.full);
|
|
||||||
if (synchronized)
|
|
||||||
statusMsg += " and synchronized";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Wallet::ConnectionStatus_Connecting: {
|
case Wallet::ConnectionStatus_Connecting: {
|
||||||
auto node = m_ctx->nodes->connection();
|
auto node = m_ctx->nodes->connection();
|
||||||
statusMsg = QString("Wallet is connecting to %1").arg(node.full);
|
statusMsg = QString("Wallet is connecting to %1").arg(node.full);
|
||||||
|
@ -876,6 +881,15 @@ void MainWindow::showConnectionStatusDialog() {
|
||||||
case Wallet::ConnectionStatus_WrongVersion:
|
case Wallet::ConnectionStatus_WrongVersion:
|
||||||
statusMsg = "Wallet is connected to incompatible daemon.";
|
statusMsg = "Wallet is connected to incompatible daemon.";
|
||||||
break;
|
break;
|
||||||
|
case Wallet::ConnectionStatus_Synchronizing: {
|
||||||
|
auto node = m_ctx->nodes->connection();
|
||||||
|
statusMsg = QString("Wallet is connected to %1").arg(node.full);
|
||||||
|
}
|
||||||
|
case Wallet::ConnectionStatus_Synchronized: {
|
||||||
|
if (synchronized)
|
||||||
|
statusMsg += " and synchronized";
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
statusMsg = "Unknown connection status (this should never happen).";
|
statusMsg = "Unknown connection status (this should never happen).";
|
||||||
}
|
}
|
||||||
|
@ -961,28 +975,6 @@ void MainWindow::menuWalletCloseClicked() {
|
||||||
m_ctx->closeWallet(true, true);
|
m_ctx->closeWallet(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::menuWalletOpenClicked() {
|
|
||||||
auto walletPath = config()->get(Config::walletPath).toString();
|
|
||||||
if(walletPath.isEmpty())
|
|
||||||
walletPath = m_ctx->defaultWalletDir;
|
|
||||||
QString path = QFileDialog::getOpenFileName(this, "Select your wallet file", walletPath, "Wallet file (*.keys)");
|
|
||||||
if(path.isEmpty()) return;
|
|
||||||
|
|
||||||
QFileInfo infoPath(path);
|
|
||||||
if(!infoPath.isReadable()) {
|
|
||||||
QMessageBox::warning(this, "Cannot read wallet file", "Permission error.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(path == m_ctx->walletPath) {
|
|
||||||
QMessageBox::warning(this, "Wallet already opened", "Please open another wallet.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ctx->closeWallet(false);
|
|
||||||
m_ctx->onOpenWallet(path, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::menuAboutClicked() {
|
void MainWindow::menuAboutClicked() {
|
||||||
m_aboutDialog->show();
|
m_aboutDialog->show();
|
||||||
}
|
}
|
||||||
|
@ -1318,7 +1310,7 @@ void MainWindow::updateNetStats() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ctx->currentWallet->connectionStatus() == Wallet::ConnectionStatus_Connected && m_ctx->currentWallet->synchronized()) {
|
if (m_ctx->currentWallet->connectionStatus() == Wallet::ConnectionStatus_Synchronized) {
|
||||||
m_statusLabelNetStats->setText("");
|
m_statusLabelNetStats->setText("");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1357,6 +1349,16 @@ void MainWindow::bringToFront() {
|
||||||
activateWindow();
|
activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::centerWidget(QWidget &w) {
|
||||||
|
QScreen *s = QGuiApplication::primaryScreen();
|
||||||
|
|
||||||
|
const QRect sr = s->geometry();
|
||||||
|
const QRect wr({}, w.frameSize().boundedTo(sr.size()));
|
||||||
|
|
||||||
|
w.resize(wr.size());
|
||||||
|
w.move(sr.center() - wr.center());
|
||||||
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "dialog/keysdialog.h"
|
#include "dialog/keysdialog.h"
|
||||||
#include "dialog/aboutdialog.h"
|
#include "dialog/aboutdialog.h"
|
||||||
#include "dialog/restoredialog.h"
|
#include "dialog/restoredialog.h"
|
||||||
|
#include "libwalletqt/Wallet.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
@ -117,7 +118,6 @@ public slots:
|
||||||
void onWalletCreatedError(const QString &err);
|
void onWalletCreatedError(const QString &err);
|
||||||
void onWalletCreated(Wallet *wallet);
|
void onWalletCreated(Wallet *wallet);
|
||||||
void menuWalletCloseClicked();
|
void menuWalletCloseClicked();
|
||||||
void menuWalletOpenClicked();
|
|
||||||
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
|
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
|
||||||
void onViewOnBlockExplorer(const QString &txid);
|
void onViewOnBlockExplorer(const QString &txid);
|
||||||
void onResendTransaction(const QString &txid);
|
void onResendTransaction(const QString &txid);
|
||||||
|
@ -173,6 +173,7 @@ private:
|
||||||
void showBalanceDialog();
|
void showBalanceDialog();
|
||||||
QString statusDots();
|
QString statusDots();
|
||||||
void bringToFront();
|
void bringToFront();
|
||||||
|
void centerWidget(QWidget &w);
|
||||||
|
|
||||||
WalletWizard *createWizard(WalletWizard::Page startPage);
|
WalletWizard *createWizard(WalletWizard::Page startPage);
|
||||||
|
|
||||||
|
@ -223,6 +224,11 @@ private:
|
||||||
bool m_statusOverrideActive = false;
|
bool m_statusOverrideActive = false;
|
||||||
QTimer m_txTimer;
|
QTimer m_txTimer;
|
||||||
|
|
||||||
|
QIcon m_statusDisconnected;
|
||||||
|
QIcon m_statusConnecting;
|
||||||
|
QIcon m_statusSynchronizing;
|
||||||
|
QIcon m_statusSynchronized;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void menuToggleTabVisible(const QString &key);
|
void menuToggleTabVisible(const QString &key);
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,6 +85,8 @@ void HistoryView::setSearchMode(bool mode) {
|
||||||
|
|
||||||
if (mode) {
|
if (mode) {
|
||||||
header()->showSection(TransactionHistoryModel::TxID);
|
header()->showSection(TransactionHistoryModel::TxID);
|
||||||
|
} else {
|
||||||
|
header()->hideSection(TransactionHistoryModel::TxID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +101,8 @@ bool HistoryView::setViewState(const QByteArray& state)
|
||||||
header()->setSortIndicator(-1, Qt::AscendingOrder);
|
header()->setSortIndicator(-1, Qt::AscendingOrder);
|
||||||
bool status = header()->restoreState(state);
|
bool status = header()->restoreState(state);
|
||||||
m_columnsNeedRelayout = state.isEmpty();
|
m_columnsNeedRelayout = state.isEmpty();
|
||||||
|
|
||||||
|
m_showTxidColumn = !header()->isSectionHidden(TransactionHistoryModel::TxID);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ private:
|
||||||
TransactionHistoryProxyModel* m_model;
|
TransactionHistoryProxyModel* m_model;
|
||||||
bool m_inSearchMode = false;
|
bool m_inSearchMode = false;
|
||||||
bool m_columnsNeedRelayout = true;
|
bool m_columnsNeedRelayout = true;
|
||||||
|
bool m_showTxidColumn = false;
|
||||||
|
|
||||||
QMenu* m_headerMenu;
|
QMenu* m_headerMenu;
|
||||||
QActionGroup* m_columnActions;
|
QActionGroup* m_columnActions;
|
||||||
|
|
|
@ -100,7 +100,7 @@ void SendWidget::fillAddress(const QString &address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendWidget::sendClicked() {
|
void SendWidget::sendClicked() {
|
||||||
if (m_ctx->currentWallet->connectionStatus() != Wallet::ConnectionStatus_Connected) {
|
if (!m_ctx->currentWallet->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.");
|
||||||
|
|
|
@ -50,6 +50,9 @@
|
||||||
<property name="horizontalScrollBarPolicy">
|
<property name="horizontalScrollBarPolicy">
|
||||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="tabChangesFocus">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="lineWrapMode">
|
<property name="lineWrapMode">
|
||||||
<enum>QPlainTextEdit::NoWrap</enum>
|
<enum>QPlainTextEdit::NoWrap</enum>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -111,23 +111,8 @@ Config::Config(QObject* parent)
|
||||||
{
|
{
|
||||||
QDir configDir = Config::defaultConfigDir();
|
QDir configDir = Config::defaultConfigDir();
|
||||||
|
|
||||||
QString portablePath = QCoreApplication::applicationDirPath().append("/%1");
|
if (!QDir().mkpath(configDir.path())) {
|
||||||
if (QFile::exists(portablePath.arg(".portable"))) {
|
qWarning() << "Unable to create config path: " << configDir.path();
|
||||||
init(portablePath.arg("feather_data/settings.json"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTails = TailsOS::detect();
|
|
||||||
if (isTails) { // #if defined(PORTABLE)
|
|
||||||
QString appImagePath = qgetenv("APPIMAGE");
|
|
||||||
QFileInfo appImageDir(appImagePath);
|
|
||||||
|
|
||||||
QDir portablePath(appImageDir.absoluteDir().path() + "/feather_data");
|
|
||||||
if (portablePath.mkpath(".")) {
|
|
||||||
configDir = portablePath;
|
|
||||||
} else {
|
|
||||||
qCritical() << "Unable to create portable directory: " << portablePath.path();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString configPath = configDir.filePath("settings.json");
|
QString configPath = configDir.filePath("settings.json");
|
||||||
|
@ -136,6 +121,26 @@ Config::Config(QObject* parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir Config::defaultConfigDir() {
|
QDir Config::defaultConfigDir() {
|
||||||
|
QString portablePath = QCoreApplication::applicationDirPath().append("/%1");
|
||||||
|
if (QFile::exists(portablePath.arg(".portable"))) {
|
||||||
|
return portablePath.arg("feather_data");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TailsOS::detect()) {
|
||||||
|
QString path = []{
|
||||||
|
QString appImagePath = qgetenv("APPIMAGE");
|
||||||
|
if (appImagePath.isEmpty()) {
|
||||||
|
qDebug() << "Not an appimage, using currentPath()";
|
||||||
|
return QDir::currentPath() + "/.feather/.config/feather";
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo appImageDir(appImagePath);
|
||||||
|
return appImageDir.absoluteDir().path() + "/.feather/.config/feather";
|
||||||
|
}();
|
||||||
|
|
||||||
|
return QDir(path);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
return QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
return QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
|
||||||
#elif defined(Q_OS_MACOS)
|
#elif defined(Q_OS_MACOS)
|
||||||
|
|
|
@ -69,7 +69,12 @@ void WalletKeysFilesModel::refresh() {
|
||||||
|
|
||||||
void WalletKeysFilesModel::updateDirectories() {
|
void WalletKeysFilesModel::updateDirectories() {
|
||||||
this->walletDirectories.clear();
|
this->walletDirectories.clear();
|
||||||
this->walletDirectories << m_ctx->defaultWalletDir; // TODO
|
QDir defaultWalletDir = QDir(Utils::defaultWalletDir());
|
||||||
|
QString walletDir = defaultWalletDir.path();
|
||||||
|
defaultWalletDir.cdUp();
|
||||||
|
QString walletDirRoot = defaultWalletDir.path();
|
||||||
|
this->walletDirectories << walletDir;
|
||||||
|
this->walletDirectories << walletDirRoot;
|
||||||
auto walletPath = config()->get(Config::walletPath).toString();
|
auto walletPath = config()->get(Config::walletPath).toString();
|
||||||
if(!walletPath.isEmpty() && Utils::fileExists(walletPath)) {
|
if(!walletPath.isEmpty() && Utils::fileExists(walletPath)) {
|
||||||
QDir d = QFileInfo(walletPath).absoluteDir();
|
QDir d = QFileInfo(walletPath).absoluteDir();
|
||||||
|
|
|
@ -183,7 +183,7 @@ void Nodes::autoConnect(bool forceReconnect) {
|
||||||
this->connectToNode(node);
|
this->connectToNode(node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (status == Wallet::ConnectionStatus_Connected && m_connection.isConnecting) {
|
else if ((status == Wallet::ConnectionStatus_Synchronizing || status == Wallet::ConnectionStatus_Synchronized) && m_connection.isConnecting) {
|
||||||
qInfo() << QString("Node connected to %1").arg(m_connection.address);
|
qInfo() << QString("Node connected to %1").arg(m_connection.address);
|
||||||
|
|
||||||
// set current connection object
|
// set current connection object
|
||||||
|
|
|
@ -11,7 +11,7 @@ TxFiatHistory::TxFiatHistory(int genesis_timestamp, const QString &configDirecto
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_genesis_timestamp(genesis_timestamp),
|
m_genesis_timestamp(genesis_timestamp),
|
||||||
m_configDirectory(configDirectory) {
|
m_configDirectory(configDirectory) {
|
||||||
m_databasePath = QString("%1fiatHistory.db").arg(configDirectory);
|
m_databasePath = QString("%1/fiatHistory.db").arg(configDirectory);
|
||||||
this->loadDatabase();
|
this->loadDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -481,6 +481,26 @@ bool Utils::isTorsocks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Utils::defaultWalletDir() {
|
QString Utils::defaultWalletDir() {
|
||||||
|
QString portablePath = QCoreApplication::applicationDirPath().append("/%1");
|
||||||
|
if (QFile::exists(portablePath.arg(".portable"))) {
|
||||||
|
return portablePath.arg("feather_data/wallets");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TailsOS::detect()) {
|
||||||
|
QString path = []{
|
||||||
|
QString appImagePath = qgetenv("APPIMAGE");
|
||||||
|
if (appImagePath.isEmpty()) {
|
||||||
|
qDebug() << "Not an appimage, using currentPath()";
|
||||||
|
return QDir::currentPath() + "/.feather/Monero/wallets";
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo appImageDir(appImagePath);
|
||||||
|
return appImageDir.absoluteDir().path() + "/.feather/Monero/wallets";
|
||||||
|
}();
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX) or defined(Q_OS_MAC)
|
#if defined(Q_OS_LINUX) or defined(Q_OS_MAC)
|
||||||
return QString("%1/Monero/wallets").arg(QDir::homePath());
|
return QString("%1/Monero/wallets").arg(QDir::homePath());
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
|
|
|
@ -88,6 +88,12 @@ void WalletWizard::createWallet() {
|
||||||
|
|
||||||
auto seed = FeatherSeed(m_ctx->restoreHeights[m_ctx->networkType], QString::fromStdString(globals::coinName), m_ctx->seedLanguage, m_wizardFields.seed.split(" "));
|
auto seed = FeatherSeed(m_ctx->restoreHeights[m_ctx->networkType], QString::fromStdString(globals::coinName), m_ctx->seedLanguage, m_wizardFields.seed.split(" "));
|
||||||
|
|
||||||
|
if (m_wizardFields.mode == WizardMode::CreateWallet && m_ctx->heights.contains(m_ctx->networkType)) {
|
||||||
|
int restoreHeight = m_ctx->heights[m_ctx->networkType];
|
||||||
|
qInfo() << "New wallet, setting restore height to latest blockheight: " << restoreHeight;
|
||||||
|
seed.setRestoreHeight(restoreHeight);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_wizardFields.mode == WizardMode::RestoreFromSeed && m_wizardFields.seedType == SeedType::MONERO)
|
if (m_wizardFields.mode == WizardMode::RestoreFromSeed && m_wizardFields.seedType == SeedType::MONERO)
|
||||||
seed.setRestoreHeight(m_wizardFields.restoreHeight);
|
seed.setRestoreHeight(m_wizardFields.restoreHeight);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue