diff --git a/electrum/plugins/trustedcoin/cmdline.py b/electrum/plugins/trustedcoin/cmdline.py index 30b2f3501..2ad281aae 100644 --- a/electrum/plugins/trustedcoin/cmdline.py +++ b/electrum/plugins/trustedcoin/cmdline.py @@ -24,7 +24,6 @@ # SOFTWARE. from electrum.i18n import _ -from electrum.plugin import hook from .trustedcoin import TrustedCoinPlugin diff --git a/electrum/plugins/trustedcoin/common_qt.py b/electrum/plugins/trustedcoin/common_qt.py index 5b4ef65c5..c39fe6e44 100644 --- a/electrum/plugins/trustedcoin/common_qt.py +++ b/electrum/plugins/trustedcoin/common_qt.py @@ -1,7 +1,6 @@ import threading import socket import base64 -import sys from typing import TYPE_CHECKING from PyQt6.QtCore import pyqtSignal, pyqtProperty, pyqtSlot @@ -83,7 +82,7 @@ class TrustedcoinPluginQObject(PluginQObject): return self._billingModel def updateBillingInfo(self, wallet): - billingModel = [] + billing_model = [] price_per_tx = wallet.price_per_tx for k, v in sorted(price_per_tx.items()): @@ -94,9 +93,9 @@ class TrustedcoinPluginQObject(PluginQObject): 'value': k, 'sats_per_tx': v / k } - billingModel.append(item) + billing_model.append(item) - self._billingModel = billingModel + self._billingModel = billing_model self.billingModelChanged.emit() @pyqtSlot() diff --git a/electrum/plugins/trustedcoin/qml.py b/electrum/plugins/trustedcoin/qml.py index 5bc6b330c..1d970ccb3 100644 --- a/electrum/plugins/trustedcoin/qml.py +++ b/electrum/plugins/trustedcoin/qml.py @@ -18,6 +18,11 @@ if TYPE_CHECKING: class Plugin(TrustedCoinPlugin): def __init__(self, *args): super().__init__(*args) + self._app = None + self.so = None + self.on_success = None + self.on_failure = None + self.tx = None @hook def load_wallet(self, wallet: 'Abstract_Wallet'): diff --git a/electrum/plugins/trustedcoin/qt.py b/electrum/plugins/trustedcoin/qt.py index 703161904..17b0d7241 100644 --- a/electrum/plugins/trustedcoin/qt.py +++ b/electrum/plugins/trustedcoin/qt.py @@ -24,23 +24,22 @@ # SOFTWARE. from functools import partial -import threading import os from typing import TYPE_CHECKING from PyQt6.QtGui import QPixmap, QMovie, QColor from PyQt6.QtCore import QObject, pyqtSignal, QSize, Qt from PyQt6.QtWidgets import (QTextEdit, QVBoxLayout, QLabel, QGridLayout, QHBoxLayout, - QRadioButton, QCheckBox, QLineEdit, QPushButton, QWidget) + QRadioButton, QCheckBox, QPushButton, QWidget) from electrum.i18n import _ from electrum.plugin import hook -from electrum.util import is_valid_email, InvalidPassword +from electrum.util import InvalidPassword from electrum.logging import Logger, get_logger from electrum import keystore -from electrum.gui.qt.util import (read_QIcon, WindowModalDialog, WaitingDialog, OkButton, - CancelButton, Buttons, icon_path, internal_plugin_icon_path, WWLabel, CloseButton, ColorScheme, +from electrum.gui.qt.util import (WindowModalDialog, WaitingDialog, OkButton, CancelButton, Buttons, icon_path, + internal_plugin_icon_path, WWLabel, CloseButton, ColorScheme, ChoiceWidget, PasswordLineEdit, char_width_in_lineedit) from electrum.gui.qt.qrcodewidget import QRCodeWidget from electrum.gui.qt.amountedit import AmountEdit @@ -50,7 +49,7 @@ from electrum.gui.qt.wizard.wizard import WizardComponent from electrum.gui.qt.util import read_QIcon_from_bytes from .common_qt import TrustedcoinPluginQObject -from .trustedcoin import TrustedCoinPlugin, server, DISCLAIMER +from .trustedcoin import TrustedCoinPlugin, DISCLAIMER if TYPE_CHECKING: from electrum.gui.qt.main_window import ElectrumWindow @@ -116,7 +115,7 @@ class Plugin(TrustedCoinPlugin): def auth_dialog(self, window): d = WindowModalDialog(window, _("Authorization")) vbox = QVBoxLayout(d) - pw = AmountEdit(None, is_int = True) + pw = AmountEdit(None, is_int=True) msg = _('Please enter your Google Authenticator code') vbox.addWidget(QLabel(msg)) grid = QGridLayout() @@ -139,6 +138,7 @@ class Plugin(TrustedCoinPlugin): def waiting_dialog_for_billing_info(self, window, *, on_finished=None): def task(): return self.request_billing_info(window.wallet, suppress_connection_error=False) + def on_error(exc_info): e = exc_info[1] window.show_error("{header}\n{exc}\n\n{tor}" @@ -216,6 +216,7 @@ class Plugin(TrustedCoinPlugin): grid.addWidget(QLabel(window.format_amount(v/k) + ' ' + window.base_unit() + "/tx"), i, 1) b = QRadioButton() b.setChecked(k == n_prepay) + def on_click(b, k): self.config.PLUGIN_TRUSTEDCOIN_NUM_PREPAY = k b.clicked.connect(partial(on_click, k=k)) @@ -374,12 +375,11 @@ class WCTerms(WizardComponent): def __init__(self, parent, wizard): WizardComponent.__init__(self, parent, wizard, title=_('Terms and conditions')) self._has_tos = False - - def on_ready(self): self.tos_e = TOS() self.tos_e.setReadOnly(True) self.layout().addWidget(self.tos_e) + def on_ready(self): self.fetch_terms_and_conditions() def fetch_terms_and_conditions(self): @@ -580,6 +580,7 @@ class WCKeepDisable(WizardComponent): class WCContinueOnline(WizardComponent): def __init__(self, parent, wizard): WizardComponent.__init__(self, parent, wizard, title=_('Continue Online')) + self.cb_online = QCheckBox(_('Go online to complete wallet creation')) def on_ready(self): path = os.path.join(os.path.dirname(self.wizard._daemon.config.get_wallet_path()), self.wizard_data['wallet_name']) @@ -596,7 +597,6 @@ class WCContinueOnline(WizardComponent): self.layout().addWidget(WWLabel('\n\n'.join(msg))) self.layout().addStretch(1) - self.cb_online = QCheckBox(_('Go online to complete wallet creation')) self.cb_online.setChecked(True) self.cb_online.stateChanged.connect(self.on_updated) # self.cb_online.setToolTip(_("Check this box to request a new secret. You will need to retype your seed.")) @@ -613,8 +613,6 @@ class WCContinueOnline(WizardComponent): class WCKeystorePassword(WizardComponent): def __init__(self, parent, wizard): WizardComponent.__init__(self, parent, wizard, title=_('Unlock Keystore')) - - def on_ready(self): self.layout().addStretch(1) hbox2 = QHBoxLayout() @@ -627,11 +625,11 @@ class WCKeystorePassword(WizardComponent): hbox2.addWidget(self.pw_e) hbox2.addStretch(1) self.layout().addLayout(hbox2) - self.layout().addStretch(1) - self._valid = False + self.ks = None + def on_ready(self): self.ks = self.wizard_data['xprv1'] def on_text(self): diff --git a/electrum/plugins/trustedcoin/trustedcoin.py b/electrum/plugins/trustedcoin/trustedcoin.py index b4060f908..7925b400c 100644 --- a/electrum/plugins/trustedcoin/trustedcoin.py +++ b/electrum/plugins/trustedcoin/trustedcoin.py @@ -225,7 +225,7 @@ class TrustedCoinCosignerClient(Logger): def reset_auth(self, id, challenge, signatures): """ Reset Google Auth secret """ - payload = {'challenge':challenge, 'signatures':signatures} + payload = {'challenge': challenge, 'signatures': signatures} return self.send_request('post', 'cosigner/%s/otp_secret' % quote(id), payload) def sign(self, id, transaction, otp): @@ -420,6 +420,15 @@ def make_billing_address(wallet, num, addr_type): raise ValueError(f'unexpected billing type: {addr_type}') +def finish_requesting(func): + def f(self, *args, **kwargs): + try: + return func(self, *args, **kwargs) + finally: + self.requesting = False + return f + + class TrustedCoinPlugin(BasePlugin): wallet_class = Wallet_2fa disclaimer_msg = DISCLAIMER @@ -459,20 +468,12 @@ class TrustedCoinPlugin(BasePlugin): @hook def get_tx_extra_fee(self, wallet, tx: Transaction): - if type(wallet) != Wallet_2fa: + if type(wallet) is not Wallet_2fa: return for o in tx.outputs(): if wallet.is_billing_address(o.address): return o.address, o.value - def finish_requesting(func): - def f(self, *args, **kwargs): - try: - return func(self, *args, **kwargs) - finally: - self.requesting = False - return f - @finish_requesting def request_billing_info(self, wallet: 'Wallet_2fa', *, suppress_connection_error=True): if wallet.can_sign_without_server(): @@ -525,7 +526,7 @@ class TrustedCoinPlugin(BasePlugin): window.wallet.is_billing = False @classmethod - def get_xkeys(self, seed, t, passphrase, derivation): + def get_xkeys(cls, seed, t, passphrase, derivation): assert is_any_2fa_seed_type(t) xtype = 'standard' if t == '2fa' else 'p2wsh' bip32_seed = Mnemonic.mnemonic_to_seed(seed, passphrase=passphrase) @@ -534,7 +535,7 @@ class TrustedCoinPlugin(BasePlugin): return child_node.to_xprv(), child_node.to_xpub() @classmethod - def xkeys_from_seed(self, seed, passphrase): + def xkeys_from_seed(cls, seed, passphrase): t = calc_seed_type(seed) if not is_any_2fa_seed_type(t): raise Exception(f'unexpected seed type: {t!r}') @@ -547,16 +548,16 @@ class TrustedCoinPlugin(BasePlugin): # the probability of it being < 20 words is about 2^(-(256+12-19*11)) = 2^(-59) if passphrase: raise Exception("old '2fa'-type electrum seed cannot have passphrase") - xprv1, xpub1 = self.get_xkeys(' '.join(words[0:12]), t, '', "m/") - xprv2, xpub2 = self.get_xkeys(' '.join(words[12:]), t, '', "m/") + xprv1, xpub1 = cls.get_xkeys(' '.join(words[0:12]), t, '', "m/") + xprv2, xpub2 = cls.get_xkeys(' '.join(words[12:]), t, '', "m/") elif n == 12: # new scheme - xprv1, xpub1 = self.get_xkeys(seed, t, passphrase, "m/0'/") - xprv2, xpub2 = self.get_xkeys(seed, t, passphrase, "m/1'/") + xprv1, xpub1 = cls.get_xkeys(seed, t, passphrase, "m/0'/") + xprv2, xpub2 = cls.get_xkeys(seed, t, passphrase, "m/1'/") else: raise Exception(f'unrecognized seed length for "2fa" seed: {n}') elif t == '2fa_segwit': - xprv1, xpub1 = self.get_xkeys(seed, t, passphrase, "m/0'/") - xprv2, xpub2 = self.get_xkeys(seed, t, passphrase, "m/1'/") + xprv1, xpub1 = cls.get_xkeys(seed, t, passphrase, "m/0'/") + xprv2, xpub2 = cls.get_xkeys(seed, t, passphrase, "m/1'/") else: raise Exception(f'unexpected seed type: {t!r}') return xprv1, xpub1, xprv2, xpub2