mirror of
https://github.com/feather-wallet/feather.git
synced 2024-11-17 09:47:36 +00:00
airgap: make view-only details compatible with ANONERO
This commit is contained in:
parent
ff1b16564a
commit
a131bbc165
9 changed files with 48 additions and 91 deletions
|
@ -1040,6 +1040,10 @@ void MainWindow::showKeysDialog() {
|
|||
}
|
||||
|
||||
void MainWindow::showViewOnlyDialog() {
|
||||
if (!this->verifyPassword()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewOnlyDialog dialog{m_wallet, this};
|
||||
dialog.exec();
|
||||
}
|
||||
|
|
|
@ -10,28 +10,12 @@
|
|||
#include "utils/Utils.h"
|
||||
#include "WalletManager.h"
|
||||
|
||||
URDialog::URDialog(QWidget *parent, const std::string &data, bool scanOnly)
|
||||
URDialog::URDialog(QWidget *parent)
|
||||
: WindowModalDialog(parent)
|
||||
, ui(new Ui::URDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if (!data.empty()) {
|
||||
ui->btn_loadFile->setVisible(false);
|
||||
ui->btn_loadClipboard->setVisible(false);
|
||||
ui->tabWidget->setTabVisible(1, false);
|
||||
|
||||
QScreen *currentScreen = QApplication::screenAt(this->geometry().center());
|
||||
if (!currentScreen) {
|
||||
currentScreen = QApplication::primaryScreen();
|
||||
}
|
||||
int availableHeight = currentScreen->availableGeometry().height() - 200;
|
||||
this->resize(availableHeight, availableHeight);
|
||||
|
||||
ui->widgetUR->setData("xmr-viewonly", data);
|
||||
return;
|
||||
}
|
||||
|
||||
connect(ui->btn_loadFile, &QPushButton::clicked, [this]{
|
||||
QString fn = QFileDialog::getOpenFileName(this, "Load file", QDir::homePath(), "All Files (*)");
|
||||
if (fn.isEmpty()) {
|
||||
|
@ -75,41 +59,6 @@ URDialog::URDialog(QWidget *parent, const std::string &data, bool scanOnly)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ui->widgetScanner->getURType() == "xmr-viewonly") {
|
||||
std::string urData = ui->widgetScanner->getURData();
|
||||
while (true) {
|
||||
bool ok;
|
||||
QString password = QInputDialog::getText(this, "Encrypt view-only details", "Enter one-time password to decrypt view-only details with", QLineEdit::Password, "", &ok);
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
|
||||
QString data = WalletManager::decryptWithPassword(urData, password);
|
||||
if (!data.startsWith("Secret view key")) {
|
||||
Utils::showError(this, "Unable to load view-only details", "Invalid password");
|
||||
continue;
|
||||
}
|
||||
|
||||
QRegularExpression viewOnlyDetails(
|
||||
"Secret view key: (?<key>[0-9a-f]{64})\nAddress: (?<address>\\w+)\nRestore height: (?<restoreheight>\\d+)\nWallet name: (?<walletname>\\w+)\n",
|
||||
QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
|
||||
QRegularExpressionMatch match = viewOnlyDetails.match(data);
|
||||
|
||||
if (!match.hasMatch()) {
|
||||
Utils::showError(this, "Unable to load view-only details", "Unexpected data");
|
||||
continue;
|
||||
}
|
||||
|
||||
m_viewOnlyDetails.address = match.captured("address");
|
||||
m_viewOnlyDetails.key = match.captured("key").toLower();
|
||||
m_viewOnlyDetails.restoreHeight = match.captured("restoreheight").toInt();
|
||||
m_viewOnlyDetails.walletName = QString("%1_view_only").arg(match.captured("walletname"));
|
||||
|
||||
this->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ui->radio_clipboard->isChecked()) {
|
||||
Utils::copyToClipboard(QString::fromStdString(ui->widgetScanner->getURData()));
|
||||
Utils::showInfo(this, "Data copied to clipboard");
|
||||
|
@ -138,22 +87,10 @@ URDialog::URDialog(QWidget *parent, const std::string &data, bool scanOnly)
|
|||
ui->widgetScanner->reset();
|
||||
});
|
||||
|
||||
if (scanOnly) {
|
||||
ui->tabWidget->setCurrentIndex(1);
|
||||
ui->tabWidget->setTabVisible(0, false);
|
||||
ui->radio_clipboard->setVisible(false);
|
||||
ui->radio_file->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ui->radio_file->setChecked(true);
|
||||
ui->tabWidget->setCurrentIndex(0);
|
||||
|
||||
this->resize(600, 700);
|
||||
}
|
||||
|
||||
ViewOnlyDetails URDialog::getViewOnlyDetails() {
|
||||
return m_viewOnlyDetails;
|
||||
}
|
||||
|
||||
URDialog::~URDialog() = default;
|
|
@ -12,26 +12,16 @@ namespace Ui {
|
|||
class URDialog;
|
||||
}
|
||||
|
||||
struct ViewOnlyDetails {
|
||||
QString address;
|
||||
QString key;
|
||||
int restoreHeight = 0;
|
||||
QString walletName;
|
||||
};
|
||||
|
||||
class URDialog : public WindowModalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit URDialog(QWidget *parent, const std::string &data = "", bool scanOnly = false);
|
||||
explicit URDialog(QWidget *parent);
|
||||
~URDialog() override;
|
||||
|
||||
ViewOnlyDetails getViewOnlyDetails();
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::URDialog> ui;
|
||||
ViewOnlyDetails m_viewOnlyDetails;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include "URDialog.h"
|
||||
#include "utils/Utils.h"
|
||||
#include "WalletManager.h"
|
||||
#include "qrcode/QrCode.h"
|
||||
#include "dialog/QrCodeDialog.h"
|
||||
|
||||
ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent)
|
||||
: WindowModalDialog(parent)
|
||||
|
@ -26,14 +28,8 @@ ViewOnlyDialog::ViewOnlyDialog(Wallet *wallet, QWidget *parent)
|
|||
connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboard);
|
||||
connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet);
|
||||
connect(ui->btn_transmitOverUR, &QPushButton::clicked, [this] {
|
||||
bool ok;
|
||||
QString password = QInputDialog::getText(this, "Encrypt view-only details", "Enter one-time password to encrypt view-only details with", QLineEdit::Password, "", &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string encrypted = WalletManager::encryptWithPassword(this->toString(), password);
|
||||
URDialog dialog{this, encrypted};
|
||||
QrCode qr(this->toJsonString(), QrCode::Version::AUTO, QrCode::ErrorCorrectionLevel::HIGH);
|
||||
QrCodeDialog dialog{this, &qr, "View-Only details"};
|
||||
dialog.exec();
|
||||
});
|
||||
|
||||
|
@ -74,6 +70,18 @@ QString ViewOnlyDialog::toString() {
|
|||
return text;
|
||||
}
|
||||
|
||||
QString ViewOnlyDialog::toJsonString() {
|
||||
QVariantMap data;
|
||||
data["version"] = 0,
|
||||
data["primaryAddress"] = m_wallet->address(0, 0);
|
||||
data["privateViewKey"] = m_wallet->getSecretViewKey();
|
||||
data["restoreHeight"] = m_wallet->getWalletCreationHeight();
|
||||
data["walletName"] = m_wallet->walletName();
|
||||
|
||||
auto obj = QJsonDocument::fromVariant(data);
|
||||
return obj.toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
void ViewOnlyDialog::copyToClipboard() {
|
||||
Utils::copyToClipboard(this->toString());
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ private slots:
|
|||
|
||||
private:
|
||||
QString toString();
|
||||
QString toJsonString();
|
||||
void copyToClipboard();
|
||||
|
||||
QScopedPointer<Ui::ViewOnlyDialog> ui;
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
<item>
|
||||
<widget class="QPushButton" name="btn_transmitOverUR">
|
||||
<property name="text">
|
||||
<string>Transmit over UR</string>
|
||||
<string>Show QR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -21,6 +21,10 @@ QrCodeScanDialog::QrCodeScanDialog(QWidget *parent, bool scan_ur)
|
|||
this->setWindowTitle("Scan QR code");
|
||||
|
||||
ui->widget_scanner->startCapture(scan_ur);
|
||||
|
||||
connect(ui->widget_scanner, &QrCodeScanWidget::finished, [this]{
|
||||
this->accept();
|
||||
});
|
||||
}
|
||||
|
||||
QString QrCodeScanDialog::decodedString() {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "constants.h"
|
||||
#include "dialog/URDialog.h"
|
||||
#include "libwalletqt/WalletManager.h"
|
||||
#include "scanner/QrCodeScanDialog.h"
|
||||
|
||||
PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *parent)
|
||||
: QWizardPage(parent)
|
||||
|
@ -43,15 +44,27 @@ PageWalletRestoreKeys::PageWalletRestoreKeys(WizardFields *fields, QWidget *pare
|
|||
connect(ui->btnOptions, &QPushButton::clicked, this, &PageWalletRestoreKeys::onOptionsClicked);
|
||||
connect(ui->combo_walletType, &QComboBox::currentTextChanged, this, &PageWalletRestoreKeys::showInputLines);
|
||||
connect(ui->btn_scanUR, &QPushButton::clicked, [this] {
|
||||
URDialog dialog{this, "", true};
|
||||
QrCodeScanDialog dialog{this, false};
|
||||
dialog.exec();
|
||||
ViewOnlyDetails details = dialog.getViewOnlyDetails();
|
||||
ui->line_address->setText(details.address);
|
||||
|
||||
QString json = dialog.decodedString();
|
||||
if (json.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonParseError error;
|
||||
auto doc = QJsonDocument::fromJson(json.toUtf8(), &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
Utils::showError(this, "Unable to load view-only details", QString("Can't parse JSON: %1").arg(error.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
ui->line_address->setText(doc["primaryAddress"].toString());
|
||||
ui->line_address->setCursorPosition(0);
|
||||
ui->line_viewkey->setText(details.key);
|
||||
ui->line_viewkey->setText(doc["privateViewKey"].toString());
|
||||
ui->line_viewkey->setCursorPosition(0);
|
||||
m_fields->restoreHeight = details.restoreHeight;
|
||||
m_fields->walletName = details.walletName;
|
||||
m_fields->restoreHeight = doc["restoreHeight"].toInt();
|
||||
m_fields->walletName = doc["walletName"].toString() + "_view_only";
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@
|
|||
<item>
|
||||
<widget class="QPushButton" name="btn_scanUR">
|
||||
<property name="text">
|
||||
<string>Scan UR</string>
|
||||
<string>Scan QR</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
Loading…
Reference in a new issue