Skip to content

Commit 4014273

Browse files
committed
Add getfeatures command and dummy hwwclient.get_features
1 parent 3c1a4da commit 4014273

File tree

6 files changed

+101
-0
lines changed

6 files changed

+101
-0
lines changed

hwilib/cli.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
displayaddress,
66
enumerate,
77
find_device,
8+
get_client_class,
89
get_client,
910
getmasterxpub,
1011
getxpub,
@@ -22,6 +23,7 @@
2223
)
2324
from .errors import (
2425
handle_errors,
26+
BAD_ARGUMENT,
2527
DEVICE_CONN_ERROR,
2628
HELP_TEXT,
2729
MISSING_ARGUMENTS,
@@ -88,6 +90,10 @@ def send_pin_handler(args, client):
8890
def install_udev_rules_handler(args):
8991
return install_udev_rules('udev', args.location)
9092

93+
def getfeatures_handler(args):
94+
client_class = get_client_class(args.device_type)
95+
return client_class.get_features()
96+
9197
class HWIHelpFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionHelpFormatter):
9298
pass
9399

@@ -208,6 +214,9 @@ def process_commands(cli_args):
208214
sendpin_parser.add_argument('pin', help='The numeric positions of the PIN')
209215
sendpin_parser.set_defaults(func=send_pin_handler)
210216

217+
getfeatures_parser = subparsers.add_parser('getfeatures', help='Returns the supported features for the given device type')
218+
getfeatures_parser.set_defaults(func=getfeatures_handler)
219+
211220
if sys.platform.startswith("linux"):
212221
udevrules_parser = subparsers.add_parser('installudevrules', help='Install and load the udev rule files for the hardware wallet devices')
213222
udevrules_parser.add_argument('--location', help='The path where the udev rules files will be copied', default='/etc/udev/rules.d/')
@@ -254,6 +263,14 @@ def process_commands(cli_args):
254263
result = args.func(args)
255264
return result
256265

266+
# Do get features
267+
if command == 'getfeatures':
268+
if not args.device_type:
269+
return {'error': 'Device type needs to be specified to get features', 'code': BAD_ARGUMENT}
270+
with handle_errors(result=result, debug=args.debug):
271+
result = args.func(args)
272+
return result
273+
257274
# Auto detect if we are using fingerprint or type to identify device
258275
if args.fingerprint or (args.device_type and not args.device_path):
259276
client = find_device(args.password, args.device_type, args.fingerprint, args.expert)

hwilib/devices/coldcard.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,11 @@ def send_pin(self, pin):
340340
def toggle_passphrase(self):
341341
raise UnavailableActionError('The Coldcard does not support toggling passphrase from the host')
342342

343+
# Get HWI features for this device
344+
@classmethod
345+
def get_features(self):
346+
raise NotImplementedError('The Coldcard does not implement this method')
347+
343348
def enumerate(password=''):
344349
results = []
345350
devices = hid.enumerate(COINKITE_VID, CKCC_PID)

hwilib/devices/digitalbitbox.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,11 @@ def send_pin(self, pin):
617617
def toggle_passphrase(self):
618618
raise UnavailableActionError('The Digital Bitbox does not support toggling passphrase from the host')
619619

620+
# Get HWI features for this device
621+
@classmethod
622+
def get_features(self):
623+
raise NotImplementedError('The Digital Bitbox does not implement this method')
624+
620625
class Digitalbitbox01Client(DigitalbitboxClient):
621626
def __init__(self, path, password='', expert=False):
622627
super(Digitalbitbox01Client, self).__init__(path, password, expert)

hwilib/devices/ledger.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,11 @@ def send_pin(self, pin):
387387
def toggle_passphrase(self):
388388
raise UnavailableActionError('The Ledger Nano S and X do not support toggling passphrase from the host')
389389

390+
# Get HWI features for this device
391+
@classmethod
392+
def get_features(self):
393+
raise NotImplementedError('The Ledger Nano S and X does not implement this method')
394+
390395
class LedgerNanoSClient(LedgerClient):
391396
def __init__(self, path, password='', expert=False):
392397
super(LedgerNanoSClient, self).__init__(path, password, expert)

hwilib/devices/trezor.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,11 @@ def toggle_passphrase(self):
551551
print(PIN_MATRIX_DESCRIPTION, file=sys.stderr)
552552
return {'success': True}
553553

554+
# Get HWI features for this device
555+
@classmethod
556+
def get_features(self):
557+
raise NotImplementedError('The {} does not implement this method'.format(self.type))
558+
554559
class Trezor1Client(TrezorClient):
555560
def __init__(self, path, password='', expert=False):
556561
super(Trezor1Client, self).__init__(path, password, expert)

hwilib/hwwclient.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,60 @@
44
from .descriptor import Descriptor
55
from .serializations import PSBT
66

7+
from enum import IntEnum
8+
9+
class DeviceFeature(IntEnum):
10+
SUPPORTED = 1 # The device supports the feature and so does HWI
11+
NOT_SUPPORTED = 2 # The device supports the feature but HWI has not implemented it yet
12+
FIRMWARE_NOT_SUPPORTED = 3 # The firmware does not support the feature so HWI cannot
13+
14+
class SupportedFeatures(object):
15+
16+
def __init__(self) -> None:
17+
self.getxpub = DeviceFeature.NOT_SUPPORTED
18+
self.signmessage = DeviceFeature.NOT_SUPPORTED
19+
self.setup = DeviceFeature.NOT_SUPPORTED
20+
self.wipe = DeviceFeature.NOT_SUPPORTED
21+
self.recover = DeviceFeature.NOT_SUPPORTED
22+
self.backup = DeviceFeature.NOT_SUPPORTED
23+
self.sign_p2pkh = DeviceFeature.NOT_SUPPORTED
24+
self.sign_p2sh_p2wpkh = DeviceFeature.NOT_SUPPORTED
25+
self.sign_p2wpkh = DeviceFeature.NOT_SUPPORTED
26+
self.sign_multi_p2sh = DeviceFeature.NOT_SUPPORTED
27+
self.sign_multi_p2sh_p2wsh = DeviceFeature.NOT_SUPPORTED
28+
self.sign_multi_p2wsh = DeviceFeature.NOT_SUPPORTED
29+
self.sign_multi_bare = DeviceFeature.NOT_SUPPORTED
30+
self.sign_arbitrary_bare = DeviceFeature.NOT_SUPPORTED
31+
self.sign_arbitrary_p2sh = DeviceFeature.NOT_SUPPORTED
32+
self.sign_arbitrary_p2sh_p2wsh = DeviceFeature.NOT_SUPPORTED
33+
self.sign_arbitrary_p2wsh = DeviceFeature.NOT_SUPPORTED
34+
self.sign_coinjoin = DeviceFeature.NOT_SUPPORTED
35+
self.sign_mixed_segwit = DeviceFeature.NOT_SUPPORTED
36+
self.display_address = DeviceFeature.NOT_SUPPORTED
37+
38+
def get_printable_dict(self) -> Dict[str, DeviceFeature]:
39+
d = {}
40+
d['getxpub'] = self.getxpub
41+
d['signmessage'] = self.signmessage
42+
d['setup'] = self.setup
43+
d['wipe'] = self.wipe
44+
d['recover'] = self.recover
45+
d['backup'] = self.backup
46+
d['sign_p2pkh'] = self.sign_p2pkh
47+
d['sign_p2sh_p2wpkh'] = self.sign_p2sh_p2wpkh
48+
d['sign_p2wpkh'] = self.sign_p2wpkh
49+
d['sign_multi_p2sh'] = self.sign_multi_p2sh
50+
d['sign_multi_p2sh_p2wsh'] = self.sign_multi_p2sh_p2wsh
51+
d['sign_multi_p2wsh'] = self.sign_multi_p2wsh
52+
d['sign_multi_bare'] = self.sign_multi_bare
53+
d['sign_arbitrary_bare'] = self.sign_arbitrary_bare
54+
d['sign_arbitrary_p2sh'] = self.sign_arbitrary_p2sh
55+
d['sign_arbitrary_p2sh_p2wsh'] = self.sign_arbitrary_p2sh_p2wsh
56+
d['sign_arbitrary_p2wsh'] = self.sign_arbitrary_p2wsh
57+
d['sign_coinjoin'] = self.sign_coinjoin
58+
d['sign_mixed_segwit'] = self.sign_mixed_segwit
59+
d['display_address'] = self.display_address
60+
return d
761

862
class HardwareWalletClient(object):
963
"""Create a client for a HID device that has already been opened.
@@ -185,3 +239,13 @@ def toggle_passphrase(self) -> Dict[str, Union[bool, str, int]]:
185239
"""
186240
raise NotImplementedError("The HardwareWalletClient base class "
187241
"does not implement this method")
242+
243+
@classmethod
244+
def get_features(self) -> 'SupportedFeatures':
245+
"""
246+
Get features.
247+
248+
Returns an object with a listing of the features supported by this device.
249+
"""
250+
raise NotImplementedError("The HardwareWalletClient base class "
251+
"does not implement this method")

0 commit comments

Comments
 (0)