wizard: scan hardware devices directly
This commit is contained in:
@@ -338,13 +338,13 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
|
|||||||
self.show_message(msg)
|
self.show_message(msg)
|
||||||
|
|
||||||
@wizard_dialog
|
@wizard_dialog
|
||||||
def confirm_dialog(self, msg, run_next):
|
def confirm_dialog(self, title, message, run_next):
|
||||||
self.confirm(msg)
|
self.confirm(message, title)
|
||||||
|
|
||||||
def confirm(self, msg):
|
def confirm(self, message, title):
|
||||||
vbox = QVBoxLayout()
|
vbox = QVBoxLayout()
|
||||||
vbox.addWidget(WWLabel(msg))
|
vbox.addWidget(WWLabel(message))
|
||||||
self.set_main_layout(vbox)
|
self.set_main_layout(vbox, title)
|
||||||
|
|
||||||
@wizard_dialog
|
@wizard_dialog
|
||||||
def action_dialog(self, action, run_next):
|
def action_dialog(self, action, run_next):
|
||||||
@@ -379,6 +379,13 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard):
|
|||||||
self.set_main_layout(vbox, '')
|
self.set_main_layout(vbox, '')
|
||||||
return clayout.selected_index()
|
return clayout.selected_index()
|
||||||
|
|
||||||
|
def get_passphrase(self, msg, confirm):
|
||||||
|
phrase = self.pw_layout(msg, PW_PASSPHRASE)
|
||||||
|
if phrase is None:
|
||||||
|
raise UserCancelled
|
||||||
|
return phrase
|
||||||
|
|
||||||
|
|
||||||
@wizard_dialog
|
@wizard_dialog
|
||||||
def account_id_dialog(self, run_next):
|
def account_id_dialog(self, run_next):
|
||||||
message = '\n'.join([
|
message = '\n'.join([
|
||||||
|
|||||||
@@ -117,12 +117,12 @@ class BaseWizard(object):
|
|||||||
('create_seed', _('Create a new seed')),
|
('create_seed', _('Create a new seed')),
|
||||||
('restore_seed', _('I already have a seed')),
|
('restore_seed', _('I already have a seed')),
|
||||||
('restore_from_key', _('Import keys')),
|
('restore_from_key', _('Import keys')),
|
||||||
('choose_hw', _('Use hardware device')),
|
('choose_device', _('Use hardware device')),
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
choices = [
|
choices = [
|
||||||
('restore_from_key', _('Import cosigner key')),
|
('restore_from_key', _('Import cosigner key')),
|
||||||
('choose_hw', _('Cosign with hardware device')),
|
('choose_device', _('Cosign with hardware device')),
|
||||||
]
|
]
|
||||||
|
|
||||||
self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run)
|
self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run)
|
||||||
@@ -165,46 +165,59 @@ class BaseWizard(object):
|
|||||||
])
|
])
|
||||||
self.restore_keys_dialog(title=title, message=message, run_next=self.on_restore, is_valid=v)
|
self.restore_keys_dialog(title=title, message=message, run_next=self.on_restore, is_valid=v)
|
||||||
|
|
||||||
def choose_hw(self):
|
def choose_device(self):
|
||||||
hw_wallet_types, choices = self.plugins.hardware_wallets('create')
|
|
||||||
choices = zip(hw_wallet_types, choices)
|
|
||||||
title = _('Hardware Keystore')
|
title = _('Hardware Keystore')
|
||||||
if choices:
|
# check available plugins
|
||||||
msg = _('Select the type of device') + ':'
|
support = self.plugins.get_hardware_support()
|
||||||
else:
|
if not support:
|
||||||
msg = ' '.join([
|
msg = '\n'.join([
|
||||||
_('No hardware wallet support found on your system.'),
|
_('No hardware wallet support found on your system.'),
|
||||||
_('Please install the relevant libraries (eg python-trezor for Trezor).'),
|
_('Please install the relevant libraries (eg python-trezor for Trezor).'),
|
||||||
])
|
])
|
||||||
self.choice_dialog(title=title, message=msg, choices=choices, run_next=self.on_hardware)
|
self.confirm_dialog(title=title, message=msg, run_next= lambda x: self.choose_device())
|
||||||
|
return
|
||||||
|
# scan devices
|
||||||
|
devices = []
|
||||||
|
for name, description, plugin in support:
|
||||||
|
devmgr = plugin.device_manager()
|
||||||
|
try:
|
||||||
|
u = devmgr.unpaired_device_infos(self, plugin)
|
||||||
|
except:
|
||||||
|
print "error", name
|
||||||
|
continue
|
||||||
|
devices += map(lambda x: (name, x), u)
|
||||||
|
if not devices:
|
||||||
|
msg = '\n'.join([
|
||||||
|
_('No hardware device detected.'),
|
||||||
|
_('To trigger a rescan, press \'next\'.'),
|
||||||
|
])
|
||||||
|
self.confirm_dialog(title=title, message=msg, run_next= lambda x: self.choose_device())
|
||||||
|
return
|
||||||
|
# select device
|
||||||
|
self.devices = devices
|
||||||
|
choices = []
|
||||||
|
for name, device_info in devices:
|
||||||
|
choices.append( ((name, device_info), device_info.description) )
|
||||||
|
msg = _('Select a device') + ':'
|
||||||
|
self.choice_dialog(title=title, message=msg, choices=choices, run_next=self.on_device)
|
||||||
|
|
||||||
def on_hardware(self, hw_type):
|
def on_device(self, name, device_info):
|
||||||
self.hw_type = hw_type
|
f = lambda x: self.run('on_hardware_account_id', name, device_info, x)
|
||||||
title = _('Hardware wallet') + ' [%s]' % hw_type
|
|
||||||
message = _('Do you have a device, or do you want to restore a wallet using an existing seed?')
|
|
||||||
choices = [
|
|
||||||
('on_hardware_device', _('I have a %s device')%hw_type),
|
|
||||||
('on_hardware_seed', _('I have a %s seed')%hw_type),
|
|
||||||
]
|
|
||||||
self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run)
|
|
||||||
|
|
||||||
def on_hardware_device(self):
|
|
||||||
f = lambda x: self.run('on_hardware_account_id', x)
|
|
||||||
self.account_id_dialog(run_next=f)
|
self.account_id_dialog(run_next=f)
|
||||||
|
|
||||||
def on_hardware_account_id(self, account_id):
|
def on_hardware_account_id(self, hw_type, device_info, account_id):
|
||||||
from keystore import hardware_keystore, bip44_derivation
|
from keystore import hardware_keystore, bip44_derivation
|
||||||
derivation = bip44_derivation(int(account_id))
|
derivation = bip44_derivation(int(account_id))
|
||||||
plugin = self.plugins.get_plugin(self.hw_type)
|
plugin = self.plugins.get_plugin(hw_type)
|
||||||
xpub = plugin.setup_device(derivation, self)
|
xpub = plugin.setup_device(device_info, derivation, self)
|
||||||
# create keystore
|
# create keystore
|
||||||
d = {
|
d = {
|
||||||
'type': 'hardware',
|
'type': 'hardware',
|
||||||
'hw_type': self.hw_type,
|
'hw_type': hw_type,
|
||||||
'derivation': derivation,
|
'derivation': derivation,
|
||||||
'xpub': xpub,
|
'xpub': xpub,
|
||||||
}
|
}
|
||||||
k = hardware_keystore(self.hw_type, d)
|
k = hardware_keystore(hw_type, d)
|
||||||
self.on_keystore(k, None)
|
self.on_keystore(k, None)
|
||||||
|
|
||||||
def on_hardware_seed(self):
|
def on_hardware_seed(self):
|
||||||
|
|||||||
@@ -139,19 +139,18 @@ class Plugins(DaemonThread):
|
|||||||
requires = d.get('requires_wallet_type', [])
|
requires = d.get('requires_wallet_type', [])
|
||||||
return not requires or w.wallet_type in requires
|
return not requires or w.wallet_type in requires
|
||||||
|
|
||||||
def hardware_wallets(self, action):
|
def get_hardware_support(self):
|
||||||
wallet_types, descs = [], []
|
out = []
|
||||||
for name, (gui_good, details) in self.hw_wallets.items():
|
for name, (gui_good, details) in self.hw_wallets.items():
|
||||||
if gui_good:
|
if gui_good:
|
||||||
try:
|
try:
|
||||||
p = self.get_plugin(name)
|
p = self.get_plugin(name)
|
||||||
if action == 'restore' or p.is_enabled():
|
if p.is_enabled():
|
||||||
wallet_types.append(details[1])
|
out.append([name, details[2], p])
|
||||||
descs.append(details[2])
|
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
self.print_error("cannot load plugin for:", name)
|
self.print_error("cannot load plugin for:", name)
|
||||||
return wallet_types, descs
|
return out
|
||||||
|
|
||||||
def register_wallet_type(self, name, gui_good, wallet_type):
|
def register_wallet_type(self, name, gui_good, wallet_type):
|
||||||
from wallet import register_wallet_type, register_constructor
|
from wallet import register_wallet_type, register_constructor
|
||||||
|
|||||||
@@ -199,13 +199,12 @@ class TrezorCompatiblePlugin(HW_PluginBase):
|
|||||||
client.load_device_by_xprv(item, pin, passphrase_protection,
|
client.load_device_by_xprv(item, pin, passphrase_protection,
|
||||||
label, language)
|
label, language)
|
||||||
|
|
||||||
def setup_device(self, derivation, wizard):
|
def setup_device(self, device_info, derivation, wizard):
|
||||||
'''Called when creating a new wallet. Select the device to use. If
|
'''Called when creating a new wallet. Select the device to use. If
|
||||||
the device is uninitialized, go through the intialization
|
the device is uninitialized, go through the intialization
|
||||||
process.'''
|
process.'''
|
||||||
handler = self.create_handler(wizard)
|
handler = wizard
|
||||||
devmgr = self.device_manager()
|
devmgr = self.device_manager()
|
||||||
device_info = devmgr.select_device(handler, self)
|
|
||||||
device_id = device_info.device.id_
|
device_id = device_info.device.id_
|
||||||
if not device_info.initialized:
|
if not device_info.initialized:
|
||||||
self.initialize_device(device_id, wizard, handler)
|
self.initialize_device(device_id, wizard, handler)
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ class TrustedCoinPlugin(BasePlugin):
|
|||||||
def show_disclaimer(self, wizard):
|
def show_disclaimer(self, wizard):
|
||||||
wizard.set_icon(':icons/trustedcoin.png')
|
wizard.set_icon(':icons/trustedcoin.png')
|
||||||
wizard.stack = []
|
wizard.stack = []
|
||||||
wizard.confirm_dialog('\n\n'.join(DISCLAIMER), run_next = lambda x: wizard.run('choose_seed'))
|
wizard.confirm_dialog(title='Disclaimer', message='\n\n'.join(DISCLAIMER), run_next = lambda x: wizard.run('choose_seed'))
|
||||||
|
|
||||||
def choose_seed(self, wizard):
|
def choose_seed(self, wizard):
|
||||||
title = _('Create or restore')
|
title = _('Create or restore')
|
||||||
@@ -372,7 +372,7 @@ class TrustedCoinPlugin(BasePlugin):
|
|||||||
]
|
]
|
||||||
msg = '\n\n'.join(msg)
|
msg = '\n\n'.join(msg)
|
||||||
wizard.stack = []
|
wizard.stack = []
|
||||||
wizard.confirm_dialog(msg, run_next = lambda x: wizard.run('create_remote_key'))
|
wizard.confirm_dialog(title='', message=msg, run_next = lambda x: wizard.run('create_remote_key'))
|
||||||
|
|
||||||
def restore_wallet(self, wizard):
|
def restore_wallet(self, wizard):
|
||||||
title = _("Restore two-factor Wallet")
|
title = _("Restore two-factor Wallet")
|
||||||
|
|||||||
Reference in New Issue
Block a user