mirror of
https://github.com/monero-project/monero-gui.git
synced 2024-12-23 12:09:57 +00:00
async device open and create from device, passphrase
- passphrase entry on host added, requires early listener setting monero pull #5355 - wallet open and create from device shows splash to indicate possible long process - create from device is async to support passphrase entry
This commit is contained in:
parent
19c2208dc4
commit
1a2675b246
10 changed files with 607 additions and 14 deletions
327
components/PassphraseDialog.qml
Normal file
327
components/PassphraseDialog.qml
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
// Copyright (c) 2014-2019, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
|
||||||
|
import "../components" as MoneroComponents
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
visible: false
|
||||||
|
z: parent.z + 2
|
||||||
|
|
||||||
|
property bool isHidden: true
|
||||||
|
property alias passphrase: passphaseInput1.text
|
||||||
|
property string walletName
|
||||||
|
property string errorText
|
||||||
|
|
||||||
|
// same signals as Dialog has
|
||||||
|
signal accepted()
|
||||||
|
signal rejected()
|
||||||
|
signal closeCallback()
|
||||||
|
|
||||||
|
function open(walletName, errorText) {
|
||||||
|
inactiveOverlay.visible = true
|
||||||
|
|
||||||
|
root.walletName = walletName ? walletName : ""
|
||||||
|
root.errorText = errorText ? errorText : "";
|
||||||
|
|
||||||
|
leftPanel.enabled = false
|
||||||
|
middlePanel.enabled = false
|
||||||
|
titleBar.enabled = false
|
||||||
|
show();
|
||||||
|
root.visible = true;
|
||||||
|
passphaseInput1.text = "";
|
||||||
|
passphaseInput2.text = "";
|
||||||
|
passphaseInput1.focus = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function close() {
|
||||||
|
inactiveOverlay.visible = false
|
||||||
|
leftPanel.enabled = true
|
||||||
|
middlePanel.enabled = true
|
||||||
|
titleBar.enabled = true
|
||||||
|
root.visible = false;
|
||||||
|
closeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleIsHidden() {
|
||||||
|
passphaseInput1.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
|
||||||
|
passphaseInput2.echoMode = isHidden ? TextInput.Normal : TextInput.Password;
|
||||||
|
isHidden = !isHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(errorText) {
|
||||||
|
open(root.walletName, errorText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement without hardcoding sizes
|
||||||
|
width: 480
|
||||||
|
height: 360
|
||||||
|
|
||||||
|
// Make window draggable
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
property point lastMousePos: Qt.point(0, 0)
|
||||||
|
onPressed: { lastMousePos = Qt.point(mouseX, mouseY); }
|
||||||
|
onMouseXChanged: root.x += (mouseX - lastMousePos.x)
|
||||||
|
onMouseYChanged: root.y += (mouseY - lastMousePos.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
z: inactiveOverlay.z + 1
|
||||||
|
id: mainLayout
|
||||||
|
spacing: 10
|
||||||
|
anchors { fill: parent; margins: 35 * scaleRatio }
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: column
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
Layout.maximumWidth: 400 * scaleRatio
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: root.walletName.length > 0 ? qsTr("Please enter wallet device passphrase for: ") + root.walletName : qsTr("Please enter wallet device passphrase")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
font.pixelSize: 16 * scaleRatio
|
||||||
|
font.family: MoneroComponents.Style.fontLight.name
|
||||||
|
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Warning: passphrase entry on host is a security risk as it can be captured by malware. It is advised to prefer device-based passphrase entry.");
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
|
||||||
|
font.pixelSize: 14 * scaleRatio
|
||||||
|
font.family: MoneroComponents.Style.fontLight.name
|
||||||
|
|
||||||
|
color: MoneroComponents.Style.warningColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: root.errorText
|
||||||
|
visible: root.errorText
|
||||||
|
|
||||||
|
color: MoneroComponents.Style.errorColor
|
||||||
|
font.pixelSize: 16 * scaleRatio
|
||||||
|
font.family: MoneroComponents.Style.fontLight.name
|
||||||
|
Layout.fillWidth: true
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id : passphaseInput1
|
||||||
|
Layout.topMargin: 6
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: TextInput.AlignLeft
|
||||||
|
verticalAlignment: TextInput.AlignVCenter
|
||||||
|
font.family: MoneroComponents.Style.fontLight.name
|
||||||
|
font.pixelSize: 24 * scaleRatio
|
||||||
|
echoMode: TextInput.Password
|
||||||
|
bottomPadding: 10
|
||||||
|
leftPadding: 10
|
||||||
|
topPadding: 10
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
selectionColor: MoneroComponents.Style.dimmedFontColor
|
||||||
|
selectedTextColor: MoneroComponents.Style.defaultFontColor
|
||||||
|
KeyNavigation.tab: passphaseInput2
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
radius: 2
|
||||||
|
border.color: Qt.rgba(255, 255, 255, 0.35)
|
||||||
|
border.width: 1
|
||||||
|
color: "black"
|
||||||
|
|
||||||
|
Image {
|
||||||
|
width: 26 * scaleRatio
|
||||||
|
height: 26 * scaleRatio
|
||||||
|
opacity: 0.7
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: isHidden ? "../images/eyeShow.png" : "../images/eyeHide.png"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 20
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
toggleIsHidden()
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
parent.opacity = 0.9
|
||||||
|
parent.width = 28 * scaleRatio
|
||||||
|
parent.height = 28 * scaleRatio
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
parent.opacity = 0.7
|
||||||
|
parent.width = 26 * scaleRatio
|
||||||
|
parent.height = 26 * scaleRatio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onEscapePressed: {
|
||||||
|
root.close()
|
||||||
|
root.rejected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// padding
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
height: 10
|
||||||
|
opacity: 0
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: qsTr("Please re-enter")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
font.pixelSize: 16 * scaleRatio
|
||||||
|
font.family: MoneroComponents.Style.fontLight.name
|
||||||
|
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id : passphaseInput2
|
||||||
|
Layout.topMargin: 6
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: TextInput.AlignLeft
|
||||||
|
verticalAlignment: TextInput.AlignVCenter
|
||||||
|
font.family: MoneroComponents.Style.fontLight.name
|
||||||
|
font.pixelSize: 24 * scaleRatio
|
||||||
|
echoMode: TextInput.Password
|
||||||
|
KeyNavigation.tab: okButton
|
||||||
|
bottomPadding: 10
|
||||||
|
leftPadding: 10
|
||||||
|
topPadding: 10
|
||||||
|
color: MoneroComponents.Style.defaultFontColor
|
||||||
|
selectionColor: MoneroComponents.Style.dimmedFontColor
|
||||||
|
selectedTextColor: MoneroComponents.Style.defaultFontColor
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
radius: 2
|
||||||
|
border.color: Qt.rgba(255, 255, 255, 0.35)
|
||||||
|
border.width: 1
|
||||||
|
color: "black"
|
||||||
|
|
||||||
|
Image {
|
||||||
|
width: 26 * scaleRatio
|
||||||
|
height: 26 * scaleRatio
|
||||||
|
opacity: 0.7
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: isHidden ? "../images/eyeShow.png" : "../images/eyeHide.png"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 20
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: {
|
||||||
|
toggleIsHidden()
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
parent.opacity = 0.9
|
||||||
|
parent.width = 28 * scaleRatio
|
||||||
|
parent.height = 28 * scaleRatio
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
parent.opacity = 0.7
|
||||||
|
parent.width = 26 * scaleRatio
|
||||||
|
parent.height = 26 * scaleRatio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
if (passphaseInput1.text === passphaseInput2.text) {
|
||||||
|
root.close()
|
||||||
|
root.accepted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Keys.onEscapePressed: {
|
||||||
|
root.close()
|
||||||
|
root.rejected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// padding
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
height: 10
|
||||||
|
opacity: 0
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ok/Cancel buttons
|
||||||
|
RowLayout {
|
||||||
|
id: buttons
|
||||||
|
spacing: 16 * scaleRatio
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: cancelButton
|
||||||
|
text: qsTr("Cancel") + translationManager.emptyString
|
||||||
|
KeyNavigation.tab: passphaseInput1
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
root.rejected()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MoneroComponents.StandardButton {
|
||||||
|
id: okButton
|
||||||
|
text: qsTr("Continue")
|
||||||
|
KeyNavigation.tab: cancelButton
|
||||||
|
enabled: passphaseInput1.text === passphaseInput2.text
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
root.accepted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ QtObject {
|
||||||
property string defaultFontColor: "white"
|
property string defaultFontColor: "white"
|
||||||
property string dimmedFontColor: "#BBBBBB"
|
property string dimmedFontColor: "#BBBBBB"
|
||||||
property string lightGreyFontColor: "#DFDFDF"
|
property string lightGreyFontColor: "#DFDFDF"
|
||||||
|
property string warningColor: "#963E00"
|
||||||
property string errorColor: "#FA6800"
|
property string errorColor: "#FA6800"
|
||||||
property string inputBoxBackground: "black"
|
property string inputBoxBackground: "black"
|
||||||
property string inputBoxBackgroundError: "#FFDDDD"
|
property string inputBoxBackgroundError: "#FFDDDD"
|
||||||
|
|
65
main.qml
65
main.qml
|
@ -85,6 +85,8 @@ ApplicationWindow {
|
||||||
property int disconnectedEpoch: 0
|
property int disconnectedEpoch: 0
|
||||||
property int estimatedBlockchainSize: 75 // GB
|
property int estimatedBlockchainSize: 75 // GB
|
||||||
property alias viewState: rootItem.state
|
property alias viewState: rootItem.state
|
||||||
|
property string prevSplashText;
|
||||||
|
property bool splashDisplayedBeforeButtonRequest;
|
||||||
|
|
||||||
property string remoteNodeService: {
|
property string remoteNodeService: {
|
||||||
// support user-defined remote node aggregators
|
// support user-defined remote node aggregators
|
||||||
|
@ -266,6 +268,8 @@ ApplicationWindow {
|
||||||
wallet_path = moneroAccountsDir + wallet_path;
|
wallet_path = moneroAccountsDir + wallet_path;
|
||||||
// console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.walletPassword);
|
// console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.walletPassword);
|
||||||
console.log("opening wallet at: ", wallet_path, ", network type: ", persistentSettings.nettype == NetworkType.MAINNET ? "mainnet" : persistentSettings.nettype == NetworkType.TESTNET ? "testnet" : "stagenet");
|
console.log("opening wallet at: ", wallet_path, ", network type: ", persistentSettings.nettype == NetworkType.MAINNET ? "mainnet" : persistentSettings.nettype == NetworkType.TESTNET ? "testnet" : "stagenet");
|
||||||
|
|
||||||
|
this.onWalletOpening();
|
||||||
walletManager.openWalletAsync(wallet_path, walletPassword,
|
walletManager.openWalletAsync(wallet_path, walletPassword,
|
||||||
persistentSettings.nettype, persistentSettings.kdfRounds);
|
persistentSettings.nettype, persistentSettings.kdfRounds);
|
||||||
}
|
}
|
||||||
|
@ -286,6 +290,8 @@ ApplicationWindow {
|
||||||
currentWallet.unconfirmedMoneyReceived.disconnect(onWalletUnconfirmedMoneyReceived)
|
currentWallet.unconfirmedMoneyReceived.disconnect(onWalletUnconfirmedMoneyReceived)
|
||||||
currentWallet.transactionCreated.disconnect(onTransactionCreated)
|
currentWallet.transactionCreated.disconnect(onTransactionCreated)
|
||||||
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
|
currentWallet.connectionStatusChanged.disconnect(onWalletConnectionStatusChanged)
|
||||||
|
currentWallet.deviceButtonRequest.disconnect(onDeviceButtonRequest);
|
||||||
|
currentWallet.deviceButtonPressed.disconnect(onDeviceButtonPressed);
|
||||||
middlePanel.paymentClicked.disconnect(handlePayment);
|
middlePanel.paymentClicked.disconnect(handlePayment);
|
||||||
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
|
middlePanel.sweepUnmixableClicked.disconnect(handleSweepUnmixable);
|
||||||
middlePanel.getProofClicked.disconnect(handleGetProof);
|
middlePanel.getProofClicked.disconnect(handleGetProof);
|
||||||
|
@ -341,6 +347,8 @@ ApplicationWindow {
|
||||||
currentWallet.unconfirmedMoneyReceived.connect(onWalletUnconfirmedMoneyReceived)
|
currentWallet.unconfirmedMoneyReceived.connect(onWalletUnconfirmedMoneyReceived)
|
||||||
currentWallet.transactionCreated.connect(onTransactionCreated)
|
currentWallet.transactionCreated.connect(onTransactionCreated)
|
||||||
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
|
currentWallet.connectionStatusChanged.connect(onWalletConnectionStatusChanged)
|
||||||
|
currentWallet.deviceButtonRequest.connect(onDeviceButtonRequest);
|
||||||
|
currentWallet.deviceButtonPressed.connect(onDeviceButtonPressed);
|
||||||
middlePanel.paymentClicked.connect(handlePayment);
|
middlePanel.paymentClicked.connect(handlePayment);
|
||||||
middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable);
|
middlePanel.sweepUnmixableClicked.connect(handleSweepUnmixable);
|
||||||
middlePanel.getProofClicked.connect(handleGetProof);
|
middlePanel.getProofClicked.connect(handleGetProof);
|
||||||
|
@ -422,7 +430,26 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onDeviceButtonRequest(code){
|
||||||
|
prevSplashText = splash.messageText;
|
||||||
|
splashDisplayedBeforeButtonRequest = splash.visible;
|
||||||
|
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDeviceButtonPressed(){
|
||||||
|
if (splashDisplayedBeforeButtonRequest){
|
||||||
|
appWindow.showProcessingSplash(prevSplashText);
|
||||||
|
} else {
|
||||||
|
hideProcessingSplash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWalletOpening(){
|
||||||
|
appWindow.showProcessingSplash(qsTr("Opening wallet ..."));
|
||||||
|
}
|
||||||
|
|
||||||
function onWalletOpened(wallet) {
|
function onWalletOpened(wallet) {
|
||||||
|
hideProcessingSplash();
|
||||||
walletName = usefulName(wallet.path)
|
walletName = usefulName(wallet.path)
|
||||||
console.log(">>> wallet opened: " + wallet)
|
console.log(">>> wallet opened: " + wallet)
|
||||||
if (wallet.status !== Wallet.Status_Ok) {
|
if (wallet.status !== Wallet.Status_Ok) {
|
||||||
|
@ -470,9 +497,27 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWalletClosed(walletAddress) {
|
function onWalletClosed(walletAddress) {
|
||||||
|
hideProcessingSplash();
|
||||||
console.log(">>> wallet closed: " + walletAddress)
|
console.log(">>> wallet closed: " + walletAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onWalletPassphraseNeeded(){
|
||||||
|
if(rootItem.state !== "normal") return;
|
||||||
|
|
||||||
|
hideProcessingSplash();
|
||||||
|
|
||||||
|
console.log(">>> wallet passphrase needed: ")
|
||||||
|
passphraseDialog.onAcceptedCallback = function() {
|
||||||
|
walletManager.onPassphraseEntered(passphraseDialog.passphrase);
|
||||||
|
this.onWalletOpening();
|
||||||
|
}
|
||||||
|
passphraseDialog.onRejectedCallback = function() {
|
||||||
|
walletManager.onPassphraseEntered("", true);
|
||||||
|
this.onWalletOpening();
|
||||||
|
}
|
||||||
|
passphraseDialog.open()
|
||||||
|
}
|
||||||
|
|
||||||
function onWalletUpdate() {
|
function onWalletUpdate() {
|
||||||
console.log(">>> wallet updated")
|
console.log(">>> wallet updated")
|
||||||
updateBalance();
|
updateBalance();
|
||||||
|
@ -1017,7 +1062,10 @@ ApplicationWindow {
|
||||||
//
|
//
|
||||||
walletManager.walletOpened.connect(onWalletOpened);
|
walletManager.walletOpened.connect(onWalletOpened);
|
||||||
walletManager.walletClosed.connect(onWalletClosed);
|
walletManager.walletClosed.connect(onWalletClosed);
|
||||||
|
walletManager.deviceButtonRequest.connect(onDeviceButtonRequest);
|
||||||
|
walletManager.deviceButtonPressed.connect(onDeviceButtonPressed);
|
||||||
walletManager.checkUpdatesComplete.connect(onWalletCheckUpdatesComplete);
|
walletManager.checkUpdatesComplete.connect(onWalletCheckUpdatesComplete);
|
||||||
|
walletManager.walletPassphraseNeeded.connect(onWalletPassphraseNeeded);
|
||||||
|
|
||||||
if(typeof daemonManager != "undefined") {
|
if(typeof daemonManager != "undefined") {
|
||||||
daemonManager.daemonStarted.connect(onDaemonStarted);
|
daemonManager.daemonStarted.connect(onDaemonStarted);
|
||||||
|
@ -1245,6 +1293,23 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PassphraseDialog {
|
||||||
|
id: passphraseDialog
|
||||||
|
visible: false
|
||||||
|
z: parent.z + 1
|
||||||
|
anchors.fill: parent
|
||||||
|
property var onAcceptedCallback
|
||||||
|
property var onRejectedCallback
|
||||||
|
onAccepted: {
|
||||||
|
if (onAcceptedCallback)
|
||||||
|
onAcceptedCallback();
|
||||||
|
}
|
||||||
|
onRejected: {
|
||||||
|
if (onRejectedCallback)
|
||||||
|
onRejectedCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PasswordDialog {
|
PasswordDialog {
|
||||||
id: passwordDialog
|
id: passwordDialog
|
||||||
visible: false
|
visible: false
|
||||||
|
|
1
qml.qrc
1
qml.qrc
|
@ -117,6 +117,7 @@
|
||||||
<file>pages/TxKey.qml</file>
|
<file>pages/TxKey.qml</file>
|
||||||
<file>pages/SharedRingDB.qml</file>
|
<file>pages/SharedRingDB.qml</file>
|
||||||
<file>components/IconButton.qml</file>
|
<file>components/IconButton.qml</file>
|
||||||
|
<file>components/PassphraseDialog.qml</file>
|
||||||
<file>components/PasswordDialog.qml</file>
|
<file>components/PasswordDialog.qml</file>
|
||||||
<file>components/NewPasswordDialog.qml</file>
|
<file>components/NewPasswordDialog.qml</file>
|
||||||
<file>components/InputDialog.qml</file>
|
<file>components/InputDialog.qml</file>
|
||||||
|
|
|
@ -75,6 +75,16 @@ public:
|
||||||
emit m_wallet->refreshed();
|
emit m_wallet->refreshed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void onDeviceButtonRequest(uint64_t code) override
|
||||||
|
{
|
||||||
|
emit m_wallet->deviceButtonRequest(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onDeviceButtonPressed() override
|
||||||
|
{
|
||||||
|
emit m_wallet->deviceButtonPressed();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Wallet * m_wallet;
|
Wallet * m_wallet;
|
||||||
};
|
};
|
||||||
|
|
|
@ -322,6 +322,8 @@ signals:
|
||||||
void newBlock(quint64 height, quint64 targetHeight);
|
void newBlock(quint64 height, quint64 targetHeight);
|
||||||
void historyModelChanged() const;
|
void historyModelChanged() const;
|
||||||
void walletCreationHeightChanged();
|
void walletCreationHeightChanged();
|
||||||
|
void deviceButtonRequest(quint64 buttonCode);
|
||||||
|
void deviceButtonPressed();
|
||||||
|
|
||||||
// emitted when transaction is created async
|
// emitted when transaction is created async
|
||||||
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
|
void transactionCreated(PendingTransaction * transaction, QString address, QString paymentId, quint32 mixinCount);
|
||||||
|
|
|
@ -13,6 +13,57 @@
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
class WalletPassphraseListenerImpl : public Monero::WalletListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WalletPassphraseListenerImpl(WalletManager * mgr): m_mgr(mgr), m_wallet(nullptr) {}
|
||||||
|
|
||||||
|
virtual void moneySpent(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
||||||
|
virtual void moneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
||||||
|
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
||||||
|
virtual void newBlock(uint64_t height) override { (void) height; };
|
||||||
|
virtual void updated() override {};
|
||||||
|
virtual void refreshed() override {};
|
||||||
|
|
||||||
|
virtual Monero::optional<std::string> onDevicePassphraseRequest(bool on_device) override
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
if (on_device) return Monero::optional<std::string>();
|
||||||
|
|
||||||
|
m_mgr->onWalletPassphraseNeeded(m_wallet);
|
||||||
|
|
||||||
|
if (m_mgr->m_passphrase_abort)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Passphrase entry abort");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tmpPass = m_mgr->m_passphrase.toStdString();
|
||||||
|
m_mgr->m_passphrase = QString::null;
|
||||||
|
|
||||||
|
return Monero::optional<std::string>(tmpPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onDeviceButtonRequest(uint64_t code) override
|
||||||
|
{
|
||||||
|
emit m_mgr->deviceButtonRequest(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onDeviceButtonPressed() override
|
||||||
|
{
|
||||||
|
emit m_mgr->deviceButtonPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onSetWallet(Monero::Wallet * wallet) override
|
||||||
|
{
|
||||||
|
qDebug() << __FUNCTION__;
|
||||||
|
m_wallet = wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Monero::Wallet * m_wallet;
|
||||||
|
WalletManager * m_mgr;
|
||||||
|
};
|
||||||
|
|
||||||
WalletManager * WalletManager::m_instance = nullptr;
|
WalletManager * WalletManager::m_instance = nullptr;
|
||||||
|
|
||||||
WalletManager *WalletManager::instance()
|
WalletManager *WalletManager::instance()
|
||||||
|
@ -41,6 +92,8 @@ Wallet *WalletManager::createWallet(const QString &path, const QString &password
|
||||||
Wallet *WalletManager::openWallet(const QString &path, const QString &password, NetworkType::Type nettype, quint64 kdfRounds)
|
Wallet *WalletManager::openWallet(const QString &path, const QString &password, NetworkType::Type nettype, quint64 kdfRounds)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
WalletPassphraseListenerImpl tmpListener(this);
|
||||||
|
|
||||||
if (m_currentWallet) {
|
if (m_currentWallet) {
|
||||||
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
||||||
delete m_currentWallet;
|
delete m_currentWallet;
|
||||||
|
@ -48,7 +101,9 @@ Wallet *WalletManager::openWallet(const QString &path, const QString &password,
|
||||||
qDebug("%s: opening wallet at %s, nettype = %d ",
|
qDebug("%s: opening wallet at %s, nettype = %d ",
|
||||||
__PRETTY_FUNCTION__, qPrintable(path), nettype);
|
__PRETTY_FUNCTION__, qPrintable(path), nettype);
|
||||||
|
|
||||||
Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), static_cast<Monero::NetworkType>(nettype), kdfRounds);
|
Monero::Wallet * w = m_pimpl->openWallet(path.toStdString(), password.toStdString(), static_cast<Monero::NetworkType>(nettype), kdfRounds, &tmpListener);
|
||||||
|
w->setListener(nullptr);
|
||||||
|
|
||||||
qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address(0, 0).c_str(), w->status());
|
qDebug("%s: opened wallet: %s, status: %d", __PRETTY_FUNCTION__, w->address(0, 0).c_str(), w->status());
|
||||||
m_currentWallet = new Wallet(w);
|
m_currentWallet = new Wallet(w);
|
||||||
|
|
||||||
|
@ -108,17 +163,48 @@ Wallet *WalletManager::createWalletFromDevice(const QString &path, const QString
|
||||||
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
|
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
WalletPassphraseListenerImpl tmpListener(this);
|
||||||
|
|
||||||
if (m_currentWallet) {
|
if (m_currentWallet) {
|
||||||
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
qDebug() << "Closing open m_currentWallet" << m_currentWallet;
|
||||||
delete m_currentWallet;
|
delete m_currentWallet;
|
||||||
m_currentWallet = NULL;
|
m_currentWallet = NULL;
|
||||||
}
|
}
|
||||||
Monero::Wallet * w = m_pimpl->createWalletFromDevice(path.toStdString(), password.toStdString(), static_cast<Monero::NetworkType>(nettype),
|
Monero::Wallet * w = m_pimpl->createWalletFromDevice(path.toStdString(), password.toStdString(), static_cast<Monero::NetworkType>(nettype),
|
||||||
deviceName.toStdString(), restoreHeight, subaddressLookahead.toStdString());
|
deviceName.toStdString(), restoreHeight, subaddressLookahead.toStdString(), 1, &tmpListener);
|
||||||
|
w->setListener(nullptr);
|
||||||
|
|
||||||
m_currentWallet = new Wallet(w);
|
m_currentWallet = new Wallet(w);
|
||||||
|
|
||||||
|
// move wallet to the GUI thread. Otherwise it wont be emitting signals
|
||||||
|
if (m_currentWallet->thread() != qApp->thread()) {
|
||||||
|
m_currentWallet->moveToThread(qApp->thread());
|
||||||
|
}
|
||||||
|
|
||||||
return m_currentWallet;
|
return m_currentWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WalletManager::createWalletFromDeviceAsync(const QString &path, const QString &password, NetworkType::Type nettype,
|
||||||
|
const QString &deviceName, quint64 restoreHeight, const QString &subaddressLookahead)
|
||||||
|
{
|
||||||
|
auto lmbd = [=](){
|
||||||
|
return this->createWalletFromDevice(path, password, nettype, deviceName, restoreHeight, subaddressLookahead);
|
||||||
|
};
|
||||||
|
|
||||||
|
QFuture<Wallet *> future = QtConcurrent::run(lmbd);
|
||||||
|
|
||||||
|
QFutureWatcher<Wallet *> * watcher = new QFutureWatcher<Wallet *>();
|
||||||
|
|
||||||
|
connect(watcher, &QFutureWatcher<Wallet *>::finished,
|
||||||
|
this, [this, watcher]() {
|
||||||
|
QFuture<Wallet *> future = watcher->future();
|
||||||
|
watcher->deleteLater();
|
||||||
|
emit walletCreated(future.result());
|
||||||
|
});
|
||||||
|
watcher->setFuture(future);
|
||||||
|
}
|
||||||
|
|
||||||
QString WalletManager::closeWallet()
|
QString WalletManager::closeWallet()
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
|
@ -419,3 +505,23 @@ WalletManager::WalletManager(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
m_pimpl = Monero::WalletManagerFactory::getWalletManager();
|
m_pimpl = Monero::WalletManagerFactory::getWalletManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WalletManager::onWalletPassphraseNeeded(Monero::Wallet * wallet)
|
||||||
|
{
|
||||||
|
m_mutex_pass.lock();
|
||||||
|
m_passphrase_abort = false;
|
||||||
|
emit this->walletPassphraseNeeded();
|
||||||
|
|
||||||
|
m_cond_pass.wait(&m_mutex_pass);
|
||||||
|
m_mutex_pass.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WalletManager::onPassphraseEntered(const QString &passphrase, bool entry_abort)
|
||||||
|
{
|
||||||
|
m_mutex_pass.lock();
|
||||||
|
m_passphrase = passphrase;
|
||||||
|
m_passphrase_abort = entry_abort;
|
||||||
|
|
||||||
|
m_cond_pass.wakeAll();
|
||||||
|
m_mutex_pass.unlock();
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <wallet/api/wallet2_api.h>
|
#include <wallet/api/wallet2_api.h>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
#include <QMutex>
|
||||||
#include "NetworkType.h"
|
#include "NetworkType.h"
|
||||||
|
|
||||||
class Wallet;
|
class Wallet;
|
||||||
|
@ -70,6 +72,13 @@ public:
|
||||||
const QString &deviceName,
|
const QString &deviceName,
|
||||||
quint64 restoreHeight = 0,
|
quint64 restoreHeight = 0,
|
||||||
const QString &subaddressLookahead = "");
|
const QString &subaddressLookahead = "");
|
||||||
|
|
||||||
|
Q_INVOKABLE void createWalletFromDeviceAsync(const QString &path,
|
||||||
|
const QString &password,
|
||||||
|
NetworkType::Type nettype,
|
||||||
|
const QString &deviceName,
|
||||||
|
quint64 restoreHeight = 0,
|
||||||
|
const QString &subaddressLookahead = "");
|
||||||
/*!
|
/*!
|
||||||
* \brief closeWallet - closes current open wallet and frees memory
|
* \brief closeWallet - closes current open wallet and frees memory
|
||||||
* \return wallet address
|
* \return wallet address
|
||||||
|
@ -152,14 +161,22 @@ public:
|
||||||
// clear/rename wallet cache
|
// clear/rename wallet cache
|
||||||
Q_INVOKABLE bool clearWalletCache(const QString &fileName) const;
|
Q_INVOKABLE bool clearWalletCache(const QString &fileName) const;
|
||||||
|
|
||||||
|
Q_INVOKABLE void onWalletPassphraseNeeded(Monero::Wallet * wallet);
|
||||||
|
Q_INVOKABLE void onPassphraseEntered(const QString &passphrase, bool entry_abort=false);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void walletOpened(Wallet * wallet);
|
void walletOpened(Wallet * wallet);
|
||||||
|
void walletCreated(Wallet * wallet);
|
||||||
|
void walletPassphraseNeeded();
|
||||||
|
void deviceButtonRequest(quint64 buttonCode);
|
||||||
|
void deviceButtonPressed();
|
||||||
void walletClosed(const QString &walletAddress);
|
void walletClosed(const QString &walletAddress);
|
||||||
void checkUpdatesComplete(const QString &result) const;
|
void checkUpdatesComplete(const QString &result) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
private:
|
private:
|
||||||
|
friend class WalletPassphraseListenerImpl;
|
||||||
|
|
||||||
explicit WalletManager(QObject *parent = 0);
|
explicit WalletManager(QObject *parent = 0);
|
||||||
static WalletManager * m_instance;
|
static WalletManager * m_instance;
|
||||||
|
@ -167,6 +184,10 @@ private:
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
QPointer<Wallet> m_currentWallet;
|
QPointer<Wallet> m_currentWallet;
|
||||||
|
|
||||||
|
QWaitCondition m_cond_pass;
|
||||||
|
QMutex m_mutex_pass;
|
||||||
|
QString m_passphrase;
|
||||||
|
bool m_passphrase_abort;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WALLETMANAGER_H
|
#endif // WALLETMANAGER_H
|
||||||
|
|
|
@ -44,6 +44,7 @@ Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
signal useMoneroClicked()
|
signal useMoneroClicked()
|
||||||
|
signal walletCreatedFromDevice(bool success)
|
||||||
|
|
||||||
function restart() {
|
function restart() {
|
||||||
wizardStateView.state = "wizardHome"
|
wizardStateView.state = "wizardHome"
|
||||||
|
@ -65,6 +66,7 @@ Rectangle {
|
||||||
wizardController.walletRestoreMode = 'seed'
|
wizardController.walletRestoreMode = 'seed'
|
||||||
wizardController.walletOptionsSubaddressLookahead = '';
|
wizardController.walletOptionsSubaddressLookahead = '';
|
||||||
wizardController.remoteNodes = {};
|
wizardController.remoteNodes = {};
|
||||||
|
disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
property var m_wallet;
|
property var m_wallet;
|
||||||
|
@ -366,6 +368,28 @@ Rectangle {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function disconnect(){
|
||||||
|
walletManager.walletCreated.disconnect(onWalletCreated);
|
||||||
|
walletManager.walletPassphraseNeeded.disconnect(onWalletPassphraseNeeded);
|
||||||
|
walletManager.deviceButtonRequest.disconnect(onDeviceButtonRequest);
|
||||||
|
walletManager.deviceButtonPressed.disconnect(onDeviceButtonPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function connect(){
|
||||||
|
walletManager.walletCreated.connect(onWalletCreated);
|
||||||
|
walletManager.walletPassphraseNeeded.connect(onWalletPassphraseNeeded);
|
||||||
|
walletManager.deviceButtonRequest.connect(onDeviceButtonRequest);
|
||||||
|
walletManager.deviceButtonPressed.connect(onDeviceButtonPressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deviceAttentionSplash(){
|
||||||
|
appWindow.showProcessingSplash(qsTr("Please proceed to the device..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
function creatingWalletDeviceSplash(){
|
||||||
|
appWindow.showProcessingSplash(qsTr("Creating wallet from device..."));
|
||||||
|
}
|
||||||
|
|
||||||
function createWalletFromDevice() {
|
function createWalletFromDevice() {
|
||||||
// TODO: create wallet in temporary filename and a) move it to the path specified by user after the final
|
// TODO: create wallet in temporary filename and a) move it to the path specified by user after the final
|
||||||
// page submitted or b) delete it when program closed before reaching final page
|
// page submitted or b) delete it when program closed before reaching final page
|
||||||
|
@ -376,30 +400,61 @@ Rectangle {
|
||||||
console.log("deleting wallet")
|
console.log("deleting wallet")
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmp_wallet_filename = oshelper.temporaryFilename();
|
tmpWalletFilename = oshelper.temporaryFilename();
|
||||||
console.log("Creating temporary wallet", tmp_wallet_filename)
|
console.log("Creating temporary wallet", tmpWalletFilename)
|
||||||
var nettype = persistentSettings.nettype;
|
var nettype = persistentSettings.nettype;
|
||||||
var restoreHeight = wizardController.walletOptionsRestoreHeight;
|
var restoreHeight = wizardController.walletOptionsRestoreHeight;
|
||||||
var subaddressLookahead = wizardController.walletOptionsSubaddressLookahead;
|
var subaddressLookahead = wizardController.walletOptionsSubaddressLookahead;
|
||||||
var deviceName = wizardController.walletOptionsDeviceName;
|
var deviceName = wizardController.walletOptionsDeviceName;
|
||||||
|
|
||||||
var wallet = walletManager.createWalletFromDevice(tmp_wallet_filename, "", nettype, deviceName, restoreHeight, subaddressLookahead);
|
connect();
|
||||||
|
walletManager.createWalletFromDeviceAsync(tmpWalletFilename, "", nettype, deviceName, restoreHeight, subaddressLookahead);
|
||||||
|
creatingWalletDeviceSplash();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWalletCreated(wallet) {
|
||||||
|
splash.close()
|
||||||
|
|
||||||
var success = wallet.status === Wallet.Status_Ok;
|
var success = wallet.status === Wallet.Status_Ok;
|
||||||
if (success) {
|
if (success) {
|
||||||
wizardController.m_wallet = wallet;
|
wizardController.m_wallet = wallet;
|
||||||
wizardController.walletOptionsIsRecoveringFromDevice = true;
|
wizardController.walletOptionsIsRecoveringFromDevice = true;
|
||||||
wizardController.tmpWalletFilename = tmp_wallet_filename;
|
|
||||||
if (!wizardController.walletOptionsDeviceIsRestore) {
|
if (!wizardController.walletOptionsDeviceIsRestore) {
|
||||||
// User creates a hardware wallet for the first time. Use a recent block height from API.
|
// User creates a hardware wallet for the first time. Use a recent block height from API.
|
||||||
wizardController.walletOptionsRestoreHeight = wizardController.m_wallet.walletCreationHeight;
|
wizardController.walletOptionsRestoreHeight = wizardController.m_wallet.walletCreationHeight;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(wallet.errorString)
|
console.log(wallet.errorString)
|
||||||
|
wizardController.tmpWalletFilename = '';
|
||||||
appWindow.showStatusMessage(qsTr(wallet.errorString), 5);
|
appWindow.showStatusMessage(qsTr(wallet.errorString), 5);
|
||||||
walletManager.closeWallet();
|
walletManager.closeWallet();
|
||||||
}
|
}
|
||||||
return success;
|
|
||||||
|
disconnect();
|
||||||
|
walletCreatedFromDevice(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onWalletPassphraseNeeded(){
|
||||||
|
splash.close()
|
||||||
|
|
||||||
|
console.log(">>> wallet passphrase needed: ");
|
||||||
|
passphraseDialog.onAcceptedCallback = function() {
|
||||||
|
walletManager.onPassphraseEntered(passphraseDialog.passphrase);
|
||||||
|
creatingWalletDeviceSplash();
|
||||||
|
}
|
||||||
|
passphraseDialog.onRejectedCallback = function() {
|
||||||
|
walletManager.onPassphraseEntered("", true);
|
||||||
|
creatingWalletDeviceSplash();
|
||||||
|
}
|
||||||
|
passphraseDialog.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDeviceButtonRequest(code){
|
||||||
|
deviceAttentionSplash();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDeviceButtonPressed(){
|
||||||
|
creatingWalletDeviceSplash();
|
||||||
}
|
}
|
||||||
|
|
||||||
function openWallet(){
|
function openWallet(){
|
||||||
|
|
|
@ -207,13 +207,9 @@ Rectangle {
|
||||||
}
|
}
|
||||||
wizardController.walletOptionsRestoreHeight = _restoreHeight;
|
wizardController.walletOptionsRestoreHeight = _restoreHeight;
|
||||||
}
|
}
|
||||||
var written = wizardController.createWalletFromDevice();
|
|
||||||
if(written){
|
wizardController.walletCreatedFromDevice.connect(onCreateWalletFromDeviceCompleted);
|
||||||
wizardController.walletOptionsIsRecoveringFromDevice = true;
|
wizardController.createWalletFromDevice();
|
||||||
wizardStateView.state = "wizardCreateWallet2";
|
|
||||||
} else {
|
|
||||||
errorMsg.text = qsTr("Error writing wallet from hardware device. Check application logs.") + translationManager.emptyString;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,4 +226,13 @@ Rectangle {
|
||||||
walletInput.reset();
|
walletInput.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onCreateWalletFromDeviceCompleted(written){
|
||||||
|
if(written){
|
||||||
|
wizardStateView.state = "wizardCreateWallet2";
|
||||||
|
} else {
|
||||||
|
errorMsg.text = qsTr("Error writing wallet from hardware device. Check application logs.") + translationManager.emptyString;
|
||||||
|
}
|
||||||
|
wizardController.walletCreatedFromDevice.disconnect(onCreateWalletFromDeviceCompleted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue