def prompt_pin(self, network): devices = commands.enumerate() for device in devices: if device.get('needs_pin_sent'): client = get_client(device, network) client.prompt_pin() self.clients.append(client)
def get_hwi_client(): '''create hwi client for plugged-in hardware wallet''' # list devices devices = commands.enumerate() # make sure there is only one assert len(devices) == 1, "One hardware wallet must be plugged in" # make sure it's unlocked device = devices[0] fingerprint = device.get("fingerprint") assert fingerprint is not None, f"Your ${device.type} is locked" # return client that can address this device if device['type'] == 'ledger': client = ledger.LedgerClient(device['path']) elif device['type'] == 'coldcard': client = coldcard.ColdcardClient(device['path']) elif device['type'] == 'trezor': client = trezor.TrezorClient(device['path']) else: raise Exception( f"Couldn't create client for you \"${device.type}\" device") # set HWI to testnet client.is_testnet = True return client
def enumerate(self): """ Returns a list of all connected devices (dicts). Standard HWI enumerate() command + Specter. """ self.devices = hwi_commands.enumerate() self.devices += specter_enumerate() return self.devices
def get_client_and_device(args, multisig): # Make sure one and only one device is plugged in devices = commands.enumerate(args.password) if not devices: raise JunctionError( 'No devices available. Enter your pin if device already plugged in' ) if len(devices) > 1: raise JunctionError('You can only plug in one device at a time') device = devices[0] # Can't instantiate bitbox client w/o pasphrase, so this needs to be before next block if device.get("needs_passphrase_sent") and not args.password: raise JunctionError( 'Please supply your device password with the --password flag') # Define an HWI "client" based on depending on which device is plugged in if device['type'] == 'ledger': client = ledger.LedgerClient(device['path']) elif device['type'] == 'digitalbitbox': client = digitalbitbox.DigitalbitboxClient(device['path'], args.password) elif device['type'] == 'coldcard': client = coldcard.ColdcardClient(device['path']) elif device['type'] == 'trezor': client = trezor.TrezorClient(device['path']) else: raise JunctionError( f'Devices of type "{device["type"]}" not yet supported') client.is_testnet = True # this requires a client, so it needs to come after previous block if device.get('needs_pin_sent'): # this prints to stderr ... suppress it with contextlib.redirect_stderr(io.StringIO()): client.prompt_pin() pin = input( "Use the numeric keypad to enter your pin. The layout is:\n\t7 8 9\n\t4 5 6\n\t1 2 3\nPin: " ) if not client.send_pin(pin)["success"]: raise JunctionError('Pin is wrong') # FIXME: device dict has not "fingerprint" key and we calling commands.enumerate() again throws error # This hack retrievs and sets it manually import time time.sleep(1) device['fingerprint'] = commands.get_xpub_fingerprint_as_id( commands.getxpub(client, 'm/0h')['xpub']) # FIXME: Commenting out for now because device variable is outdated in "needs_pin_sent" case and I can't manage to refresh it ... # Get updated "device" (prior value may lack "fingerprint" if device was locked) # if device.get("error"): # raise JunctionError(f"Unexpected error: {device['error']}") return client, device
def get_device(device_id): matching_device = None with hwi_lock: devices = commands.enumerate() for device in devices: if device.get('path') == device_id: matching_device = device elif device.get('fingerprint') == device_id: matching_device = device if not matching_device: raise JunctionError('Device not found') return matching_device
def get_device_and_client(): devices = commands.enumerate() if len(devices) < 1: raise Exception('No hardware wallets detected') if len(devices) > 1: raise Exception('You can only have 1 device plugged in at a time') device = devices[0] if 'fingerprint' not in device: raise Exception('Device is locked') client = commands.get_client(device['type'], device['path']) client.is_testnet = True return device, client
def devices(): devices = commands.enumerate() # prompt pins for device in devices: if device.get('needs_pin_sent'): global trezor_client trezor_client = trezor.TrezorClient(device['path']) trezor_client.prompt_pin() everything_unlocked = not any(['error' in device for device in devices]) return render_template('devices.html', devices=devices, everything_unlocked=everything_unlocked)
def wallet(): wallet = MultisigWallet.open(wallet_name) devices = commands.enumerate() unconfirmed_balance, confirmed_balance = wallet.balances() # FIXME: ugly if wallet.psbt: psbt = wallet.decode_psbt() pprint(psbt) for signer in wallet.signers: signed = False # FIXME: this should check they've signed every input, not just one input for input in psbt['inputs']: for deriv in input['bip32_derivs']: fingerprint_match = deriv['master_fingerprint'] == signer[ 'fingerprint'] pubkey_match = deriv['pubkey'] in input.get( 'partial_signatures', []) if fingerprint_match and pubkey_match: signed = True signer['signed'] = signed else: psbt = None # FIXME: ugly for signer in wallet.signers: match = {'error': "Not found"} # note: "Not found" is used in UI for device in devices: if device.get('fingerprint') == signer['fingerprint']: match = device signer['device'] = match # FIXME: ugly signer_fingerprints = [signer['fingerprint'] for signer in wallet.signers] potential_signers = [ d for d in devices if 'fingerprint' not in d or d['fingerprint'] not in signer_fingerprints ] return render_template('wallet.html', devices=devices, wallet=wallet, psbt=psbt, unconfirmed_balance=unconfirmed_balance, confirmed_balance=confirmed_balance, potential_signers=potential_signers, btc_to_sat=btc_to_sat)
def enumerate(self, passphrase='', chain=''): """ Returns a list of all connected devices (dicts). Standard HWI enumerate() command + Specter. """ self.devices = hwi_commands.enumerate(passphrase) self.devices += specter_enumerate(passphrase) for device in self.devices: client = self._get_client(device_type=device['type'], path=device['path'], passphrase=passphrase, chain=chain) try: device['fingerprint'] = client.get_master_fingerprint_hex() except: pass if client: client.close() return self.devices
def get_client_and_device(fingerprint): # get device devices = commands.enumerate() device = None for d in devices: if d.get("fingerprint") == fingerprint: device = d assert device is not None # get client if device["type"] == "ledger": client = ledger.LedgerClient(device["path"]) elif device["type"] == "coldcard": client = coldcard.ColdcardClient(device["path"]) elif device["type"] == "trezor": client = trezor.TrezorClient(device["path"]) else: raise JunctionError(f'Devices of type "{device["type"]}" not yet supported') client.is_testnet = True return client, device
def get_device_for_client(client): with hwi_lock: devices = commands.enumerate() for device in devices: if client.path == device.path: return client
def resolve_devices(self, info): return commands.enumerate()
def list_devices(): devices = commands.enumerate() devices = [Device(**device) for device in devices] return devices
async def hwi_enumerate(): async with hwi_lock: return commands.enumerate()
def api_devices(): devices = commands.enumerate() return jsonify(devices)
from hwilib import commands print(commands.enumerate())
def list_devices(): with hwi_lock: return jsonify(commands.enumerate())
def enumerate(): devices = json.dumps(commands.enumerate(), indent=4) return render_template('enumerate.html', devices=devices)
async def list_devices(request): return json(commands.enumerate())
def api_enumerate(): return jsonify(commands.enumerate())
def test(): device = commands.enumerate()[0] sync_device(device)
import sys from PySide2.QtWidgets import QApplication, QMessageBox, QGridLayout, QDialog from hwilib import commands, serializations from hwilib.devices import trezor, ledger, coldcard from hwi_qt.except_hook import except_hook from hwi_qt.logging import log from hwi_qt.selectable_text import SelectableText from hwi_qt.sync_button import SyncButton if __name__ == '__main__': devices = commands.enumerate() print(devices) sys.excepthook = except_hook log.info('Starting hwi-qt') app = QApplication(sys.argv) dialog = QDialog() dialog.layout = QGridLayout() for device in devices: name = device['type'] + '-' + device['fingerprint'] text = SelectableText(name) dialog.layout.addWidget(text, 0, 0) button = SyncButton('Sync', 'Syncing...') dialog.layout.addLayout(button, 0, 1)