Browse Source

qml: show 2FA status and billing info in WalletDetails, expose billing schedule setting in config

patch-4
Sander van Grieken 2 years ago
parent
commit
0c9d4abb82
  1. 75
      electrum/gui/qml/components/WalletDetails.qml
  2. 11
      electrum/gui/qml/qeconfig.py
  3. 9
      electrum/gui/qml/qewallet.py
  4. 41
      electrum/plugins/trustedcoin/qml.py
  5. 5
      electrum/plugins/trustedcoin/trustedcoin.py

75
electrum/gui/qml/components/WalletDetails.qml

@ -163,13 +163,86 @@ Pane {
}
}
GridLayout {
visible: Daemon.currentWallet && Daemon.currentWallet.walletType == '2fa'
Layout.preferredWidth: parent.width
columns: 2
Label {
text: qsTr('2FA')
color: Material.accentColor
}
Label {
Layout.fillWidth: true
text: Daemon.currentWallet.canSignWithoutServer
? qsTr('disabled (can sign without server')
: qsTr('enabled')
}
Label {
visible: !Daemon.currentWallet.canSignWithoutServer
text: qsTr('Remaining TX')
color: Material.accentColor
}
Label {
Layout.fillWidth: true
visible: !Daemon.currentWallet.canSignWithoutServer
text: 'tx_remaining' in Daemon.currentWallet.billingInfo
? Daemon.currentWallet.billingInfo['tx_remaining']
: qsTr('unknown')
}
Label {
Layout.columnSpan: 2
visible: !Daemon.currentWallet.canSignWithoutServer
text: qsTr('Billing')
color: Material.accentColor
}
ColumnLayout {
Layout.columnSpan: 2
Layout.leftMargin: constants.paddingMedium
spacing: 0
ButtonGroup {
id: billinggroup
onCheckedButtonChanged: {
Config.trustedcoinPrepay = checkedButton.value
}
}
Repeater {
model: AppController.plugin('trustedcoin').billingModel
delegate: RowLayout {
RadioButton {
ButtonGroup.group: billinggroup
property string value: modelData.value
text: modelData.text
checked: modelData.value == Config.trustedcoinPrepay
}
Label {
text: Config.formatSats(modelData.sats_per_tx)
font.family: FixedFont
}
Label {
text: Config.baseUnit + '/tx'
color: Material.accentColor
}
}
}
}
}
GridLayout {
id: detailsLayout
visible: Daemon.currentWallet
Layout.preferredWidth: parent.width
columns: 2
Label {
text: qsTr('Derivation prefix')
visible: Daemon.currentWallet.isDeterministic

11
electrum/gui/qml/qeconfig.py

@ -166,6 +166,17 @@ class QEConfig(AuthMixin, QObject):
self.config.set_key('use_recoverable_channels', useRecoverableChannels)
self.useRecoverableChannelsChanged.emit()
trustedcoinPrepayChanged = pyqtSignal()
@pyqtProperty(int, notify=trustedcoinPrepayChanged)
def trustedcoinPrepay(self):
return self.config.get('trustedcoin_prepay', 20)
@trustedcoinPrepay.setter
def trustedcoinPrepay(self, num_prepay):
if num_prepay != self.config.get('trustedcoin_prepay', 20):
self.config.set_key('trustedcoin_prepay', num_prepay)
self.trustedcoinPrepayChanged.emit()
@pyqtSlot('qint64', result=str)
@pyqtSlot('qint64', bool, result=str)
@pyqtSlot(QEAmount, result=str)

9
electrum/gui/qml/qewallet.py

@ -301,6 +301,11 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
def isLightning(self):
return bool(self.wallet.lnworker)
billingInfoChanged = pyqtSignal()
@pyqtProperty('QVariantMap', notify=billingInfoChanged)
def billingInfo(self):
return {} if self.wallet.wallet_type != '2fa' else self.wallet.billing_info
@pyqtProperty(bool, notify=dataChanged)
def canHaveLightning(self):
return self.wallet.can_have_lightning()
@ -349,6 +354,10 @@ class QEWallet(AuthMixin, QObject, QtEventListener):
def masterPubkey(self):
return self.wallet.get_master_public_key()
@pyqtProperty(bool, notify=dataChanged)
def canSignWithoutServer(self):
return self.wallet.can_sign_without_server() if self.wallet.wallet_type == '2fa' else True
balanceChanged = pyqtSignal()
@pyqtProperty(QEAmount, notify=balanceChanged)

41
electrum/plugins/trustedcoin/qml.py

@ -39,6 +39,8 @@ class Plugin(TrustedCoinPlugin):
_otpSecret = ''
shortIdChanged = pyqtSignal()
_shortId = ''
billingModelChanged = pyqtSignal()
_billingModel = []
_remoteKeyState = ''
remoteKeyStateChanged = pyqtSignal()
@ -91,6 +93,27 @@ class Plugin(TrustedCoinPlugin):
self._remoteKeyState = new_state
self.remoteKeyStateChanged.emit()
@pyqtProperty('QVariantList', notify=billingModelChanged)
def billingModel(self):
return self._billingModel
def updateBillingInfo(self, wallet):
billingModel = []
price_per_tx = wallet.price_per_tx
for k, v in sorted(price_per_tx.items()):
if k == 1:
continue
item = {
'text': 'Pay every %d transactions' % k,
'value': k,
'sats_per_tx': v/k
}
billingModel.append(item)
self._billingModel = billingModel
self.billingModelChanged.emit()
@pyqtSlot()
def fetchTermsAndConditions(self):
def fetch_task():
@ -274,6 +297,8 @@ class Plugin(TrustedCoinPlugin):
# extend wizard
self.extend_wizard()
# wizard support functions
def extend_wizard(self):
wizard = self._app.daemon.newWalletWizard
self.logger.debug(repr(wizard))
@ -367,7 +392,7 @@ class Plugin(TrustedCoinPlugin):
wizard_data['x3/'] = k3.dump()
# regular wallet prompt functions
# running wallet functions
def prompt_user_for_otp(self, wallet, tx, on_success, on_failure):
self.logger.debug('prompt_user_for_otp')
@ -379,7 +404,12 @@ class Plugin(TrustedCoinPlugin):
qewallet.request_otp(self.on_otp)
def on_otp(self, otp):
if not otp:
self.on_failure(_('No auth code'))
return
self.logger.debug(f'on_otp {otp} for tx {repr(self.tx)}')
try:
self.wallet.on_otp(self.tx, otp)
except UserFacingException as e:
@ -388,8 +418,15 @@ class Plugin(TrustedCoinPlugin):
if e.status_code == 400: # invalid OTP
self.on_failure(_('Invalid one-time password.'))
else:
self.on_failure(_('Error') + ':\n' + str(e))
self.on_failure(_('Service Error') + ':\n' + str(e))
except Exception as e:
self.on_failure(_('Error') + ':\n' + str(e))
else:
self.on_success(self.tx)
def billing_info_retrieved(self, wallet):
self.logger.info('billing_info_retrieved')
qewallet = QEWallet.getInstanceFor(wallet)
qewallet.billingInfoChanged.emit()
self.so.updateBillingInfo(wallet)

5
electrum/plugins/trustedcoin/trustedcoin.py

@ -519,8 +519,13 @@ class TrustedCoinPlugin(BasePlugin):
wallet.billing_info = billing_info
wallet.price_per_tx = dict(billing_info['price_per_tx'])
wallet.price_per_tx.pop(1, None)
self.billing_info_retrieved(wallet)
return True
def billing_info_retrieved(self, wallet):
# override to handle billing info when it becomes available
pass
def start_request_thread(self, wallet):
from threading import Thread
if self.requesting is False:

Loading…
Cancel
Save