mirror of
https://github.com/feather-wallet/feather.git
synced 2024-12-23 03:59:29 +00:00
Merge pull request 'Open/create view-only wallets' (#53) from dsc/feather:view-only into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/53
This commit is contained in:
commit
36641d73a6
19 changed files with 619 additions and 23 deletions
|
@ -341,6 +341,13 @@ void AppContext::onWalletOpened(Wallet *wallet) {
|
||||||
|
|
||||||
// force trigger preferredFiat signal for history model
|
// force trigger preferredFiat signal for history model
|
||||||
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
|
this->onPreferredFiatCurrencyChanged(config()->get(Config::preferredFiatCurrency).toString());
|
||||||
|
|
||||||
|
// (window) title
|
||||||
|
QFileInfo fileInfo(this->walletPath);
|
||||||
|
auto title = QString("Feather - [%1]").arg(fileInfo.fileName());
|
||||||
|
if(this->currentWallet->viewOnly())
|
||||||
|
title += " [view-only]";
|
||||||
|
emit setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppContext::onWSMessage(const QJsonObject &msg) {
|
void AppContext::onWSMessage(const QJsonObject &msg) {
|
||||||
|
@ -541,6 +548,43 @@ void AppContext::createWallet(FeatherSeed seed, const QString &path, const QStri
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->createWalletFinish(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppContext::createWalletViewOnly(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight) {
|
||||||
|
if(Utils::fileExists(path)) {
|
||||||
|
auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path);
|
||||||
|
qCritical() << err;
|
||||||
|
emit walletCreatedError(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this->walletManager->addressValid(address, this->networkType)) {
|
||||||
|
auto err = QString("Failed to create wallet. Invalid address provided.").arg(path);
|
||||||
|
qCritical() << err;
|
||||||
|
emit walletCreatedError(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this->walletManager->keyValid(viewkey, address, true, this->networkType)) {
|
||||||
|
auto err = QString("Failed to create wallet. Invalid viewkey provided.").arg(path);
|
||||||
|
qCritical() << err;
|
||||||
|
emit walletCreatedError(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!spendkey.isEmpty() && !this->walletManager->keyValid(spendkey, address, false, this->networkType)) {
|
||||||
|
auto err = QString("Failed to create wallet. Invalid spendkey provided.").arg(path);
|
||||||
|
qCritical() << err;
|
||||||
|
emit walletCreatedError(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->currentWallet = this->walletManager->createWalletFromKeys(path, this->seedLanguage, this->networkType, address, viewkey, spendkey, restoreHeight);
|
||||||
|
this->createWalletFinish(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppContext::createWalletFinish(const QString &password) {
|
||||||
this->currentWallet->setPassword(password);
|
this->currentWallet->setPassword(password);
|
||||||
this->currentWallet->store();
|
this->currentWallet->store();
|
||||||
this->walletPassword = password;
|
this->walletPassword = password;
|
||||||
|
@ -614,8 +658,9 @@ void AppContext::onOpenAliasResolve(const QString &openAlias) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppContext::donateBeg() {
|
void AppContext::donateBeg() {
|
||||||
if(this->networkType != NetworkType::Type::MAINNET)
|
if(this->currentWallet == nullptr) return;
|
||||||
return;
|
if(this->networkType != NetworkType::Type::MAINNET) return;
|
||||||
|
if(this->currentWallet->viewOnly()) return;
|
||||||
|
|
||||||
auto donationCounter = config()->get(Config::donateBeg).toInt();
|
auto donationCounter = config()->get(Config::donateBeg).toInt();
|
||||||
if(donationCounter == -1)
|
if(donationCounter == -1)
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
|
PendingTransaction::Priority tx_priority = PendingTransaction::Priority::Priority_Low;
|
||||||
quint32 tx_mixin = static_cast<const quint32 &>(10);
|
quint32 tx_mixin = static_cast<const quint32 &>(10);
|
||||||
static constexpr const double cdiv = 1e12;
|
static constexpr const double cdiv = 1e12;
|
||||||
|
QString seedLanguage = "English"; // 14 word `monero-seed` only has English
|
||||||
|
|
||||||
QNetworkAccessManager *network;
|
QNetworkAccessManager *network;
|
||||||
QNetworkAccessManager *networkClearnet;
|
QNetworkAccessManager *networkClearnet;
|
||||||
|
@ -89,6 +90,8 @@ public:
|
||||||
WalletManager *walletManager;
|
WalletManager *walletManager;
|
||||||
Wallet *currentWallet = nullptr;
|
Wallet *currentWallet = nullptr;
|
||||||
void createWallet(FeatherSeed seed, const QString &path, const QString &password);
|
void createWallet(FeatherSeed seed, const QString &path, const QString &password);
|
||||||
|
void createWalletViewOnly(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight);
|
||||||
|
void createWalletFinish(const QString &password);
|
||||||
void syncStatusUpdated(quint64 height, quint64 target);
|
void syncStatusUpdated(quint64 height, quint64 target);
|
||||||
void updateBalance();
|
void updateBalance();
|
||||||
void initTor();
|
void initTor();
|
||||||
|
@ -160,6 +163,7 @@ signals:
|
||||||
void initiateTransaction();
|
void initiateTransaction();
|
||||||
void endTransaction();
|
void endTransaction();
|
||||||
void walletClosing();
|
void walletClosing();
|
||||||
|
void setTitle(const QString &title); // set window title
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sorry();
|
void sorry();
|
||||||
|
|
59
src/dialog/viewonlydialog.cpp
Normal file
59
src/dialog/viewonlydialog.cpp
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020, The Monero Project.
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "viewonlydialog.h"
|
||||||
|
#include "ui_viewonlydialog.h"
|
||||||
|
|
||||||
|
ViewOnlyDialog::ViewOnlyDialog(AppContext *ctx, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::ViewOnlyDialog), m_ctx(ctx)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
ui->label_restoreHeight->setText(QString::number(ctx->currentWallet->getWalletCreationHeight()));
|
||||||
|
ui->label_primaryAddress->setText(ctx->currentWallet->address(0, 0));
|
||||||
|
ui->label_secretViewKey->setText(ctx->currentWallet->getSecretViewKey());
|
||||||
|
|
||||||
|
connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboad);
|
||||||
|
connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet);
|
||||||
|
|
||||||
|
ui->btn_Save->setEnabled(!m_ctx->currentWallet->viewOnly());
|
||||||
|
this->adjustSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewOnlyDialog::onWriteViewOnlyWallet(){
|
||||||
|
QString fn = QFileDialog::getSaveFileName(this, "Save .keys wallet file", QDir::homePath(), "Monero wallet (*.keys)");
|
||||||
|
if(fn.isEmpty()) return;
|
||||||
|
if(!fn.endsWith(".keys")) fn += ".keys";
|
||||||
|
|
||||||
|
QString passwd;
|
||||||
|
QInputDialog passwordDialog(this);
|
||||||
|
passwordDialog.setInputMode(QInputDialog::TextInput);
|
||||||
|
passwordDialog.setTextEchoMode(QLineEdit::Password);
|
||||||
|
passwordDialog.setWindowTitle("View-Only wallet password");
|
||||||
|
passwordDialog.setLabelText("Protect this view-only wallet with a password?");
|
||||||
|
passwordDialog.resize(300, 100);
|
||||||
|
if((bool)passwordDialog.exec())
|
||||||
|
passwd = passwordDialog.textValue();
|
||||||
|
|
||||||
|
m_ctx->currentWallet->createViewOnly(fn, passwd);
|
||||||
|
|
||||||
|
QMessageBox::information(this, "Information", "View-only wallet successfully written to disk.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewOnlyDialog::copyToClipboad() {
|
||||||
|
QString text = "";
|
||||||
|
text += QString("Address: %1\n").arg(ui->label_primaryAddress->text());
|
||||||
|
text += QString("Secret view key: %1\n").arg(ui->label_secretViewKey->text());
|
||||||
|
text += QString("Restore height: %1\n").arg(ui->label_restoreHeight->text());
|
||||||
|
Utils::copyToClipboard(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewOnlyDialog::~ViewOnlyDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
32
src/dialog/viewonlydialog.h
Normal file
32
src/dialog/viewonlydialog.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020, The Monero Project.
|
||||||
|
|
||||||
|
#ifndef FEATHER_VIEWONLYDIALOG_H
|
||||||
|
#define FEATHER_VIEWONLYDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "appcontext.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ViewOnlyDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewOnlyDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ViewOnlyDialog(AppContext *ctx, QWidget *parent = nullptr);
|
||||||
|
~ViewOnlyDialog() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onWriteViewOnlyWallet();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::ViewOnlyDialog *ui;
|
||||||
|
AppContext *m_ctx = nullptr;
|
||||||
|
void copyToClipboad();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //FEATHER_KEYSDIALOG_H
|
139
src/dialog/viewonlydialog.ui
Normal file
139
src/dialog/viewonlydialog.ui
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ViewOnlyDialog</class>
|
||||||
|
<widget class="QDialog" name="ViewOnlyDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>659</width>
|
||||||
|
<height>254</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>View-Only</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_6">
|
||||||
|
<property name="title">
|
||||||
|
<string>Restore height</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_restoreHeight">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Primary address</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_primaryAddress">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Secret view key</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_secretViewKey">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_Copy">
|
||||||
|
<property name="text">
|
||||||
|
<string>Copy</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btn_Save">
|
||||||
|
<property name="text">
|
||||||
|
<string>Create view-only wallet</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>ViewOnlyDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>ViewOnlyDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -16,6 +16,7 @@
|
||||||
#include "dialog/debuginfodialog.h"
|
#include "dialog/debuginfodialog.h"
|
||||||
#include "dialog/walletinfodialog.h"
|
#include "dialog/walletinfodialog.h"
|
||||||
#include "dialog/torinfodialog.h"
|
#include "dialog/torinfodialog.h"
|
||||||
|
#include "dialog/viewonlydialog.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
|
@ -325,6 +326,10 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) :
|
||||||
connect(m_ctx, &AppContext::walletClosing, [=]{
|
connect(m_ctx, &AppContext::walletClosing, [=]{
|
||||||
ui->tabWidget->setCurrentIndex(0);
|
ui->tabWidget->setCurrentIndex(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// window title
|
||||||
|
connect(m_ctx, &AppContext::setTitle, this, &QMainWindow::setWindowTitle);
|
||||||
|
|
||||||
// setup some UI
|
// setup some UI
|
||||||
this->initMain();
|
this->initMain();
|
||||||
this->initWidgets();
|
this->initWidgets();
|
||||||
|
@ -389,6 +394,7 @@ void MainWindow::initMenu() {
|
||||||
connect(ui->actionSeed, &QAction::triggered, this, &MainWindow::showSeedDialog);
|
connect(ui->actionSeed, &QAction::triggered, this, &MainWindow::showSeedDialog);
|
||||||
connect(ui->actionPassword, &QAction::triggered, this, &MainWindow::showPasswordDialog);
|
connect(ui->actionPassword, &QAction::triggered, this, &MainWindow::showPasswordDialog);
|
||||||
connect(ui->actionKeys, &QAction::triggered, this, &MainWindow::showKeysDialog);
|
connect(ui->actionKeys, &QAction::triggered, this, &MainWindow::showKeysDialog);
|
||||||
|
connect(ui->actionViewOnly, &QAction::triggered, this, &MainWindow::showViewOnlyDialog);
|
||||||
connect(ui->actionStore_wallet, &QAction::triggered, [&]{
|
connect(ui->actionStore_wallet, &QAction::triggered, [&]{
|
||||||
m_ctx->currentWallet->store();
|
m_ctx->currentWallet->store();
|
||||||
});
|
});
|
||||||
|
@ -412,7 +418,8 @@ void MainWindow::initMenu() {
|
||||||
connect(ui->actionExport_CSV, &QAction::triggered, [=]{
|
connect(ui->actionExport_CSV, &QAction::triggered, [=]{
|
||||||
if(m_ctx->currentWallet == nullptr) return;
|
if(m_ctx->currentWallet == nullptr) return;
|
||||||
QString fn = QFileDialog::getSaveFileName(this, "Save CSV file", QDir::homePath(), "CSV (*.csv)");
|
QString fn = QFileDialog::getSaveFileName(this, "Save CSV file", QDir::homePath(), "CSV (*.csv)");
|
||||||
if(!fn.startsWith(".csv")) fn += ".csv";
|
if(fn.isEmpty()) return;
|
||||||
|
if(!fn.endsWith(".csv")) fn += ".csv";
|
||||||
m_ctx->currentWallet->history()->writeCSV(fn);
|
m_ctx->currentWallet->history()->writeCSV(fn);
|
||||||
Utils::showMessageBox("CSV export", QString("Transaction history exported to %1").arg(fn), false);
|
Utils::showMessageBox("CSV export", QString("Transaction history exported to %1").arg(fn), false);
|
||||||
});
|
});
|
||||||
|
@ -543,10 +550,6 @@ void MainWindow::onWalletOpened() {
|
||||||
else
|
else
|
||||||
m_statusLabelStatus->setText("Wallet opened - Searching for node");
|
m_statusLabelStatus->setText("Wallet opened - Searching for node");
|
||||||
|
|
||||||
// window title as wallet name
|
|
||||||
QFileInfo fileInfo(m_ctx->walletPath);
|
|
||||||
this->setWindowTitle(QString("Feather - [%1]").arg(fileInfo.fileName()));
|
|
||||||
|
|
||||||
connect(m_ctx->currentWallet, &Wallet::connectionStatusChanged, this, &MainWindow::onConnectionStatusChanged);
|
connect(m_ctx->currentWallet, &Wallet::connectionStatusChanged, this, &MainWindow::onConnectionStatusChanged);
|
||||||
|
|
||||||
// receive page
|
// receive page
|
||||||
|
@ -850,6 +853,12 @@ void MainWindow::showKeysDialog() {
|
||||||
dialog->deleteLater();
|
dialog->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::showViewOnlyDialog() {
|
||||||
|
auto *dialog = new ViewOnlyDialog(m_ctx, this);
|
||||||
|
dialog->exec();
|
||||||
|
dialog->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::menuTorClicked() {
|
void MainWindow::menuTorClicked() {
|
||||||
|
|
||||||
auto *dialog = new TorInfoDialog(m_ctx, this);
|
auto *dialog = new TorInfoDialog(m_ctx, this);
|
||||||
|
|
|
@ -79,6 +79,7 @@ public slots:
|
||||||
void showConnectionStatusDialog();
|
void showConnectionStatusDialog();
|
||||||
void showPasswordDialog();
|
void showPasswordDialog();
|
||||||
void showKeysDialog();
|
void showKeysDialog();
|
||||||
|
void showViewOnlyDialog();
|
||||||
void donateButtonClicked();
|
void donateButtonClicked();
|
||||||
void showCalcWindow();
|
void showCalcWindow();
|
||||||
void showSendTab();
|
void showSendTab();
|
||||||
|
|
|
@ -291,7 +291,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>894</width>
|
<width>894</width>
|
||||||
<height>30</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
|
@ -335,6 +335,7 @@
|
||||||
<addaction name="actionPassword"/>
|
<addaction name="actionPassword"/>
|
||||||
<addaction name="actionSeed"/>
|
<addaction name="actionSeed"/>
|
||||||
<addaction name="actionKeys"/>
|
<addaction name="actionKeys"/>
|
||||||
|
<addaction name="actionViewOnly"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="menuHistory"/>
|
<addaction name="menuHistory"/>
|
||||||
<addaction name="menuContacts"/>
|
<addaction name="menuContacts"/>
|
||||||
|
@ -518,6 +519,21 @@
|
||||||
<string>Debug info</string>
|
<string>Debug info</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionCreate_view_only_details">
|
||||||
|
<property name="text">
|
||||||
|
<string>Details</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionCreate_view_only_wallet_file">
|
||||||
|
<property name="text">
|
||||||
|
<string>Export wallet file</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionViewOnly">
|
||||||
|
<property name="text">
|
||||||
|
<string>View-Only</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
|
|
@ -84,16 +84,16 @@ struct FeatherSeed {
|
||||||
time_t time = 0;
|
time_t time = 0;
|
||||||
unsigned int restoreHeight = 0;
|
unsigned int restoreHeight = 0;
|
||||||
RestoreHeightLookup *lookup = nullptr;
|
RestoreHeightLookup *lookup = nullptr;
|
||||||
QString language = "English";
|
QString language;
|
||||||
std::string coinName;
|
std::string coinName;
|
||||||
explicit FeatherSeed(RestoreHeightLookup *lookup, const std::string &coinName = "monero") : lookup(lookup), coinName(coinName) {}
|
explicit FeatherSeed(RestoreHeightLookup *lookup, const std::string &coinName = "monero", const QString &language = "English") : lookup(lookup), coinName(coinName), language(language) {}
|
||||||
|
|
||||||
static FeatherSeed fromSeed(RestoreHeightLookup *lookup,
|
static FeatherSeed fromSeed(RestoreHeightLookup *lookup,
|
||||||
const std::string &coinName,
|
const std::string &coinName,
|
||||||
|
const QString &seedLanguage,
|
||||||
const std::string &mnemonicSeed) {
|
const std::string &mnemonicSeed) {
|
||||||
|
|
||||||
auto rtn = FeatherSeed(lookup, coinName);
|
auto rtn = FeatherSeed(lookup, coinName, seedLanguage);
|
||||||
rtn.coinName = coinName;
|
|
||||||
rtn.lookup = lookup;
|
rtn.lookup = lookup;
|
||||||
rtn.mnemonicSeed = QString::fromStdString(mnemonicSeed);
|
rtn.mnemonicSeed = QString::fromStdString(mnemonicSeed);
|
||||||
|
|
||||||
|
@ -108,8 +108,8 @@ struct FeatherSeed {
|
||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FeatherSeed generate(RestoreHeightLookup *lookup, const std::string &coinName) {
|
static FeatherSeed generate(RestoreHeightLookup *lookup, const std::string &coinName, const QString &language) {
|
||||||
auto rtn = FeatherSeed(lookup, coinName);
|
auto rtn = FeatherSeed(lookup, coinName, language);
|
||||||
time_t _time = std::time(nullptr);
|
time_t _time = std::time(nullptr);
|
||||||
monero_seed seed(_time, coinName);
|
monero_seed seed(_time, coinName);
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ struct FeatherSeed {
|
||||||
if(this->lookup == nullptr) return wallet;
|
if(this->lookup == nullptr) return wallet;
|
||||||
if(this->mnemonicSeed.split(" ").count() == 14) {
|
if(this->mnemonicSeed.split(" ").count() == 14) {
|
||||||
if(this->spendKey.isEmpty()) {
|
if(this->spendKey.isEmpty()) {
|
||||||
auto _seed = FeatherSeed::fromSeed(this->lookup, this->coinName, this->mnemonicSeed.toStdString());
|
auto _seed = FeatherSeed::fromSeed(this->lookup, this->coinName, this->language, this->mnemonicSeed.toStdString());
|
||||||
_seed.setRestoreHeight();
|
_seed.setRestoreHeight();
|
||||||
this->time = _seed.time;
|
this->time = _seed.time;
|
||||||
this->restoreHeight = _seed.restoreHeight;
|
this->restoreHeight = _seed.restoreHeight;
|
||||||
|
|
|
@ -82,7 +82,12 @@ bool CreateWalletPage::validateWidgets(){
|
||||||
|
|
||||||
int CreateWalletPage::nextId() const {
|
int CreateWalletPage::nextId() const {
|
||||||
auto restoredSeed = this->field("mnemonicRestoredSeed").toString();
|
auto restoredSeed = this->field("mnemonicRestoredSeed").toString();
|
||||||
return restoredSeed.isEmpty() ? WalletWizard::Page_CreateWalletSeed : -1;
|
auto restoredViewOnlyKey = this->field("viewOnlyViewKey").toString();
|
||||||
|
|
||||||
|
if(!restoredSeed.isEmpty() || !restoredViewOnlyKey.isEmpty())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return WalletWizard::Page_CreateWalletSeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreateWalletPage::validatePage() {
|
bool CreateWalletPage::validatePage() {
|
||||||
|
@ -93,6 +98,7 @@ bool CreateWalletPage::validatePage() {
|
||||||
ui->walletName->setStyleSheet("");
|
ui->walletName->setStyleSheet("");
|
||||||
|
|
||||||
auto restoredSeed = this->field("mnemonicRestoredSeed").toString();
|
auto restoredSeed = this->field("mnemonicRestoredSeed").toString();
|
||||||
if(!restoredSeed.isEmpty()) emit createWallet();
|
auto restoredViewOnlyKey = this->field("viewOnlyViewKey").toString();
|
||||||
|
if(!restoredSeed.isEmpty() || !restoredViewOnlyKey.isEmpty()) emit createWallet();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ CreateWalletSeedPage::CreateWalletSeedPage(AppContext *ctx, QWidget *parent) :
|
||||||
void CreateWalletSeedPage::seedRoulette(int count) {
|
void CreateWalletSeedPage::seedRoulette(int count) {
|
||||||
count += 1;
|
count += 1;
|
||||||
if(count > m_rouletteSpin) return;
|
if(count > m_rouletteSpin) return;
|
||||||
auto seed = FeatherSeed::generate(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString());
|
auto seed = FeatherSeed::generate(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage);
|
||||||
m_mnemonic = seed.mnemonicSeed;
|
m_mnemonic = seed.mnemonicSeed;
|
||||||
m_restoreHeight = seed.restoreHeight;
|
m_restoreHeight = seed.restoreHeight;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ int MenuPage::nextId() const {
|
||||||
return WalletWizard::Page_CreateWallet;
|
return WalletWizard::Page_CreateWallet;
|
||||||
if(ui->radioSeed->isChecked())
|
if(ui->radioSeed->isChecked())
|
||||||
return WalletWizard::Page_Restore;
|
return WalletWizard::Page_Restore;
|
||||||
|
if(ui->radioViewOnly->isChecked())
|
||||||
|
return WalletWizard::Page_ViewOnly;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="radioViewOnly">
|
||||||
|
<property name="text">
|
||||||
|
<string>Import from keys</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -130,7 +130,7 @@ bool RestorePage::validatePage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto _seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], "monero", seed.toStdString());
|
auto _seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage, seed.toStdString());
|
||||||
restoreHeight = _seed.restoreHeight;
|
restoreHeight = _seed.restoreHeight;
|
||||||
|
|
||||||
this->setField("restoreHeight", restoreHeight);
|
this->setField("restoreHeight", restoreHeight);
|
||||||
|
@ -153,7 +153,7 @@ bool RestorePage::validatePage() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto _seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], "monero", seed.toStdString());
|
auto _seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage, seed.toStdString());
|
||||||
_seed.setRestoreHeight(restoreHeight);
|
_seed.setRestoreHeight(restoreHeight);
|
||||||
this->setField("restoreHeight", restoreHeight);
|
this->setField("restoreHeight", restoreHeight);
|
||||||
this->setField("mnemonicSeed", seed);
|
this->setField("mnemonicSeed", seed);
|
||||||
|
|
106
src/wizard/viewonlywallet.cpp
Normal file
106
src/wizard/viewonlywallet.cpp
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020, The Monero Project.
|
||||||
|
|
||||||
|
#include "wizard/viewonlywallet.h"
|
||||||
|
#include "wizard/walletwizard.h"
|
||||||
|
#include "ui_viewonlywallet.h"
|
||||||
|
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include <QTextCharFormat>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QButtonGroup>
|
||||||
|
|
||||||
|
#include <monero_seed/wordlist.hpp> // tevador 14 word
|
||||||
|
|
||||||
|
#include "libwalletqt/WalletManager.h"
|
||||||
|
|
||||||
|
ViewOnlyPage::ViewOnlyPage(AppContext *ctx, QWidget *parent) :
|
||||||
|
QWizardPage(parent),
|
||||||
|
ui(new Ui::ViewOnlyPage),
|
||||||
|
m_ctx(ctx) {
|
||||||
|
ui->setupUi(this);
|
||||||
|
this->setTitle("Import view only wallet");
|
||||||
|
ui->label_errorString->hide();
|
||||||
|
|
||||||
|
QFont f("feather");
|
||||||
|
f.setStyleHint(QFont::Monospace);
|
||||||
|
|
||||||
|
auto *viewOnlyViewKeyDummy = new QLineEdit(this);
|
||||||
|
viewOnlyViewKeyDummy->setVisible(false);
|
||||||
|
auto *viewOnlySpendKeyDummy = new QLineEdit(this);
|
||||||
|
viewOnlySpendKeyDummy->setVisible(false);
|
||||||
|
auto *viewOnlyAddressDummy = new QLineEdit(this);
|
||||||
|
viewOnlyAddressDummy->setVisible(false);
|
||||||
|
auto *restoreHeightDummy = new QLineEdit(this);
|
||||||
|
restoreHeightDummy->setVisible(false);
|
||||||
|
|
||||||
|
this->registerField("viewOnlySpendKey", viewOnlySpendKeyDummy);
|
||||||
|
this->registerField("viewOnlyViewKey", viewOnlyViewKeyDummy);
|
||||||
|
this->registerField("viewOnlyAddress", viewOnlyAddressDummy);
|
||||||
|
this->registerField("viewOnlyHeight", restoreHeightDummy);
|
||||||
|
|
||||||
|
#ifndef QT_NO_CURSOR
|
||||||
|
QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||||
|
QGuiApplication::restoreOverrideCursor();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(m_ctx->networkType == NetworkType::Type::TESTNET) {
|
||||||
|
ui->restoreHeightWidget->hideSlider();
|
||||||
|
} else {
|
||||||
|
// load restoreHeight lookup db
|
||||||
|
ui->restoreHeightWidget->initRestoreHeights(m_ctx->restoreHeights[m_ctx->networkType]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_ctx->networkType == NetworkType::Type::MAINNET) {
|
||||||
|
ui->lineEdit_address->setPlaceholderText("4...");
|
||||||
|
} else if (m_ctx->networkType == NetworkType::Type::STAGENET) {
|
||||||
|
ui->lineEdit_address->setPlaceholderText("5...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ViewOnlyPage::nextId() const {
|
||||||
|
return WalletWizard::Page_CreateWallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewOnlyPage::cleanupPage() const {}
|
||||||
|
|
||||||
|
bool ViewOnlyPage::validatePage() {
|
||||||
|
auto errStyle = "QLineEdit{border: 1px solid red;}";
|
||||||
|
|
||||||
|
ui->lineEdit_address->setStyleSheet("");
|
||||||
|
ui->lineEdit_viewkey->setStyleSheet("");
|
||||||
|
ui->label_errorString->hide();
|
||||||
|
|
||||||
|
unsigned int restoreHeight = ui->restoreHeightWidget->getHeight();
|
||||||
|
auto spendkey = ui->lineEdit_spendkey->text().trimmed();
|
||||||
|
auto viewkey = ui->lineEdit_viewkey->text().trimmed();
|
||||||
|
auto address = ui->lineEdit_address->text().trimmed();
|
||||||
|
|
||||||
|
if(!m_ctx->walletManager->addressValid(address, m_ctx->networkType)){
|
||||||
|
ui->label_errorString->show();
|
||||||
|
ui->label_errorString->setText("Invalid address.");
|
||||||
|
ui->lineEdit_address->setStyleSheet(errStyle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_ctx->walletManager->keyValid(viewkey, address, true, m_ctx->networkType)) {
|
||||||
|
ui->label_errorString->show();
|
||||||
|
ui->label_errorString->setText("Invalid key.");
|
||||||
|
ui->lineEdit_viewkey->setStyleSheet(errStyle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!spendkey.isEmpty() && !m_ctx->walletManager->keyValid(spendkey, address, false, m_ctx->networkType)) {
|
||||||
|
ui->label_errorString->show();
|
||||||
|
ui->label_errorString->setText("Invalid key.");
|
||||||
|
ui->lineEdit_viewkey->setStyleSheet(errStyle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setField("viewOnlyViewKey", viewkey);
|
||||||
|
this->setField("viewOnlySpendKey", spendkey);
|
||||||
|
this->setField("viewOnlyAddress", address);
|
||||||
|
this->setField("viewOnlyHeight", restoreHeight);
|
||||||
|
return true;
|
||||||
|
}
|
36
src/wizard/viewonlywallet.h
Normal file
36
src/wizard/viewonlywallet.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020, The Monero Project.
|
||||||
|
|
||||||
|
#ifndef FEATHER_WIZARDVIEWONLY_H
|
||||||
|
#define FEATHER_WIZARDVIEWONLY_H
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QWizardPage>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QCompleter>
|
||||||
|
|
||||||
|
#include "appcontext.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ViewOnlyPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewOnlyPage : public QWizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ViewOnlyPage(AppContext *ctx, QWidget *parent = nullptr);
|
||||||
|
bool validatePage() override;
|
||||||
|
int nextId() const override;
|
||||||
|
void cleanupPage() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppContext *m_ctx;
|
||||||
|
QLabel *topLabel;
|
||||||
|
Ui::ViewOnlyPage *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
119
src/wizard/viewonlywallet.ui
Normal file
119
src/wizard/viewonlywallet.ui
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ViewOnlyPage</class>
|
||||||
|
<widget class="QWizardPage" name="ViewOnlyPage">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>502</width>
|
||||||
|
<height>506</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>ViewOnlyPage</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Standard address</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_address"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Secret view key</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_viewkey"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Secret spend key (optional)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit_spendkey"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="restoreFrame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="RestoreHeightWidget" name="restoreHeightWidget" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_restoreHeightInfo">
|
||||||
|
<property name="text">
|
||||||
|
<string>You may specify the "restore height". This is the moment the wallet was created, expressed through a blockheight (number). This speeds up wallet refreshes. If you don't know, leave it empty.</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_errorString">
|
||||||
|
<property name="text">
|
||||||
|
<string>errorString</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>RestoreHeightWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>widgets/restoreheightwidget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -9,9 +9,11 @@
|
||||||
#include "wizard/network.h"
|
#include "wizard/network.h"
|
||||||
#include "wizard/createwalletseed.h"
|
#include "wizard/createwalletseed.h"
|
||||||
#include "wizard/restorewallet.h"
|
#include "wizard/restorewallet.h"
|
||||||
|
#include "wizard/viewonlywallet.h"
|
||||||
|
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
@ -29,6 +31,7 @@ WalletWizard::WalletWizard(AppContext *ctx, WalletWizard::Page startPage, QWidge
|
||||||
setPage(Page_CreateWalletSeed, createWalletSeed);
|
setPage(Page_CreateWalletSeed, createWalletSeed);
|
||||||
setPage(Page_Network, new NetworkPage(m_ctx, this));
|
setPage(Page_Network, new NetworkPage(m_ctx, this));
|
||||||
setPage(Page_Restore, new RestorePage(m_ctx, this));
|
setPage(Page_Restore, new RestorePage(m_ctx, this));
|
||||||
|
setPage(Page_ViewOnly, new ViewOnlyPage(m_ctx, this));
|
||||||
|
|
||||||
if(config()->get(Config::firstRun).toUInt())
|
if(config()->get(Config::firstRun).toUInt())
|
||||||
setStartId(Page_Network);
|
setStartId(Page_Network);
|
||||||
|
@ -58,8 +61,20 @@ void WalletWizard::createWallet() {
|
||||||
const auto walletPath = this->field("walletPath").toString();
|
const auto walletPath = this->field("walletPath").toString();
|
||||||
const auto walletPasswd = this->field("walletPasswd").toString();
|
const auto walletPasswd = this->field("walletPasswd").toString();
|
||||||
auto restoreHeight = this->field("restoreHeight").toUInt();
|
auto restoreHeight = this->field("restoreHeight").toUInt();
|
||||||
|
auto viewKey = this->field("viewOnlyViewKey").toString();
|
||||||
|
auto spendKey = this->field("viewOnlySpendKey").toString();
|
||||||
|
auto viewAddress = this->field("viewOnlyAddress").toString();
|
||||||
|
|
||||||
auto seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), mnemonicSeed.toStdString());
|
if(!viewKey.isEmpty() && !viewAddress.isEmpty()) {
|
||||||
|
auto viewHeight = this->field("viewOnlyHeight").toUInt();
|
||||||
|
m_ctx->createWalletViewOnly(walletPath,
|
||||||
|
walletPasswd,
|
||||||
|
viewAddress,
|
||||||
|
viewKey, spendKey, viewHeight);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto seed = FeatherSeed::fromSeed(m_ctx->restoreHeights[m_ctx->networkType], m_ctx->coinName.toStdString(), m_ctx->seedLanguage, mnemonicSeed.toStdString());
|
||||||
if(restoreHeight > 0)
|
if(restoreHeight > 0)
|
||||||
seed.setRestoreHeight(restoreHeight);
|
seed.setRestoreHeight(restoreHeight);
|
||||||
m_ctx->createWallet(seed, walletPath, walletPasswd);
|
m_ctx->createWallet(seed, walletPath, walletPasswd);
|
||||||
|
|
|
@ -17,7 +17,7 @@ class WalletWizard : public QWizard
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Page { Page_Menu, Page_CreateWallet, Page_CreateWalletSeed, Page_OpenWallet, Page_Network, Page_Restore };
|
enum Page { Page_Menu, Page_CreateWallet, Page_CreateWalletSeed, Page_OpenWallet, Page_Network, Page_Restore, Page_ViewOnly };
|
||||||
|
|
||||||
explicit WalletWizard(AppContext *ctx, WalletWizard::Page startPage = WalletWizard::Page::Page_Menu, QWidget *parent = nullptr);
|
explicit WalletWizard(AppContext *ctx, WalletWizard::Page startPage = WalletWizard::Page::Page_Menu, QWidget *parent = nullptr);
|
||||||
signals:
|
signals:
|
||||||
|
|
Loading…
Reference in a new issue