You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

154 lines
5.5 KiB

import os
from typing import TYPE_CHECKING
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject
from electrum.logging import get_logger
from electrum import mnemonic
from electrum.wizard import NewWalletWizard, ServerConnectWizard
if TYPE_CHECKING:
from electrum.gui.qml.qedaemon import QEDaemon
from electrum.plugin import Plugins
class QEAbstractWizard(QObject):
""" Concrete subclasses of QEAbstractWizard must also inherit from a concrete AbstractWizard subclass.
QEAbstractWizard forms the base for all QML GUI based wizards, while AbstractWizard defines
the base for non-gui wizard flow navigation functionality.
"""
_logger = get_logger(__name__)
def __init__(self, parent=None):
QObject.__init__(self, parent)
@pyqtSlot(result=str)
def startWizard(self):
self.start()
return self._current.view
@pyqtSlot(str, result=str)
def viewToComponent(self, view):
return self.navmap[view]['gui'] + '.qml'
@pyqtSlot('QJSValue', result='QVariant')
def submit(self, wizard_data):
wdata = wizard_data.toVariant()
view = self.resolve_next(self._current.view, wdata)
return { 'view': view.view, 'wizard_data': view.wizard_data }
@pyqtSlot(result='QVariant')
def prev(self):
viewstate = self.resolve_prev()
return viewstate.wizard_data
@pyqtSlot('QJSValue', result=bool)
def isLast(self, wizard_data):
wdata = wizard_data.toVariant()
return self.is_last_view(self._current.view, wdata)
class QENewWalletWizard(NewWalletWizard, QEAbstractWizard):
createError = pyqtSignal([str], arguments=["error"])
createSuccess = pyqtSignal()
def __init__(self, daemon: 'QEDaemon', plugins: 'Plugins', parent=None):
NewWalletWizard.__init__(self, daemon.daemon, plugins)
QEAbstractWizard.__init__(self, parent)
self._qedaemon = daemon
self._path = None
self._password = None
# attach view names and accept handlers
self.navmap_merge({
'wallet_name': {'gui': 'WCWalletName'},
'wallet_type': {'gui': 'WCWalletType'},
'keystore_type': {'gui': 'WCKeystoreType'},
'create_seed': {'gui': 'WCCreateSeed'},
'confirm_seed': {'gui': 'WCConfirmSeed'},
'have_seed': {'gui': 'WCHaveSeed'},
'script_and_derivation': {'gui': 'WCScriptAndDerivation'},
'have_master_key': {'gui': 'WCHaveMasterKey'},
'multisig': {'gui': 'WCMultisig'},
'multisig_cosigner_keystore': {'gui': 'WCCosignerKeystore'},
'multisig_cosigner_key': {'gui': 'WCHaveMasterKey'},
'multisig_cosigner_seed': {'gui': 'WCHaveSeed'},
'multisig_cosigner_script_and_derivation': {'gui': 'WCScriptAndDerivation'},
'imported': {'gui': 'WCImport'},
'wallet_password': {'gui': 'WCWalletPassword'}
})
pathChanged = pyqtSignal()
@pyqtProperty(str, notify=pathChanged)
def path(self):
return self._path
@path.setter
def path(self, path):
self._path = path
self.pathChanged.emit()
def is_single_password(self):
return self._qedaemon.singlePasswordEnabled
@pyqtSlot('QJSValue', result=bool)
def hasDuplicateMasterKeys(self, js_data):
self._logger.info('Checking for duplicate masterkeys')
data = js_data.toVariant()
return self.has_duplicate_masterkeys(data)
@pyqtSlot('QJSValue', result=bool)
def hasHeterogeneousMasterKeys(self, js_data):
self._logger.info('Checking for heterogeneous masterkeys')
data = js_data.toVariant()
return self.has_heterogeneous_masterkeys(data)
@pyqtSlot(str, str, result=bool)
def isMatchingSeed(self, seed, seed_again):
return mnemonic.is_matching_seed(seed=seed, seed_again=seed_again)
@pyqtSlot(str, str, str, result='QVariantMap')
def verifySeed(self, seed, seed_variant, wallet_type='standard'):
seed_valid, seed_type, validation_message = self.validate_seed(seed, seed_variant, wallet_type)
return {
'valid': seed_valid,
'type': seed_type,
'message': validation_message
}
@pyqtSlot('QJSValue', bool, str)
def createStorage(self, js_data, single_password_enabled, single_password):
self._logger.info('Creating wallet from wizard data')
data = js_data.toVariant()
if single_password_enabled and single_password:
data['encrypt'] = True
data['password'] = single_password
path = os.path.join(os.path.dirname(self._qedaemon.daemon.config.get_wallet_path()), data['wallet_name'])
try:
self.create_storage(path, data)
# minimally populate self after create
self._password = data['password']
self.path = path
self.createSuccess.emit()
except Exception as e:
self._logger.exception(f"createStorage errored: {e!r}")
self.createError.emit(str(e))
class QEServerConnectWizard(ServerConnectWizard, QEAbstractWizard):
def __init__(self, daemon: 'QEDaemon', parent=None):
ServerConnectWizard.__init__(self, daemon.daemon)
QEAbstractWizard.__init__(self, parent)
# attach view names
self.navmap_merge({
'autoconnect': {'gui': 'WCAutoConnect'},
'proxy_ask': {'gui': 'WCProxyAsk'},
'proxy_config': {'gui': 'WCProxyConfig'},
'server_config': {'gui': 'WCServerConfig'},
})