Browse Source

wip otp on pay

patch-4
Sander van Grieken 2 years ago
parent
commit
20c95b26ea
  1. 53
      electrum/gui/qml/components/OtpDialog.qml
  2. 23
      electrum/gui/qml/components/WalletMainView.qml
  3. 25
      electrum/gui/qml/qewallet.py
  4. 27
      electrum/plugins/trustedcoin/qml.py

53
electrum/gui/qml/components/OtpDialog.qml

@ -0,0 +1,53 @@
import QtQuick 2.6
import QtQuick.Layouts 1.0
import QtQuick.Controls 2.14
import QtQuick.Controls.Material 2.0
import org.electrum 1.0
import "controls"
ElDialog {
id: dialog
title: qsTr('OTP auth')
property string otpauth
// property var lnurlData
// property InvoiceParser invoiceParser
// property alias lnurlData: dialog.invoiceParser.lnurlData
standardButtons: Dialog.Cancel
modal: true
parent: Overlay.overlay
Overlay.modal: Rectangle {
color: "#aa000000"
}
GridLayout {
columns: 2
implicitWidth: parent.width
Label {
text: qsTr('code')
}
TextField {
id: otpEdit
}
Button {
Layout.columnSpan: 2
Layout.alignment: Qt.AlignHCenter
text: qsTr('Proceed')
onClicked: {
// dialog.close()
otpauth = otpEdit.text
dialog.accept()
}
}
}
}

23
electrum/gui/qml/components/WalletMainView.qml

@ -256,6 +256,19 @@ Item {
} }
} }
Connections {
target: Daemon.currentWallet
function onOtpRequested() {
console.log('OTP requested')
var dialog = otpDialog.createObject(mainView)
dialog.accepted.connect(function() {
console.log('accepted ' + dialog.otpauth)
Daemon.currentWallet.finish_otp(dialog.otpauth)
})
dialog.open()
}
}
Component { Component {
id: sendDialog id: sendDialog
SendDialog { SendDialog {
@ -304,5 +317,15 @@ Item {
onClosed: destroy() onClosed: destroy()
} }
} }
Component {
id: otpDialog
OtpDialog {
width: parent.width * 0.9
anchors.centerIn: parent
onClosed: destroy()
}
}
} }

25
electrum/gui/qml/qewallet.py

@ -3,6 +3,7 @@ import queue
import threading import threading
import time import time
from typing import Optional, TYPE_CHECKING from typing import Optional, TYPE_CHECKING
from functools import partial
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject, QTimer
@ -13,6 +14,7 @@ from electrum.logging import get_logger
from electrum.network import TxBroadcastError, BestEffortRequestFailed from electrum.network import TxBroadcastError, BestEffortRequestFailed
from electrum.transaction import PartialTxOutput from electrum.transaction import PartialTxOutput
from electrum.util import (parse_max_spend, InvalidPassword, event_listener) from electrum.util import (parse_max_spend, InvalidPassword, event_listener)
from electrum.plugin import run_hook
from .auth import AuthMixin, auth_protect from .auth import AuthMixin, auth_protect
from .qeaddresslistmodel import QEAddressListModel from .qeaddresslistmodel import QEAddressListModel
@ -63,6 +65,7 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
#broadcastSucceeded = pyqtSignal([str], arguments=['txid']) #broadcastSucceeded = pyqtSignal([str], arguments=['txid'])
broadcastFailed = pyqtSignal([str,str,str], arguments=['txid','code','reason']) broadcastFailed = pyqtSignal([str,str,str], arguments=['txid','code','reason'])
labelsUpdated = pyqtSignal() labelsUpdated = pyqtSignal()
otpRequested = pyqtSignal()
_network_signal = pyqtSignal(str, object) _network_signal = pyqtSignal(str, object)
@ -423,6 +426,16 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
@auth_protect @auth_protect
def sign(self, tx, *, broadcast: bool = False): def sign(self, tx, *, broadcast: bool = False):
sign_hook = run_hook('tc_sign_wrapper', self.wallet, tx, partial(self.on_sign_complete, broadcast), None)
if sign_hook:
self.do_sign(tx, False)
self._logger.debug('plugin needs to sign tx too')
sign_hook(tx)
return
self.do_sign(tx, broadcast)
def do_sign(self, tx, broadcast):
tx = self.wallet.sign_transaction(tx, self.password) tx = self.wallet.sign_transaction(tx, self.password)
if tx is None: if tx is None:
@ -441,6 +454,18 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
if broadcast: if broadcast:
self.broadcast(tx) self.broadcast(tx)
def on_sign_complete(self, broadcast, tx):
if broadcast:
self.broadcast(tx)
def request_otp(self, on_submit):
self._otp_on_submit = on_submit
self.otpRequested.emit()
@pyqtSlot(str)
def finish_otp(self, otp):
self._otp_on_submit(otp)
def broadcast(self, tx): def broadcast(self, tx):
assert tx.is_complete() assert tx.is_complete()

27
electrum/plugins/trustedcoin/qml.py

@ -6,6 +6,7 @@ from PyQt5.QtCore import QObject, pyqtSignal, pyqtProperty, pyqtSlot
from electrum.i18n import _ from electrum.i18n import _
from electrum.plugin import hook from electrum.plugin import hook
from electrum.bip32 import xpub_type from electrum.bip32 import xpub_type
from electrum.util import UserFacingException
from electrum import keystore from electrum import keystore
from electrum.gui.qml.qewallet import QEWallet from electrum.gui.qml.qewallet import QEWallet
@ -18,8 +19,6 @@ from .trustedcoin import (TrustedCoinPlugin, server, ErrorConnectingServer,
class Plugin(TrustedCoinPlugin): class Plugin(TrustedCoinPlugin):
class QSignalObject(PluginQObject): class QSignalObject(PluginQObject):
requestView = pyqtSignal([str], arguments=['component'])
canSignWithoutServerChanged = pyqtSignal() canSignWithoutServerChanged = pyqtSignal()
_canSignWithoutServer = False _canSignWithoutServer = False
termsAndConditionsChanged = pyqtSignal() termsAndConditionsChanged = pyqtSignal()
@ -37,6 +36,8 @@ class Plugin(TrustedCoinPlugin):
shortIdChanged = pyqtSignal() shortIdChanged = pyqtSignal()
_shortId = '' _shortId = ''
requestOtp = pyqtSignal()
def __init__(self, plugin, parent): def __init__(self, plugin, parent):
super().__init__(plugin, parent) super().__init__(plugin, parent)
@ -307,26 +308,24 @@ class Plugin(TrustedCoinPlugin):
def prompt_user_for_otp(self, wallet, tx, on_success, on_failure): def prompt_user_for_otp(self, wallet, tx, on_success, on_failure):
self.logger.debug('prompt_user_for_otp') self.logger.debug('prompt_user_for_otp')
self.on_success = on_success self.on_success = on_success
self.on_failure = on_failure self.on_failure = on_failure if on_failure else lambda x: self.logger.error(x)
self.wallet = wallet self.wallet = wallet
self.tx = tx self.tx = tx
self.so.requestView.emit('../../../../plugins/trustedcoin/qml/OTP.qml') qewallet = QEWallet.getInstanceFor(wallet)
qewallet.request_otp(self.on_otp)
def on_otp(self, otp): def on_otp(self, otp):
self.logger.debug(f'on_otp {otp} for tx {repr(self.tx)}')
try: try:
self.wallet.on_otp(self.tx, otp) self.wallet.on_otp(self.tx, otp)
except UserFacingException as e:
self.on_failure(_('Invalid one-time password.'))
except TrustedCoinException as e: except TrustedCoinException as e:
if e.status_code == 400: # invalid OTP if e.status_code == 400: # invalid OTP
# Clock.schedule_once(lambda dt: self.on_failure(_('Invalid one-time password.'))
self.on_failure(_('Invalid one-time password.'))
# )
else: else:
# Clock.schedule_once(lambda dt, bound_e=e: self.on_failure(_('Error') + ':\n' + str(e))
self.on_failure(_('Error') + ':\n' + str(bound_e))
# )
except Exception as e: except Exception as e:
# Clock.schedule_once(lambda dt, bound_e=e: self.on_failure(_('Error') + ':\n' + str(e))
self.on_failure(_('Error') + ':\n' + str(bound_e))
# )
else: else:
self.on_success(tx) self.on_success(self.tx)

Loading…
Cancel
Save