diff --git a/hwilib/devices/coldcard.py b/hwilib/devices/coldcard.py index 7ea18ea9a..28bd0936a 100644 --- a/hwilib/devices/coldcard.py +++ b/hwilib/devices/coldcard.py @@ -2,7 +2,11 @@ from typing import Dict, Union -from ..hwwclient import HardwareWalletClient +from ..hwwclient import ( + DeviceFeature, + HardwareWalletClient, + SupportedFeatures, +) from ..errors import ( ActionCanceledError, BadArgumentError, @@ -94,6 +98,29 @@ def func(*args, **kwargs): # This class extends the HardwareWalletClient for ColdCard specific things class ColdcardClient(HardwareWalletClient): + # Setup features + features = SupportedFeatures() + features.getxpub = DeviceFeature.SUPPORTED + features.signmessage = DeviceFeature.SUPPORTED + features.setup = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.wipe = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.recover = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.backup = DeviceFeature.SUPPORTED + features.sign_p2pkh = DeviceFeature.SUPPORTED + features.sign_p2sh_p2wpkh = DeviceFeature.SUPPORTED + features.sign_p2wpkh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_coinjoin = DeviceFeature.SUPPORTED + features.sign_mixed_segwit = DeviceFeature.SUPPORTED + features.display_address = DeviceFeature.SUPPORTED + def __init__(self, path, password='', expert=False): super(ColdcardClient, self).__init__(path, password, expert) # Simulator hard coded pipe socket @@ -343,7 +370,7 @@ def toggle_passphrase(self): # Get HWI features for this device @classmethod def get_features(self): - raise NotImplementedError('The Coldcard does not implement this method') + return self.features.get_printable_dict() def enumerate(password=''): results = [] diff --git a/hwilib/devices/digitalbitbox.py b/hwilib/devices/digitalbitbox.py index a55cd698d..73222d702 100644 --- a/hwilib/devices/digitalbitbox.py +++ b/hwilib/devices/digitalbitbox.py @@ -15,7 +15,11 @@ import time from typing import Dict, Union -from ..hwwclient import HardwareWalletClient +from ..hwwclient import ( + DeviceFeature, + HardwareWalletClient, + SupportedFeatures, +) from ..errors import ( ActionCanceledError, BadArgumentError, @@ -326,6 +330,29 @@ def format_backup_filename(name): # This class extends the HardwareWalletClient for Digital Bitbox specific things class DigitalbitboxClient(HardwareWalletClient): + # Setup features + features = SupportedFeatures() + features.getxpub = DeviceFeature.SUPPORTED + features.signmessage = DeviceFeature.SUPPORTED + features.setup = DeviceFeature.SUPPORTED + features.wipe = DeviceFeature.SUPPORTED + features.recover = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.backup = DeviceFeature.SUPPORTED + features.sign_p2pkh = DeviceFeature.SUPPORTED + features.sign_p2sh_p2wpkh = DeviceFeature.SUPPORTED + features.sign_p2wpkh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_bare = DeviceFeature.SUPPORTED + features.sign_arbitrary_bare = DeviceFeature.SUPPORTED + features.sign_arbitrary_p2sh = DeviceFeature.SUPPORTED + features.sign_arbitrary_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_arbitrary_p2wsh = DeviceFeature.SUPPORTED + features.sign_coinjoin = DeviceFeature.SUPPORTED + features.sign_mixed_segwit = DeviceFeature.SUPPORTED + features.display_address = DeviceFeature.FIRMWARE_NOT_SUPPORTED + def __init__(self, path, password, expert=False): super(DigitalbitboxClient, self).__init__(path, password, expert) if not password: @@ -620,7 +647,7 @@ def toggle_passphrase(self): # Get HWI features for this device @classmethod def get_features(self): - raise NotImplementedError('The Digital Bitbox does not implement this method') + return self.features.get_printable_dict() class Digitalbitbox01Client(DigitalbitboxClient): def __init__(self, path, password='', expert=False): diff --git a/hwilib/devices/keepkey.py b/hwilib/devices/keepkey.py index ab69ef6fc..507118f94 100644 --- a/hwilib/devices/keepkey.py +++ b/hwilib/devices/keepkey.py @@ -6,6 +6,10 @@ common_err_msgs, handle_errors, ) +from ..hwwclient import ( + DeviceFeature, + SupportedFeatures, +) from .trezorlib.transport import ( enumerate_devices, KEEPKEY_VENDOR_IDS, @@ -15,10 +19,38 @@ py_enumerate = enumerate # Need to use the enumerate built-in but there's another function already named that class KeepkeyClient(TrezorClient): + + # Setup features + features = SupportedFeatures() + features.getxpub = DeviceFeature.SUPPORTED + features.signmessage = DeviceFeature.SUPPORTED + features.setup = DeviceFeature.SUPPORTED + features.wipe = DeviceFeature.SUPPORTED + features.recover = DeviceFeature.SUPPORTED + features.backup = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_p2pkh = DeviceFeature.SUPPORTED + features.sign_p2sh_p2wpkh = DeviceFeature.SUPPORTED + features.sign_p2wpkh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_coinjoin = DeviceFeature.SUPPORTED + features.sign_mixed_segwit = DeviceFeature.SUPPORTED + features.display_address = DeviceFeature.SUPPORTED + def __init__(self, path, password='', expert=False): super(KeepkeyClient, self).__init__(path, password, expert) self.type = 'Keepkey' + @classmethod + def get_features(self): + return self.features.get_printable_dict() + def enumerate(password=''): results = [] for dev in enumerate_devices(): diff --git a/hwilib/devices/ledger.py b/hwilib/devices/ledger.py index bd0b7eecd..589a1f123 100644 --- a/hwilib/devices/ledger.py +++ b/hwilib/devices/ledger.py @@ -2,7 +2,11 @@ from typing import Dict, Union -from ..hwwclient import HardwareWalletClient +from ..hwwclient import ( + DeviceFeature, + HardwareWalletClient, + SupportedFeatures, +) from ..errors import ( ActionCanceledError, BadArgumentError, @@ -100,6 +104,29 @@ def func(*args, **kwargs): # This class extends the HardwareWalletClient for Ledger Nano S and Nano X specific things class LedgerClient(HardwareWalletClient): + # Setup features + features = SupportedFeatures() + features.getxpub = DeviceFeature.SUPPORTED + features.signmessage = DeviceFeature.SUPPORTED + features.setup = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.wipe = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.recover = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.backup = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_p2pkh = DeviceFeature.SUPPORTED + features.sign_p2sh_p2wpkh = DeviceFeature.SUPPORTED + features.sign_p2wpkh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_bare = DeviceFeature.SUPPORTED + features.sign_arbitrary_bare = DeviceFeature.SUPPORTED + features.sign_arbitrary_p2sh = DeviceFeature.SUPPORTED + features.sign_arbitrary_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_arbitrary_p2wsh = DeviceFeature.SUPPORTED + features.sign_coinjoin = DeviceFeature.SUPPORTED + features.sign_mixed_segwit = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.display_address = DeviceFeature.SUPPORTED + def __init__(self, path, password='', expert=False): super(LedgerClient, self).__init__(path, password, expert) self.type = 'Ledger Nano S and X' @@ -390,7 +417,7 @@ def toggle_passphrase(self): # Get HWI features for this device @classmethod def get_features(self): - raise NotImplementedError('The Ledger Nano S and X does not implement this method') + return self.features.get_printable_dict() class LedgerNanoSClient(LedgerClient): def __init__(self, path, password='', expert=False): diff --git a/hwilib/devices/trezor.py b/hwilib/devices/trezor.py index e310fb1f0..24155868f 100644 --- a/hwilib/devices/trezor.py +++ b/hwilib/devices/trezor.py @@ -2,7 +2,11 @@ from typing import Dict, Union -from ..hwwclient import HardwareWalletClient +from ..hwwclient import ( + DeviceFeature, + HardwareWalletClient, + SupportedFeatures, +) from ..errors import ( ActionCanceledError, BadArgumentError, @@ -554,18 +558,74 @@ def toggle_passphrase(self): # Get HWI features for this device @classmethod def get_features(self): - raise NotImplementedError('The {} does not implement this method'.format(self.type)) + raise UnavailableActionError('A specific Trezor model must be specified to get the features') class Trezor1Client(TrezorClient): + + # Setup features + features = SupportedFeatures() + features.getxpub = DeviceFeature.SUPPORTED + features.signmessage = DeviceFeature.SUPPORTED + features.setup = DeviceFeature.SUPPORTED + features.wipe = DeviceFeature.SUPPORTED + features.recover = DeviceFeature.SUPPORTED + features.backup = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_p2pkh = DeviceFeature.SUPPORTED + features.sign_p2sh_p2wpkh = DeviceFeature.SUPPORTED + features.sign_p2wpkh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_coinjoin = DeviceFeature.SUPPORTED + features.sign_mixed_segwit = DeviceFeature.SUPPORTED + features.display_address = DeviceFeature.SUPPORTED + def __init__(self, path, password='', expert=False): super(Trezor1Client, self).__init__(path, password, expert) self.type = 'Trezor 1' + @classmethod + def get_features(self): + return self.features.get_printable_dict() + class TrezorTClient(TrezorClient): + + # Setup features + features = SupportedFeatures() + features.getxpub = DeviceFeature.SUPPORTED + features.signmessage = DeviceFeature.SUPPORTED + features.setup = DeviceFeature.SUPPORTED + features.wipe = DeviceFeature.SUPPORTED + features.recover = DeviceFeature.SUPPORTED + features.backup = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_p2pkh = DeviceFeature.SUPPORTED + features.sign_p2sh_p2wpkh = DeviceFeature.SUPPORTED + features.sign_p2wpkh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh = DeviceFeature.SUPPORTED + features.sign_multi_p2sh_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_p2wsh = DeviceFeature.SUPPORTED + features.sign_multi_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_bare = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2sh_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_arbitrary_p2wsh = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.sign_coinjoin = DeviceFeature.SUPPORTED + features.sign_mixed_segwit = DeviceFeature.FIRMWARE_NOT_SUPPORTED + features.display_address = DeviceFeature.SUPPORTED + def __init__(self, path, password='', expert=False): super(TrezorTClient, self).__init__(path, password, expert) self.type = 'Trezor T' + @classmethod + def get_features(self): + return self.features.get_printable_dict() + def enumerate(password=''): results = [] for dev in enumerate_devices():