mirror of
https://github.com/feather-wallet/feather.git
synced 2025-03-12 09:37:47 +00:00
Beta-6 fixes
This commit is contained in:
parent
d4cfa05157
commit
663960af2f
28 changed files with 201 additions and 95 deletions
|
@ -31,7 +31,7 @@ if(DEBUG)
|
|||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
endif()
|
||||
|
||||
set(MONERO_HEAD "626f1b4ba1c1a490ca97fe265230aea84eac0ed2")
|
||||
set(MONERO_HEAD "36fb05da3394505f8033ceb8806b28909617696f")
|
||||
set(BUILD_GUI_DEPS ON)
|
||||
set(ARCH "x86-64")
|
||||
set(BUILD_64 ON)
|
||||
|
|
14
Dockerfile
14
Dockerfile
|
@ -323,17 +323,17 @@ RUN rm /usr/lib/x86_64-linux-gnu/libX11.a && \
|
|||
cd ../../../.. && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b v1.0.23 --depth 1 https://github.com/libusb/libusb && \
|
||||
RUN git clone -b v1.0.24 --depth 1 https://github.com/libusb/libusb && \
|
||||
cd libusb && \
|
||||
git reset --hard e782eeb2514266f6738e242cdcb18e3ae1ed06fa && \
|
||||
git reset --hard c6a35c56016ea2ab2f19115d2ea1e85e0edae155 && \
|
||||
./autogen.sh --disable-shared --enable-static && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b hidapi-0.9.0 --depth 1 https://github.com/libusb/hidapi && \
|
||||
RUN git clone -b hidapi-0.10.1 --depth 1 https://github.com/libusb/hidapi && \
|
||||
cd hidapi && \
|
||||
git reset --hard 7da5cc91fc0d2dbe4df4f08cd31f6ca1a262418f && \
|
||||
git reset --hard f6d0073fcddbdda24549199445e844971d3c9cef && \
|
||||
./bootstrap && \
|
||||
./configure --disable-shared --enable-static && \
|
||||
make -j$THREADS && \
|
||||
|
@ -384,9 +384,9 @@ RUN git clone -b v3.18.4 --depth 1 https://github.com/Kitware/CMake && \
|
|||
make -j$THREADS install && \
|
||||
rm -rf $(pwd)
|
||||
|
||||
RUN git clone -b v4.0.2 --depth 1 https://github.com/fukuchi/libqrencode.git && \
|
||||
RUN git clone -b v4.1.1 --depth 1 https://github.com/fukuchi/libqrencode.git && \
|
||||
cd libqrencode && \
|
||||
git reset --hard 59ee597f913fcfda7a010a6e106fbee2595f68e4 && \
|
||||
git reset --hard 715e29fd4cd71b6e452ae0f4e36d917b43122ce8 && \
|
||||
cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/usr . && \
|
||||
make -j$THREADS && \
|
||||
make -j$THREADS install && \
|
||||
|
@ -415,7 +415,7 @@ RUN mkdir linuxdeployqt && \
|
|||
./linuxdeployqt-7-x86_64.AppImage --appimage-extract && \
|
||||
rm linuxdeployqt-7-x86_64.AppImage
|
||||
|
||||
RUN git clone https://github.com/nih-at/libzip.git && \
|
||||
RUN git clone -b v1.7.3 --depth 1 https://github.com/nih-at/libzip.git && \
|
||||
cd libzip && \
|
||||
git reset --hard 66e496489bdae81bfda8b0088172871d8fda0032 && \
|
||||
cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/usr . && \
|
||||
|
|
2
monero
2
monero
|
@ -1 +1 @@
|
|||
Subproject commit 626f1b4ba1c1a490ca97fe265230aea84eac0ed2
|
||||
Subproject commit 36fb05da3394505f8033ceb8806b28909617696f
|
|
@ -112,7 +112,7 @@ QString LocalMoneroApi::getBuySellUrl(bool buy, const QString ¤cyCode, con
|
|||
url += QString("/%1/%2").arg(countryCode, paymentMethod);
|
||||
|
||||
QUrlQuery query;
|
||||
if (!amount.isEmpty())
|
||||
if (!amount.isEmpty() && amount != "0")
|
||||
query.addQueryItem("amount", amount);
|
||||
if (page > 0)
|
||||
query.addQueryItem("page", QString::number(page));
|
||||
|
|
|
@ -84,6 +84,8 @@ AppContext::AppContext(QCommandLineParser *cmdargs) {
|
|||
|
||||
// TODO: move me
|
||||
connect(websocketNotifier(), &WebsocketNotifier::NodesReceived, this->nodes, &Nodes::onWSNodesReceived);
|
||||
|
||||
m_rpc = new DaemonRpc{this, getNetworkTor(), ""};
|
||||
}
|
||||
|
||||
void AppContext::initTor() {
|
||||
|
@ -113,7 +115,7 @@ void AppContext::onCancelTransaction(PendingTransaction *tx, const QVector<QStri
|
|||
this->currentWallet->disposeTransaction(tx);
|
||||
}
|
||||
|
||||
void AppContext::onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) const {
|
||||
void AppContext::onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) {
|
||||
if(this->currentWallet == nullptr){
|
||||
qCritical() << "Cannot create transaction; no wallet loaded";
|
||||
return;
|
||||
|
@ -125,6 +127,8 @@ void AppContext::onSweepOutput(const QString &keyImage, QString address, bool ch
|
|||
|
||||
qCritical() << "Creating transaction";
|
||||
this->currentWallet->createTransactionSingleAsync(keyImage, address, outputs, this->tx_priority);
|
||||
|
||||
emit initiateTransaction();
|
||||
}
|
||||
|
||||
void AppContext::onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all) {
|
||||
|
@ -266,8 +270,6 @@ void AppContext::commitTransaction(PendingTransaction *tx) {
|
|||
}
|
||||
|
||||
void AppContext::onMultiBroadcast(PendingTransaction *tx) {
|
||||
DaemonRpc rpc{this, getNetworkTor(), ""};
|
||||
|
||||
int count = tx->txCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
QString txData = tx->signedTxToHex(i);
|
||||
|
@ -277,8 +279,8 @@ void AppContext::onMultiBroadcast(PendingTransaction *tx) {
|
|||
|
||||
QString address = node.toURL();
|
||||
qDebug() << QString("Relaying %1 to: %2").arg(tx->txid()[i], address);
|
||||
rpc.setDaemonAddress(address);
|
||||
rpc.sendRawTransaction(txData);
|
||||
m_rpc->setDaemonAddress(address);
|
||||
m_rpc->sendRawTransaction(txData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -362,6 +364,7 @@ void AppContext::onWalletOpened(Wallet *wallet) {
|
|||
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();
|
||||
|
||||
|
@ -626,6 +629,8 @@ void AppContext::onHeightRefreshed(quint64 walletHeight, quint64 daemonHeight, q
|
|||
}
|
||||
|
||||
void AppContext::onTransactionCreated(PendingTransaction *tx, const QVector<QString> &address) {
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
for (auto &addr : address) {
|
||||
if (addr == globals::donationAddress) {
|
||||
this->donationSending = true;
|
||||
|
|
|
@ -82,7 +82,7 @@ public slots:
|
|||
void onCreateTransaction(const QString &address, quint64 amount, const QString &description, bool all);
|
||||
void onCreateTransactionMultiDest(const QVector<QString> &addresses, const QVector<quint64> &amounts, const QString &description);
|
||||
void onCancelTransaction(PendingTransaction *tx, const QVector<QString> &address);
|
||||
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs) const;
|
||||
void onSweepOutput(const QString &keyImage, QString address, bool churn, int outputs);
|
||||
void onCreateTransactionError(const QString &msg);
|
||||
void onOpenAliasResolve(const QString &openAlias);
|
||||
void onSetRestoreHeight(quint64 height);
|
||||
|
@ -140,6 +140,7 @@ signals:
|
|||
void deviceError(const QString &message);
|
||||
|
||||
private:
|
||||
DaemonRpc *m_rpc;
|
||||
QTimer m_storeTimer;
|
||||
bool m_openWalletTriedOnce = false;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,7 @@ UpdateDialog::UpdateDialog(QWidget *parent, QString version, QString downloadUrl
|
|||
}
|
||||
|
||||
void UpdateDialog::onDownloadClicked() {
|
||||
ui->label_body->setText("Downloading update..");
|
||||
ui->btn_download->hide();
|
||||
ui->progressBar->show();
|
||||
|
||||
|
@ -173,7 +174,9 @@ void UpdateDialog::onInstallUpdate() {
|
|||
zip_close(zip_archive);
|
||||
|
||||
QString applicationPath = qgetenv("APPIMAGE");
|
||||
if (applicationPath.isEmpty()) {
|
||||
if (!applicationPath.isEmpty()) {
|
||||
applicationPath = QFileInfo(applicationPath).absoluteDir().path();
|
||||
} else {
|
||||
applicationPath = QCoreApplication::applicationDirPath();
|
||||
}
|
||||
|
||||
|
@ -184,7 +187,7 @@ void UpdateDialog::onInstallUpdate() {
|
|||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::WriteOnly))
|
||||
{
|
||||
this->onInstallError("Error: Could not write to application directory");
|
||||
this->onInstallError(QString("Error: Could not write to application path: %1").arg(filePath));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -193,7 +196,9 @@ void UpdateDialog::onInstallUpdate() {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!file.setPermissions(QFile::ExeUser | QFile::ExeOwner | QFile::ReadUser | QFile::ReadOwner | QFile::WriteUser | QFile::WriteOwner)) {
|
||||
if (!file.setPermissions(QFile::ExeUser | QFile::ExeOwner | QFile::ExeGroup | QFile::ExeOther
|
||||
| QFile::ReadUser | QFile::ReadOwner
|
||||
| QFile::WriteUser | QFile::WriteOwner)) {
|
||||
this->onInstallError("Error: Unable to set executable flags");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>693</width>
|
||||
<height>612</height>
|
||||
<height>613</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -270,6 +270,9 @@
|
|||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
|
|
|
@ -18,7 +18,14 @@ SplashDialog::SplashDialog(QWidget *parent)
|
|||
this->adjustSize();
|
||||
}
|
||||
|
||||
void SplashDialog::setMessage(const QString &message) {
|
||||
ui->label_message->setText(message);
|
||||
}
|
||||
|
||||
void SplashDialog::setIcon(const QPixmap &icon) {
|
||||
ui->icon->setPixmap(icon.scaledToWidth(32, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
SplashDialog::~SplashDialog() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ public:
|
|||
explicit SplashDialog(QWidget *parent = nullptr);
|
||||
~SplashDialog() override;
|
||||
|
||||
void setMessage(const QString &message);
|
||||
void setIcon(const QPixmap &icon);
|
||||
|
||||
private:
|
||||
Ui::SplashDialog *ui;
|
||||
};
|
||||
|
|
|
@ -120,17 +120,16 @@ void TorInfoDialog::initPrivacyLevel() {
|
|||
if (m_ctx->nodes->connection().isLocal()) {
|
||||
ui->label_notice->setText("You are connected to a local node. Traffic is not routed over Tor.");
|
||||
}
|
||||
else if (Utils::isTorsocks() || WhonixOS::detect() || TailsOS::detect()) {
|
||||
ui->radio_allTorExceptNode->setEnabled(false);
|
||||
ui->radio_allTorExceptInitSync->setEnabled(false);
|
||||
|
||||
if (Utils::isTorsocks())
|
||||
ui->label_notice->setText("Feather was started with torsocks, all traffic is routed over Tor");
|
||||
else if (WhonixOS::detect())
|
||||
ui->label_notice->setText("Feather is running on Whonix, all traffic is routed over Tor");
|
||||
else if (TailsOS::detect())
|
||||
ui->label_notice->setText("Feather is running on Tails, all traffic is routed over Tor");
|
||||
} else {
|
||||
else if (Utils::isTorsocks()) {
|
||||
ui->label_notice->setText("Feather was started with torsocks, all traffic is routed over Tor");
|
||||
}
|
||||
else if (WhonixOS::detect()) {
|
||||
ui->label_notice->setText("Feather is running on Whonix, all traffic is routed over Tor");
|
||||
}
|
||||
else if (TailsOS::detect()) {
|
||||
ui->label_notice->setText("Feather is running on Tails, all traffic is routed over Tor");
|
||||
}
|
||||
else {
|
||||
ui->frame_notice->hide();
|
||||
}
|
||||
|
||||
|
|
|
@ -605,15 +605,15 @@ PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QSt
|
|||
quint64 amount, quint32 mixin_count,
|
||||
PendingTransaction::Priority priority)
|
||||
{
|
||||
pauseRefresh();
|
||||
// pauseRefresh();
|
||||
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||
dst_addr.toStdString(), payment_id.toStdString(), amount, mixin_count,
|
||||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl,0);
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl, nullptr);
|
||||
|
||||
startRefresh();
|
||||
// startRefresh();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -631,7 +631,7 @@ void Wallet::createTransactionAsync(const QString &dst_addr, const QString &paym
|
|||
PendingTransaction* Wallet::createTransactionMultiDest(const QVector<QString> &dst_addr, const QVector<quint64> &amount,
|
||||
PendingTransaction::Priority priority)
|
||||
{
|
||||
pauseRefresh();
|
||||
// pauseRefresh();
|
||||
|
||||
std::vector<std::string> dests;
|
||||
for (auto &addr : dst_addr) {
|
||||
|
@ -647,7 +647,7 @@ PendingTransaction* Wallet::createTransactionMultiDest(const QVector<QString> &d
|
|||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionMultDest(dests, "", amounts, 11, static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl);
|
||||
|
||||
startRefresh();
|
||||
// startRefresh();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,7 @@ void Wallet::createTransactionMultiDestAsync(const QVector<QString> &dst_addr, c
|
|||
PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const QString &payment_id,
|
||||
quint32 mixin_count, PendingTransaction::Priority priority)
|
||||
{
|
||||
pauseRefresh();
|
||||
// pauseRefresh();
|
||||
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransaction(
|
||||
|
@ -675,7 +675,7 @@ PendingTransaction *Wallet::createTransactionAll(const QString &dst_addr, const
|
|||
static_cast<Monero::PendingTransaction::Priority>(priority), currentSubaddressAccount(), subaddr_indices);
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||
|
||||
startRefresh();
|
||||
// startRefresh();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -693,13 +693,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::Priority priority)
|
||||
{
|
||||
pauseRefresh();
|
||||
// pauseRefresh();
|
||||
|
||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createTransactionSingle(key_image.toStdString(), dst_addr.toStdString(),
|
||||
outputs, static_cast<Monero::PendingTransaction::Priority>(priority));
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||
|
||||
startRefresh();
|
||||
// startRefresh();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -715,12 +715,12 @@ void Wallet::createTransactionSingleAsync(const QString &key_image, const QStrin
|
|||
|
||||
PendingTransaction *Wallet::createSweepUnmixableTransaction()
|
||||
{
|
||||
pauseRefresh();
|
||||
// pauseRefresh();
|
||||
|
||||
Monero::PendingTransaction * ptImpl = m_walletImpl->createSweepUnmixableTransaction();
|
||||
PendingTransaction * result = new PendingTransaction(ptImpl, this);
|
||||
|
||||
startRefresh();
|
||||
// startRefresh();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent)
|
|||
connect(m_ctx, &AppContext::walletRefreshed, ui->historyWidget, &HistoryWidget::onWalletRefreshed);
|
||||
connect(m_ctx, &AppContext::walletOpened, ui->historyWidget, &HistoryWidget::onWalletOpened);
|
||||
|
||||
if (!config()->get(Config::firstRun).toBool()) {
|
||||
if (!config()->get(Config::firstRun).toBool() || TailsOS::detect() || WhonixOS::detect()) {
|
||||
this->onInitialNetworkConfigured();
|
||||
}
|
||||
|
||||
|
@ -418,8 +418,9 @@ void MainWindow::initWalletContext() {
|
|||
}
|
||||
|
||||
void MainWindow::initWizard() {
|
||||
this->setEnabled(false);
|
||||
auto startPage = WalletWizard::Page_Menu;
|
||||
if (config()->get(Config::firstRun).toBool()) {
|
||||
if (config()->get(Config::firstRun).toBool() && !(TailsOS::detect() || WhonixOS::detect())) {
|
||||
startPage = WalletWizard::Page_Network;
|
||||
}
|
||||
|
||||
|
@ -544,6 +545,8 @@ void MainWindow::onDeviceButtonRequest(quint64 code) {
|
|||
m_wizard->hide();
|
||||
}
|
||||
|
||||
m_splashDialog->setMessage("Action required on device: Export the view key to open the wallet.");
|
||||
m_splashDialog->setIcon(QPixmap(":/assets/images/key.png"));
|
||||
m_splashDialog->show();
|
||||
m_splashDialog->setEnabled(true);
|
||||
}
|
||||
|
@ -571,7 +574,10 @@ void MainWindow::displayWalletErrorMsg(const QString &err) {
|
|||
errMsg += "\n\nIncompatible version: you may need to upgrade the Monero app on the Ledger device to the latest version.";
|
||||
}
|
||||
else if (errMsg.contains("Wrong Device Status")) {
|
||||
errMsg += "\n\nThe device may need to be unlocked";
|
||||
errMsg += "\n\nThe device may need to be unlocked.";
|
||||
}
|
||||
else if (errMsg.contains("Wrong Channel")) {
|
||||
errMsg += "\n\nRestart the hardware device and try again.";
|
||||
}
|
||||
|
||||
QMessageBox::warning(this, "Wallet error", errMsg);
|
||||
|
@ -630,9 +636,18 @@ void MainWindow::onBalanceUpdated(quint64 balance, quint64 spendable) {
|
|||
qDebug() << Q_FUNC_INFO;
|
||||
bool hide = config()->get(Config::hideBalance).toBool();
|
||||
|
||||
QString label_str = QString("Balance: %1 XMR").arg(Utils::balanceFormat(spendable));
|
||||
if (balance > spendable)
|
||||
int amountPrecision = config()->get(Config::amountPrecision).toInt();
|
||||
|
||||
QString balance_str = WalletManager::displayAmount(spendable);
|
||||
balance_str.remove(QRegExp("0+$"));
|
||||
|
||||
QString label_str = QString("Balance: %1 XMR").arg(balance_str);
|
||||
if (balance > spendable) {
|
||||
QString unconfirmed_str = WalletManager::displayAmount(spendable);
|
||||
unconfirmed_str.remove(QRegExp("0+$"));
|
||||
label_str += QString(" (+%1 XMR unconfirmed)").arg(Utils::balanceFormat(balance - spendable));
|
||||
}
|
||||
|
||||
|
||||
if (hide)
|
||||
label_str = "Balance: HIDDEN";
|
||||
|
@ -725,12 +740,12 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto
|
|||
err = QString("%1 %2").arg(err).arg(tx_err);
|
||||
|
||||
qDebug() << Q_FUNC_INFO << err;
|
||||
QMessageBox::warning(this, "Transactions error", err);
|
||||
this->displayWalletErrorMsg(err);
|
||||
m_ctx->currentWallet->disposeTransaction(tx);
|
||||
} else if (tx->txCount() == 0) {
|
||||
err = QString("%1 %2").arg(err).arg("No unmixable outputs to sweep.");
|
||||
qDebug() << Q_FUNC_INFO << err;
|
||||
QMessageBox::warning(this, "Transaction error", err);
|
||||
this->displayWalletErrorMsg(err);
|
||||
m_ctx->currentWallet->disposeTransaction(tx);
|
||||
} else {
|
||||
const auto &description = m_ctx->tmpTxDescription;
|
||||
|
@ -797,7 +812,7 @@ void MainWindow::showWalletInfoDialog() {
|
|||
|
||||
void MainWindow::showSeedDialog() {
|
||||
if (m_ctx->currentWallet->isHwBacked()) {
|
||||
QMessageBox::information(this, "Information", "Wallet keys are stored on hardware device.");
|
||||
QMessageBox::information(this, "Information", "Seed unavailable: Wallet keys are stored on hardware device.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1232,15 +1247,21 @@ void MainWindow::createUnsignedTxDialog(UnsignedTransaction *tx) {
|
|||
|
||||
void MainWindow::importTransaction() {
|
||||
|
||||
auto result = QMessageBox::warning(this, "Warning", "Using this feature may allow a remote node to associate the transaction with your IP address.\n"
|
||||
"\n"
|
||||
"Connect to a trusted node or run Feather over Tor if network level metadata leakage is included in your threat model.",
|
||||
QMessageBox::Ok | QMessageBox::Cancel);
|
||||
if (result == QMessageBox::Ok) {
|
||||
auto *dialog = new TxImportDialog(this, m_ctx);
|
||||
dialog->exec();
|
||||
dialog->deleteLater();
|
||||
if (config()->get(Config::torPrivacyLevel).toInt() == Config::allTorExceptNode) {
|
||||
// TODO: don't show if connected to local node
|
||||
|
||||
auto result = QMessageBox::warning(this, "Warning", "Using this feature may allow a remote node to associate the transaction with your IP address.\n"
|
||||
"\n"
|
||||
"Connect to a trusted node or run Feather over Tor if network level metadata leakage is included in your threat model.",
|
||||
QMessageBox::Ok | QMessageBox::Cancel);
|
||||
if (result != QMessageBox::Ok) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto *dialog = new TxImportDialog(this, m_ctx);
|
||||
dialog->exec();
|
||||
dialog->deleteLater();
|
||||
}
|
||||
|
||||
void MainWindow::onDeviceError(const QString &error) {
|
||||
|
@ -1332,9 +1353,10 @@ void MainWindow::onCheckUpdatesComplete(const QString &version, const QString &b
|
|||
versionDisplay.replace("beta", "Beta");
|
||||
QString updateText = QString("Update to Feather %1 is available").arg(versionDisplay);
|
||||
m_statusUpdateAvailable->setText(updateText);
|
||||
m_statusUpdateAvailable->setToolTip("Click to Download update.");
|
||||
m_statusUpdateAvailable->show();
|
||||
|
||||
disconnect(m_statusUpdateAvailable);
|
||||
m_statusUpdateAvailable->disconnect();
|
||||
connect(m_statusUpdateAvailable, &StatusBarButton::clicked, [this, version, binaryFilename, hash, signer] {
|
||||
this->onShowUpdateCheck(version, binaryFilename, hash, signer);
|
||||
});
|
||||
|
@ -1367,9 +1389,9 @@ void MainWindow::onUpdatesAvailable(const QJsonObject &updates) {
|
|||
}
|
||||
|
||||
QString newVersion = platformData["version"].toString();
|
||||
// if (SemanticVersion::fromString(newVersion) <= featherVersion) {
|
||||
// return;
|
||||
// }
|
||||
if (SemanticVersion::fromString(newVersion) <= featherVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hooray! New update available
|
||||
|
||||
|
@ -1423,6 +1445,14 @@ void MainWindow::onInitiateTransaction() {
|
|||
m_statusDots = 0;
|
||||
m_constructingTransaction = true;
|
||||
m_txTimer.start(1000);
|
||||
|
||||
if (m_ctx->currentWallet->isHwBacked()) {
|
||||
QString message = "Constructing transaction: action may be required on device.";
|
||||
m_splashDialog->setMessage(message);
|
||||
m_splashDialog->setIcon(QPixmap(":/assets/images/unconfirmed.png"));
|
||||
m_splashDialog->show();
|
||||
m_splashDialog->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onEndTransaction() {
|
||||
|
@ -1430,6 +1460,10 @@ void MainWindow::onEndTransaction() {
|
|||
m_constructingTransaction = false;
|
||||
m_txTimer.stop();
|
||||
this->setStatusText(m_statusText);
|
||||
|
||||
if (m_ctx->currentWallet->isHwBacked()) {
|
||||
m_splashDialog->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onCustomRestoreHeightSet(int height) {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1156</width>
|
||||
<height>496</height>
|
||||
<width>977</width>
|
||||
<height>499</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -352,8 +352,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1156</width>
|
||||
<height>27</height>
|
||||
<width>977</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
|
|
@ -44,9 +44,10 @@ void TorManager::stop() {
|
|||
}
|
||||
|
||||
void TorManager::start() {
|
||||
m_checkConnectionTimer->start(5000);
|
||||
|
||||
if (m_localTor) {
|
||||
this->checkConnection();
|
||||
m_checkConnectionTimer->start(5000);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -256,6 +257,9 @@ bool TorManager::shouldStartTorDaemon() {
|
|||
|
||||
// Tor daemon (or other service) is already running on our port (19450)
|
||||
if (Utils::portOpen(featherTorHost, featherTorPort)) {
|
||||
// TODO: this is a hack, fix it later
|
||||
config()->set(Config::socks5Host, featherTorHost);
|
||||
config()->set(Config::socks5Port, featherTorPort);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
|
|||
{Config::useOnionNodes,{QS("useOnionNodes"), false}},
|
||||
{Config::showTabHome,{QS("showTabHome"), true}},
|
||||
{Config::showTabCoins,{QS("showTabCoins"), false}},
|
||||
{Config::showTabExchange, {QS("showTabExchange"), true}},
|
||||
{Config::showTabExchange, {QS("showTabExchange"), false}},
|
||||
{Config::showTabXMRig,{QS("showTabXMRig"), false}},
|
||||
{Config::showTabCalc,{QS("showTabCalc"), true}},
|
||||
{Config::geometry, {QS("geometry"), {}}},
|
||||
|
|
|
@ -37,6 +37,7 @@ void DaemonRpc::onResponse(QNetworkReply *reply, Endpoint endpoint) {
|
|||
const auto err = reply->errorString();
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
reply->deleteLater();
|
||||
QJsonObject obj;
|
||||
if (!data.isEmpty() && Utils::validateJSON(data)) {
|
||||
auto doc = QJsonDocument::fromJson(data);
|
||||
|
@ -65,8 +66,8 @@ void DaemonRpc::onResponse(QNetworkReply *reply, Endpoint endpoint) {
|
|||
return;
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
emit ApiResponse(DaemonResponse(true, endpoint, "", obj));
|
||||
DaemonResponse resp{true, endpoint, "", obj};
|
||||
emit ApiResponse(resp);
|
||||
}
|
||||
|
||||
QString DaemonRpc::onSendRawTransactionFailed(const QJsonObject &obj) {
|
||||
|
|
|
@ -318,12 +318,19 @@ void Nodes::setCustomNodes(const QList<FeatherNode> &nodes) {
|
|||
}
|
||||
|
||||
void Nodes::onWalletRefreshed() {
|
||||
if (config()->get(Config::torPrivacyLevel).toInt() == Config::allTorExceptInitSync && !m_connection.isLocal()) {
|
||||
if (config()->get(Config::torPrivacyLevel).toInt() == Config::allTorExceptInitSync) {
|
||||
if (m_connection.isLocal())
|
||||
return;
|
||||
if (TailsOS::detect() || WhonixOS::detect())
|
||||
return;
|
||||
this->autoConnect(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool Nodes::useOnionNodes() {
|
||||
if (TailsOS::detect() || WhonixOS::detect()) {
|
||||
return true;
|
||||
}
|
||||
auto privacyLevel = config()->get(Config::torPrivacyLevel).toInt();
|
||||
if (privacyLevel == Config::allTor || (privacyLevel == Config::allTorExceptInitSync && m_ctx->refreshed)) {
|
||||
return true;
|
||||
|
|
|
@ -7,10 +7,16 @@
|
|||
#include "tails.h"
|
||||
#include "utils.h"
|
||||
|
||||
bool TailsOS::detected = false;
|
||||
bool TailsOS::isTails = false;
|
||||
const QString TailsOS::tailsPathData = QString("/live/persistence/TailsData_unlocked/");
|
||||
|
||||
bool TailsOS::detect()
|
||||
{
|
||||
if (detected) {
|
||||
return TailsOS::isTails;
|
||||
}
|
||||
|
||||
if (!Utils::fileExists("/etc/os-release"))
|
||||
return false;
|
||||
|
||||
|
@ -22,6 +28,9 @@ bool TailsOS::detect()
|
|||
if (matched)
|
||||
qDebug() << "Tails OS detected";
|
||||
|
||||
TailsOS::detected = true;
|
||||
TailsOS::isTails = matched;
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ public:
|
|||
static bool usePersistence;
|
||||
static bool rememberChoice;
|
||||
static const QString tailsPathData;
|
||||
|
||||
static bool isTails;
|
||||
static bool detected;
|
||||
};
|
||||
|
||||
#endif // TAILSOS_H
|
||||
|
|
|
@ -17,10 +17,6 @@
|
|||
#include "utils/ColorScheme.h"
|
||||
#include "globals.h"
|
||||
|
||||
// Application log for current session
|
||||
QVector<logMessage> applicationLog = QVector<logMessage>(); // todo: replace with ring buffer
|
||||
QMutex logMutex;
|
||||
|
||||
QByteArray Utils::fileGetContents(const QString &path)
|
||||
{
|
||||
QFile file(path);
|
||||
|
@ -128,12 +124,6 @@ void Utils::applicationLogHandler(QtMsgType type, const QMessageLogContext &cont
|
|||
|
||||
auto message = logMessage(type, line, fn);
|
||||
|
||||
{
|
||||
QMutexLocker locker(&logMutex);
|
||||
applicationLog.append(message);
|
||||
}
|
||||
|
||||
|
||||
//emit applicationLogUpdated(message);
|
||||
}
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ void LocalMoneroWidget::updatePaymentMethods() {
|
|||
QString currency = ui->combo_currency->currentText().toUpper();
|
||||
|
||||
ui->combo_paymentMethod->clear();
|
||||
ui->combo_paymentMethod->addItem("All online offers");
|
||||
ui->combo_paymentMethod->addItem("Any payment method");
|
||||
|
||||
for (const auto &payment_method : m_paymentMethods.keys()) {
|
||||
auto pm = m_paymentMethods[payment_method].toObject();
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All online offers</string>
|
||||
<string>Any payment method</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
|
|
|
@ -28,11 +28,6 @@
|
|||
<string>Ledger Nano S/X</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Trezor Model T</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -12,16 +12,20 @@ PageNetworkTor::PageNetworkTor(AppContext *ctx, QWidget *parent)
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QPixmap iconAllTorExceptNode(":/assets/images/securityLevelStandardWhite.png");
|
||||
QPixmap iconAllTorExceptInitSync(":/assets/images/securityLevelSaferWhite.png");
|
||||
QPixmap iconAllTor(":/assets/images/securityLevelSafestWhite.png");
|
||||
this->setCommitPage(true);
|
||||
this->setButtonText(QWizard::CommitButton, "Next");
|
||||
|
||||
QPixmap iconAllTorExceptNode(":/assets/images/securityLevelStandard.png");
|
||||
QPixmap iconAllTorExceptInitSync(":/assets/images/securityLevelSafer.png");
|
||||
QPixmap iconAllTor(":/assets/images/securityLevelSafest.png");
|
||||
ui->icon_allTorExceptNode->setPixmap(iconAllTorExceptNode.scaledToHeight(16, Qt::SmoothTransformation));
|
||||
ui->icon_allTorExceptInitSync->setPixmap(iconAllTorExceptInitSync.scaledToHeight(16, Qt::SmoothTransformation));
|
||||
ui->icon_allTor->setPixmap(iconAllTor.scaledToHeight(16, Qt::SmoothTransformation));
|
||||
|
||||
ui->frame_privacyLevel->setVisible(false);
|
||||
connect(ui->radio_configureManually, &QRadioButton::toggled, [this](bool checked){
|
||||
ui->frame_privacyLevel->setVisible(checked);
|
||||
this->adjustSize();
|
||||
this->updateGeometry();
|
||||
});
|
||||
|
||||
ui->btnGroup_privacyLevel->setId(ui->radio_allTorExceptNode, Config::allTorExceptNode);
|
||||
|
@ -35,6 +39,13 @@ PageNetworkTor::PageNetworkTor(AppContext *ctx, QWidget *parent)
|
|||
}
|
||||
}
|
||||
|
||||
void PageNetworkTor::initializePage() {
|
||||
// Fuck you Qt. No squish.
|
||||
QTimer::singleShot(1, [this]{
|
||||
ui->frame_privacyLevel->setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
int PageNetworkTor::nextId() const {
|
||||
return WalletWizard::Page_Menu;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ Q_OBJECT
|
|||
|
||||
public:
|
||||
explicit PageNetworkTor(AppContext *ctx, QWidget *parent = nullptr);
|
||||
void initializePage() override;
|
||||
bool validatePage() override;
|
||||
int nextId() const override;
|
||||
|
||||
|
|
|
@ -83,6 +83,12 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_privacyLevel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
|
@ -107,6 +113,12 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radio_allTorExceptNode">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Route all traffic over Tor, except traffic to node</string>
|
||||
</property>
|
||||
|
@ -134,8 +146,14 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radio_allTorExceptInitSync">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Route all traffic over Tor, except initial wallet synchronization</string>
|
||||
<string>Route all traffic over Tor, except initial wallet sync</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">btnGroup_privacyLevel</string>
|
||||
|
@ -161,6 +179,12 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radio_allTor">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Route all traffic over Tor</string>
|
||||
</property>
|
||||
|
|
|
@ -97,7 +97,11 @@ QString PageWalletFile::defaultWalletName() {
|
|||
int count = 1;
|
||||
QString walletName;
|
||||
do {
|
||||
walletName = QString("wallet_%1").arg(count);
|
||||
QString walletStr = QString("wallet_%1");
|
||||
if (m_fields->mode == WizardMode::CreateWalletFromDevice) {
|
||||
walletStr = QString("ledger_%1");
|
||||
}
|
||||
walletName = walletStr.arg(count);
|
||||
count++;
|
||||
} while (this->walletPathExists(walletName));
|
||||
|
||||
|
|
Loading…
Reference in a new issue