2022-09-30 15:47:18 +02:00
|
|
|
from typing import TYPE_CHECKING
|
2022-09-22 12:43:51 +02:00
|
|
|
|
|
|
|
|
from electrum.i18n import _
|
|
|
|
|
from electrum.plugin import hook
|
2022-09-29 18:05:06 +02:00
|
|
|
from electrum.util import UserFacingException
|
2022-09-22 12:43:51 +02:00
|
|
|
|
|
|
|
|
from electrum.gui.qml.qewallet import QEWallet
|
2023-08-31 08:54:53 +02:00
|
|
|
from .common_qt import TrustedcoinPluginQObject
|
2022-09-22 12:43:51 +02:00
|
|
|
|
2023-08-03 20:43:16 +02:00
|
|
|
from .trustedcoin import TrustedCoinPlugin, TrustedCoinException
|
2022-09-22 12:43:51 +02:00
|
|
|
|
2022-09-30 15:47:18 +02:00
|
|
|
if TYPE_CHECKING:
|
2023-07-11 12:51:37 +02:00
|
|
|
from electrum.gui.qml import ElectrumQmlApplication
|
2022-09-30 15:47:18 +02:00
|
|
|
from electrum.wallet import Abstract_Wallet
|
2023-08-03 20:43:16 +02:00
|
|
|
from electrum.wizard import NewWalletWizard
|
2022-09-30 15:47:18 +02:00
|
|
|
|
2023-07-11 12:51:37 +02:00
|
|
|
|
2022-09-22 12:43:51 +02:00
|
|
|
class Plugin(TrustedCoinPlugin):
|
|
|
|
|
def __init__(self, *args):
|
|
|
|
|
super().__init__(*args)
|
2024-10-21 14:11:18 +02:00
|
|
|
self._app = None
|
|
|
|
|
self.so = None
|
|
|
|
|
self.on_success = None
|
|
|
|
|
self.on_failure = None
|
|
|
|
|
self.tx = None
|
2022-09-22 12:43:51 +02:00
|
|
|
|
|
|
|
|
@hook
|
|
|
|
|
def load_wallet(self, wallet: 'Abstract_Wallet'):
|
|
|
|
|
if not isinstance(wallet, self.wallet_class):
|
|
|
|
|
return
|
|
|
|
|
self.logger.debug(f'plugin enabled for wallet "{str(wallet)}"')
|
|
|
|
|
if wallet.can_sign_without_server():
|
|
|
|
|
self.so._canSignWithoutServer = True
|
|
|
|
|
self.so.canSignWithoutServerChanged.emit()
|
|
|
|
|
|
|
|
|
|
msg = ' '.join([
|
|
|
|
|
_('This wallet was restored from seed, and it contains two master private keys.'),
|
|
|
|
|
_('Therefore, two-factor authentication is disabled.')
|
|
|
|
|
])
|
2022-10-04 21:10:17 +02:00
|
|
|
self.logger.info(msg)
|
2022-09-22 12:43:51 +02:00
|
|
|
self.start_request_thread(wallet)
|
|
|
|
|
|
|
|
|
|
@hook
|
2023-07-11 12:51:37 +02:00
|
|
|
def init_qml(self, app: 'ElectrumQmlApplication'):
|
|
|
|
|
self.logger.debug(f'init_qml hook called, gui={str(type(app))}')
|
|
|
|
|
self._app = app
|
2023-08-03 20:43:16 +02:00
|
|
|
wizard = self._app.daemon.newWalletWizard
|
2023-08-24 15:31:47 +02:00
|
|
|
# important: TrustedcoinPluginQObject needs to be parented, as keeping a ref
|
2022-09-22 12:43:51 +02:00
|
|
|
# in the plugin is not enough to avoid gc
|
2023-08-24 15:31:47 +02:00
|
|
|
# Note: storing the trustedcoin qt helper in the plugin is different from the desktop client,
|
|
|
|
|
# which stores the helper in the wizard object. As the mobile client only shows a single wizard
|
|
|
|
|
# at a time, this is ok for now.
|
|
|
|
|
self.so = TrustedcoinPluginQObject(self, wizard, self._app)
|
2022-09-22 12:43:51 +02:00
|
|
|
# extend wizard
|
2023-08-03 20:43:16 +02:00
|
|
|
self.extend_wizard(wizard)
|
2022-09-22 12:43:51 +02:00
|
|
|
|
2022-11-04 13:35:15 +01:00
|
|
|
# wizard support functions
|
|
|
|
|
|
2023-08-03 20:43:16 +02:00
|
|
|
def extend_wizard(self, wizard: 'NewWalletWizard'):
|
|
|
|
|
super().extend_wizard(wizard)
|
2022-09-22 12:43:51 +02:00
|
|
|
views = {
|
|
|
|
|
'trustedcoin_start': {
|
|
|
|
|
'gui': '../../../../plugins/trustedcoin/qml/Disclaimer',
|
|
|
|
|
},
|
|
|
|
|
'trustedcoin_choose_seed': {
|
|
|
|
|
'gui': '../../../../plugins/trustedcoin/qml/ChooseSeed',
|
|
|
|
|
},
|
|
|
|
|
'trustedcoin_create_seed': {
|
|
|
|
|
'gui': 'WCCreateSeed',
|
|
|
|
|
},
|
|
|
|
|
'trustedcoin_confirm_seed': {
|
|
|
|
|
'gui': 'WCConfirmSeed',
|
|
|
|
|
},
|
|
|
|
|
'trustedcoin_have_seed': {
|
|
|
|
|
'gui': 'WCHaveSeed',
|
2022-10-04 21:10:17 +02:00
|
|
|
},
|
|
|
|
|
'trustedcoin_keep_disable': {
|
|
|
|
|
'gui': '../../../../plugins/trustedcoin/qml/KeepDisable',
|
2022-09-22 12:43:51 +02:00
|
|
|
},
|
2023-12-08 11:56:11 +01:00
|
|
|
'trustedcoin_tos': {
|
2022-09-22 12:43:51 +02:00
|
|
|
'gui': '../../../../plugins/trustedcoin/qml/Terms',
|
|
|
|
|
},
|
2024-10-08 00:04:20 +02:00
|
|
|
'trustedcoin_keystore_unlock': {
|
|
|
|
|
# TODO when QML can import external wallet files
|
|
|
|
|
},
|
2022-09-22 12:43:51 +02:00
|
|
|
'trustedcoin_show_confirm_otp': {
|
|
|
|
|
'gui': '../../../../plugins/trustedcoin/qml/ShowConfirmOTP',
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wizard.navmap_merge(views)
|
|
|
|
|
|
2022-11-04 13:35:15 +01:00
|
|
|
# running wallet functions
|
2022-09-22 12:43:51 +02:00
|
|
|
|
|
|
|
|
def prompt_user_for_otp(self, wallet, tx, on_success, on_failure):
|
|
|
|
|
self.logger.debug('prompt_user_for_otp')
|
|
|
|
|
self.on_success = on_success
|
2022-09-29 18:05:06 +02:00
|
|
|
self.on_failure = on_failure if on_failure else lambda x: self.logger.error(x)
|
2022-09-22 12:43:51 +02:00
|
|
|
self.wallet = wallet
|
|
|
|
|
self.tx = tx
|
2022-09-29 18:05:06 +02:00
|
|
|
qewallet = QEWallet.getInstanceFor(wallet)
|
|
|
|
|
qewallet.request_otp(self.on_otp)
|
2022-09-22 12:43:51 +02:00
|
|
|
|
|
|
|
|
def on_otp(self, otp):
|
2022-11-04 13:35:15 +01:00
|
|
|
if not otp:
|
|
|
|
|
self.on_failure(_('No auth code'))
|
|
|
|
|
return
|
|
|
|
|
|
2022-09-29 18:05:06 +02:00
|
|
|
self.logger.debug(f'on_otp {otp} for tx {repr(self.tx)}')
|
2022-11-04 13:35:15 +01:00
|
|
|
|
2022-09-22 12:43:51 +02:00
|
|
|
try:
|
|
|
|
|
self.wallet.on_otp(self.tx, otp)
|
2022-09-29 18:05:06 +02:00
|
|
|
except UserFacingException as e:
|
|
|
|
|
self.on_failure(_('Invalid one-time password.'))
|
2022-09-22 12:43:51 +02:00
|
|
|
except TrustedCoinException as e:
|
|
|
|
|
if e.status_code == 400: # invalid OTP
|
2022-09-29 18:05:06 +02:00
|
|
|
self.on_failure(_('Invalid one-time password.'))
|
2022-09-22 12:43:51 +02:00
|
|
|
else:
|
2022-11-04 13:35:15 +01:00
|
|
|
self.on_failure(_('Service Error') + ':\n' + str(e))
|
2022-09-22 12:43:51 +02:00
|
|
|
except Exception as e:
|
2024-06-17 16:30:32 +00:00
|
|
|
self.on_failure(_('Error') + ':\n' + str(e))
|
2022-09-22 12:43:51 +02:00
|
|
|
else:
|
2022-09-29 18:05:06 +02:00
|
|
|
self.on_success(self.tx)
|
2022-11-04 13:35:15 +01:00
|
|
|
|
|
|
|
|
def billing_info_retrieved(self, wallet):
|
|
|
|
|
self.logger.info('billing_info_retrieved')
|
|
|
|
|
qewallet = QEWallet.getInstanceFor(wallet)
|
|
|
|
|
qewallet.billingInfoChanged.emit()
|
|
|
|
|
self.so.updateBillingInfo(wallet)
|