diff --git a/src/cryptoadvance/specter/device.py b/src/cryptoadvance/specter/device.py index a92cbee6e..de6f2b828 100644 --- a/src/cryptoadvance/specter/device.py +++ b/src/cryptoadvance/specter/device.py @@ -1,4 +1,7 @@ import json +from typing import Type + +from cryptoadvance.specter.util.reflection import get_subclasses_for_clazz from .key import Key from .persistence import read_json_file, write_json_file import logging @@ -59,6 +62,13 @@ class Device: return f"{module_array[2]}_endpoint.static" return "static" + @classmethod + def get_device_class_by_device_type_string(cls, device_type: str) -> Type: + for clazz in get_subclasses_for_clazz(Device): + if clazz.device_type == device_type: + return clazz + return None + def create_psbts(self, base64_psbt, wallet): """ Overwrite this method for a device. diff --git a/src/cryptoadvance/specter/devices/__init__.py b/src/cryptoadvance/specter/devices/__init__.py index 44fe54c77..6b19138ae 100644 --- a/src/cryptoadvance/specter/devices/__init__.py +++ b/src/cryptoadvance/specter/devices/__init__.py @@ -1,4 +1,3 @@ -from .device_types import DeviceTypes from .coldcard import ColdCard from .trezor import Trezor from .ledger import Ledger diff --git a/src/cryptoadvance/specter/devices/bitbox02.py b/src/cryptoadvance/specter/devices/bitbox02.py index 1e9c525e6..b370ccf41 100644 --- a/src/cryptoadvance/specter/devices/bitbox02.py +++ b/src/cryptoadvance/specter/devices/bitbox02.py @@ -1,9 +1,8 @@ -from . import DeviceTypes from .hwi_device import HWIDevice class BitBox02(HWIDevice): - device_type = DeviceTypes.BITBOX02 + device_type = "bitbox02" name = "BitBox02" icon = "img/devices/bitbox02_icon.svg" supports_hwi_multisig_display_address = True diff --git a/src/cryptoadvance/specter/devices/bitcoin_core.py b/src/cryptoadvance/specter/devices/bitcoin_core.py index db2c2f2a7..2a67b29fb 100644 --- a/src/cryptoadvance/specter/devices/bitcoin_core.py +++ b/src/cryptoadvance/specter/devices/bitcoin_core.py @@ -15,13 +15,12 @@ from ..util.base58 import decode_base58, encode_base58_checksum from ..util.descriptor import AddChecksum from ..util.xpub import convert_xpub_prefix, get_xpub_fingerprint from ..util.mnemonic import mnemonic_to_root -from . import DeviceTypes logger = logging.getLogger(__name__) class BitcoinCore(Device): - device_type = DeviceTypes.BITCOINCORE + device_type = "bitcoincore" name = "Bitcoin Core (hot wallet)" icon = "img/devices/bitcoincore_icon.svg" @@ -271,7 +270,7 @@ class BitcoinCoreWatchOnly(BitcoinCore): It can be converted back to a device of Type BitcoinCore by providing the 12 words again. """ - device_type = DeviceTypes.BITCOINCORE_WATCHONLY + device_type = "bitcoincore_watchonly" name = "Bitcoin Core (watch only)" hot_wallet = False @@ -306,6 +305,6 @@ class BitcoinCoreWatchOnly(BitcoinCore): ) # Change type (also triggers write to file) - self.set_type(DeviceTypes.BITCOINCORE) + self.set_type(BitcoinCore.device_type) # After update this device will be available as a BitcoinCore (hot) instance self.manager.update(comment="via BitcoinCoreWatchOnly") diff --git a/src/cryptoadvance/specter/devices/cobo.py b/src/cryptoadvance/specter/devices/cobo.py index aed5a8a8f..22d4ba7e5 100644 --- a/src/cryptoadvance/specter/devices/cobo.py +++ b/src/cryptoadvance/specter/devices/cobo.py @@ -1,7 +1,6 @@ import hashlib # from ..device import Device -from . import DeviceTypes from .coldcard import ColdCard from hwilib.psbt import PSBT from binascii import a2b_base64 @@ -11,7 +10,7 @@ from ..helpers import to_ascii20 class Cobo(ColdCard): - device_type = DeviceTypes.COBO + device_type = "cobo" name = "Cobo Vault" icon = "img/devices/cobo_icon.svg" diff --git a/src/cryptoadvance/specter/devices/device_types.py b/src/cryptoadvance/specter/devices/device_types.py deleted file mode 100644 index bd724957c..000000000 --- a/src/cryptoadvance/specter/devices/device_types.py +++ /dev/null @@ -1,27 +0,0 @@ -""" A list of static device_type strings. As Devices can, in the meantime, also be created - in extensions, this file should be limited to device_type_strings which ARE referenced - in core-code. - ToDo: Remove the strings which are only referenced in the corresponding-type. - There is no point in doing that. -""" - - -class DeviceTypes: - BITCOINCORE = "bitcoincore" - BITCOINCORE_WATCHONLY = "bitcoincore_watchonly" - ELEMENTSCORE = "elementscore" - - # All those ones are not treated any different in core-code and therefore should no - # longer be referenced here: - BITBOX02 = "bitbox02" - COBO = "cobo" - COLDCARD = "coldcard" - GENERICDEVICE = "other" - JADE = "jade" - KEEPKEY = "keepkey" - LEDGER = "ledger" - SEEDSIGNER = "seedsigner" - SPECTERDIY = "specter" - TREZOR = "trezor" - KEYSTONE = "keystone" - PASSPORT = "passport" diff --git a/src/cryptoadvance/specter/devices/elements_core.py b/src/cryptoadvance/specter/devices/elements_core.py index dde06bad4..f7f8d7439 100644 --- a/src/cryptoadvance/specter/devices/elements_core.py +++ b/src/cryptoadvance/specter/devices/elements_core.py @@ -3,12 +3,11 @@ from embit import bip39 from embit.liquid.slip77 import master_blinding_from_seed from ..helpers import is_liquid -from . import DeviceTypes from .bitcoin_core import BitcoinCore class ElementsCore(BitcoinCore): - device_type = DeviceTypes.ELEMENTSCORE + device_type = "elementscore" name = "Elements Core (hot wallet)" icon = "img/devices/elementscore_icon.svg" diff --git a/src/cryptoadvance/specter/devices/generic.py b/src/cryptoadvance/specter/devices/generic.py index 8ee617525..5a6543270 100644 --- a/src/cryptoadvance/specter/devices/generic.py +++ b/src/cryptoadvance/specter/devices/generic.py @@ -1,9 +1,8 @@ -from . import DeviceTypes from ..device import Device class GenericDevice(Device): - device_type = DeviceTypes.GENERICDEVICE + device_type = "other" name = "Other" sd_card_support = True diff --git a/src/cryptoadvance/specter/devices/jade.py b/src/cryptoadvance/specter/devices/jade.py index 2e7773657..eafe44fa1 100644 --- a/src/cryptoadvance/specter/devices/jade.py +++ b/src/cryptoadvance/specter/devices/jade.py @@ -1,4 +1,3 @@ -from . import DeviceTypes from .hwi_device import HWIDevice from .hwi.jade import JadeClient from .hwi.jade import enumerate as jade_enumerate @@ -6,7 +5,7 @@ from ..helpers import is_liquid class Jade(HWIDevice): - device_type = DeviceTypes.JADE + device_type = "jade" name = "Jade" icon = "img/devices/jade_icon.svg" diff --git a/src/cryptoadvance/specter/devices/keepkey.py b/src/cryptoadvance/specter/devices/keepkey.py index 989f93da5..046be7e28 100644 --- a/src/cryptoadvance/specter/devices/keepkey.py +++ b/src/cryptoadvance/specter/devices/keepkey.py @@ -1,10 +1,9 @@ -from . import DeviceTypes from .hwi_device import HWIDevice from hwilib.devices.keepkey import KeepkeyClient class Keepkey(HWIDevice): - device_type = DeviceTypes.KEEPKEY + device_type = "keepkey" name = "KeepKey" icon = "img/devices/keepkey_icon.svg" diff --git a/src/cryptoadvance/specter/devices/keystone.py b/src/cryptoadvance/specter/devices/keystone.py index 25e3de673..df10526f0 100644 --- a/src/cryptoadvance/specter/devices/keystone.py +++ b/src/cryptoadvance/specter/devices/keystone.py @@ -1,4 +1,3 @@ -from . import DeviceTypes from .cobo import Cobo from ..helpers import to_ascii20 from ..util.xpub import get_xpub_fingerprint @@ -6,7 +5,7 @@ from binascii import b2a_base64 class Keystone(Cobo): - device_type = DeviceTypes.KEYSTONE + device_type = "keystone" name = "Keystone" icon = "img/devices/keystone_icon.svg" diff --git a/src/cryptoadvance/specter/devices/ledger.py b/src/cryptoadvance/specter/devices/ledger.py index d90d76e40..6d8083212 100644 --- a/src/cryptoadvance/specter/devices/ledger.py +++ b/src/cryptoadvance/specter/devices/ledger.py @@ -1,9 +1,8 @@ -from . import DeviceTypes from .hwi_device import HWIDevice class Ledger(HWIDevice): - device_type = DeviceTypes.LEDGER + device_type = "ledger" name = "Ledger" icon = "img/devices/ledger_icon.svg" diff --git a/src/cryptoadvance/specter/devices/passport.py b/src/cryptoadvance/specter/devices/passport.py index f9c6471d2..8d3fdb39b 100644 --- a/src/cryptoadvance/specter/devices/passport.py +++ b/src/cryptoadvance/specter/devices/passport.py @@ -1,8 +1,7 @@ -from . import DeviceTypes from .keystone import Keystone class Passport(Keystone): - device_type = DeviceTypes.PASSPORT + device_type = "passport" name = "Passport" icon = "img/devices/passport_icon.svg" diff --git a/src/cryptoadvance/specter/devices/seedsigner.py b/src/cryptoadvance/specter/devices/seedsigner.py index 37f2ea9f5..350746ce7 100644 --- a/src/cryptoadvance/specter/devices/seedsigner.py +++ b/src/cryptoadvance/specter/devices/seedsigner.py @@ -1,9 +1,8 @@ -from . import DeviceTypes from ..device import Device class SeedSignerDevice(Device): - device_type = DeviceTypes.SEEDSIGNER + device_type = "seedsigner" name = "SeedSigner" icon = "img/devices/seedsigner_icon.svg" diff --git a/src/cryptoadvance/specter/devices/specter.py b/src/cryptoadvance/specter/devices/specter.py index b630460c3..34bbae36e 100644 --- a/src/cryptoadvance/specter/devices/specter.py +++ b/src/cryptoadvance/specter/devices/specter.py @@ -1,5 +1,4 @@ import hashlib -from . import DeviceTypes from .sd_card_device import SDCardDevice from .hwi.specter_diy import enumerate as specter_enumerate, SpecterClient from ..helpers import to_ascii20 @@ -60,7 +59,7 @@ def fill_external_wallet_derivations(psbt, wallet): class Specter(SDCardDevice): - device_type = DeviceTypes.SPECTERDIY + device_type = "specter" name = "Specter-DIY" icon = "img/devices/specter_icon.svg" diff --git a/src/cryptoadvance/specter/devices/trezor.py b/src/cryptoadvance/specter/devices/trezor.py index a92d0eb94..2dfe0e875 100644 --- a/src/cryptoadvance/specter/devices/trezor.py +++ b/src/cryptoadvance/specter/devices/trezor.py @@ -1,10 +1,9 @@ -from . import DeviceTypes from .hwi_device import HWIDevice from hwilib.devices.trezor import TrezorClient class Trezor(HWIDevice): - device_type = DeviceTypes.TREZOR + device_type = "trezor" name = "Trezor" icon = "img/devices/trezor_icon.svg" diff --git a/src/cryptoadvance/specter/server_endpoints/devices.py b/src/cryptoadvance/specter/server_endpoints/devices.py index 7ccf4d5c1..df046891d 100644 --- a/src/cryptoadvance/specter/server_endpoints/devices.py +++ b/src/cryptoadvance/specter/server_endpoints/devices.py @@ -3,16 +3,21 @@ import json import logging import random import re +from cryptoadvance.specter.device import Device -from cryptoadvance.specter.devices.device_types import DeviceTypes from flask import Blueprint, Flask from flask import current_app as app from flask import jsonify, redirect, render_template, request, url_for from flask_babel import lazy_gettext as _ from flask_login import current_user, login_required from mnemonic import Mnemonic +from cryptoadvance.specter.devices.elements_core import ElementsCore +from cryptoadvance.specter.managers.node_manager import NodeManager +from cryptoadvance.specter.node import Node -from ..devices.bitcoin_core import BitcoinCore +from cryptoadvance.specterext.electrum.controller import specter + +from ..devices.bitcoin_core import BitcoinCore, BitcoinCoreWatchOnly from ..helpers import is_testnet from ..key import Key from ..managers.device_manager import get_device_class @@ -92,15 +97,15 @@ def new_device_keys(device_type): keys.append(Key.parse_xpub(request.form["master_pub_key"])) if not keys and not err: if device_type in [ - DeviceTypes.BITCOINCORE, - DeviceTypes.ELEMENTSCORE, - DeviceTypes.BITCOINCORE_WATCHONLY, + BitcoinCore.device_type, + ElementsCore.device_type, + BitcoinCoreWatchOnly.device_type, ]: if not paths: err = _("No paths were specified, please provide at least one.") if err is None: if existing_device: - if device_type == DeviceTypes.BITCOINCORE_WATCHONLY: + if device_type == BitcoinCoreWatchOnly.device_type: device.setup_device( file_password, app.specter.wallet_manager ) @@ -404,7 +409,7 @@ def new_device_manual(): def device(device_alias): err = None try: - device = app.specter.device_manager.get_by_alias(device_alias) + device: Device = app.specter.device_manager.get_by_alias(device_alias) except: return render_template( "base.jinja", error=_("Device not found"), specter=app.specter, rand=rand @@ -490,7 +495,16 @@ def device(device_alias): ) elif action == "settype": device_type = request.form["device_type"] - device.set_type(device_type) + if app.specter.node_manager.active_node.is_device_supported( + Device.get_device_class_by_device_type_string(device_type) + ): + device.set_type(device_type) + # Should actually not be possible to end up here (UI doesn't let you select this) but just in case + else: + flash( + f"The device type {Device.get_device_class_by_device_type_string(device_type).name} is not supported by your connection.", + "error", + ) device = copy.deepcopy(device) def sort_accounts(k): diff --git a/src/cryptoadvance/specter/specter.py b/src/cryptoadvance/specter/specter.py index b43b550c7..a615b6d74 100644 --- a/src/cryptoadvance/specter/specter.py +++ b/src/cryptoadvance/specter/specter.py @@ -15,7 +15,7 @@ from sys import exit from urllib.parse import urlparse import requests -from cryptoadvance.specter.devices.device_types import DeviceTypes +from cryptoadvance.specter.devices.bitcoin_core import BitcoinCore, BitcoinCoreWatchOnly from cryptoadvance.specter.services.service_encrypted_storage import ( ServiceEncryptedStorageManager, ServiceUnencryptedStorageManager, @@ -729,8 +729,8 @@ class Specter: data.compress_type = zipfile.ZIP_DEFLATED device = device.json # Exporting the bitcoincore hot wallet as watchonly - if device["type"] == DeviceTypes.BITCOINCORE: - device["type"] = DeviceTypes.BITCOINCORE_WATCHONLY + if device["type"] == BitcoinCore.device_type: + device["type"] = BitcoinCoreWatchOnly.device_type zf.writestr( "devices/{}.json".format(device["alias"]), json.dumps(device) ) diff --git a/src/cryptoadvance/specter/templates/device/components/device_type.jinja b/src/cryptoadvance/specter/templates/device/components/device_type.jinja index e509d37ba..4a8d1bd79 100644 --- a/src/cryptoadvance/specter/templates/device/components/device_type.jinja +++ b/src/cryptoadvance/specter/templates/device/components/device_type.jinja @@ -5,8 +5,10 @@ diff --git a/src/cryptoadvance/specter/util/reflection.py b/src/cryptoadvance/specter/util/reflection.py index ac9b5b348..13e2abf24 100644 --- a/src/cryptoadvance/specter/util/reflection.py +++ b/src/cryptoadvance/specter/util/reflection.py @@ -1,6 +1,6 @@ import logging from importlib import import_module -from inspect import isclass +import inspect import os from pathlib import Path import pkgutil @@ -106,7 +106,7 @@ def get_classlist_of_type_clazz_from_modulelist(clazz, modulelist): logger.debug(f"Imported {fq_module_name}") for attribute_name in dir(module): attribute = getattr(module, attribute_name) - if isclass(attribute): + if inspect.isclass(attribute): if ( issubclass(attribute, clazz) # This works for 1 level inheritance within one module @@ -123,7 +123,6 @@ def get_classlist_of_type_clazz_from_modulelist(clazz, modulelist): def get_subclasses_for_clazz_in_cwd(clazz, cwd=".") -> List[type]: """Returns all subclasses of class clazz located in the CWD if the cwd is not a specter-desktop dev-env-kind-of-dir or contains any .py-file - So """ package_dirs = [] # security first! No dynamic loading in app-images @@ -158,8 +157,10 @@ def get_subclasses_for_clazz_in_cwd(clazz, cwd=".") -> List[type]: return get_subclasses_for_clazz(clazz, package_dirs) -def get_subclasses_for_clazz(clazz, package_dirs: List[str] = None): - """Returns all subclasses of class clazz located in the CWD +def get_subclasses_for_clazz( + clazz, package_dirs: List[str] = None, package: str = None +): + """Returns all subclasses of class clazz searching in specific directories potentially add additional_packagedirs which is usefull for calculating pyinstaller hiddenimports """ @@ -222,21 +223,13 @@ def get_subclasses_for_clazz(clazz, package_dirs: List[str] = None): f"cryptoadvance.specter.util.migrations.{module_name}" ) else: - try: - module = import_module( - f"{module_name}.{camelcase2snake_case(clazz.__name__)}" - ) - logger.debug( - f"Imported {module_name}.{camelcase2snake_case(clazz.__name__)}" - ) - except ModuleNotFoundError as e: - logger.debug( - f"No Service Impl found in {module_name}.service. Skipping!" - ) - continue + # Hopefully all the classes we're searching for are imported otherwise not much get + # found + return get_subclasses(clazz) + for attribute_name in dir(module): attribute = getattr(module, attribute_name) - if isclass(attribute): + if inspect.isclass(attribute): if ( issubclass(attribute, clazz) and not attribute.__name__ == clazz.__name__ @@ -244,3 +237,17 @@ def get_subclasses_for_clazz(clazz, package_dirs: List[str] = None): class_list.append(attribute) logger.info(f" Found class {attribute.__name__}") return class_list + + +def get_subclasses(cls): + """Naive implementation of searching for subclasses. This will only return classes which has been + imported. If you also want to find classes which are not imported, you need to provide package-directories + or well known places as for specific classes as implemented in get_subclasses_for_clazz + Returns all subclasses of a specific call including sususub...classes + """ + subclasses = [] + for subclass in cls.__subclasses__(): + # if not subclass.__module__.startswith("test_"): + subclasses.append(subclass) + subclasses.extend(get_subclasses(subclass)) + return subclasses diff --git a/src/cryptoadvance/specterext/devhelp/devices/devhelpdevice.py b/src/cryptoadvance/specterext/devhelp/devices/devhelpdevice.py index e70feb131..56a307b5e 100644 --- a/src/cryptoadvance/specterext/devhelp/devices/devhelpdevice.py +++ b/src/cryptoadvance/specterext/devhelp/devices/devhelpdevice.py @@ -1,7 +1,6 @@ """ This Device is not a real device but just something to demonstrate the creation of devices in extensions """ -from cryptoadvance.specter.devices.device_types import DeviceTypes from cryptoadvance.specter.devices.hwi_device import HWIDevice diff --git a/src/cryptoadvance/specterext/electrum/devices/electrum.py b/src/cryptoadvance/specterext/electrum/devices/electrum.py index 90ceb4108..dac425c52 100644 --- a/src/cryptoadvance/specterext/electrum/devices/electrum.py +++ b/src/cryptoadvance/specterext/electrum/devices/electrum.py @@ -1,6 +1,5 @@ from binascii import a2b_base64 from typing import List -from cryptoadvance.specter.devices.device_types import DeviceTypes from cryptoadvance.specter.util.base43 import b43_encode from cryptoadvance.specter.device import Device diff --git a/src/cryptoadvance/specterext/spectrum/spectrum_node.py b/src/cryptoadvance/specterext/spectrum/spectrum_node.py index 137c116d3..8d0c969b0 100644 --- a/src/cryptoadvance/specterext/spectrum/spectrum_node.py +++ b/src/cryptoadvance/specterext/spectrum/spectrum_node.py @@ -1,4 +1,6 @@ import logging +from cryptoadvance.specter.util.reflection import get_class +from cryptoadvance.specter.util.common import snake_case2camelcase from cryptoadvance.specterext.spectrum.bridge_rpc import BridgeRPC from cryptoadvance.specter.helpers import deep_update from cryptoadvance.specter.node import AbstractNode @@ -198,8 +200,18 @@ class SpectrumNode(AbstractNode): # If a device class is passed as argument, take that, otherwise derive the class from the instance if device_class_or_device_instance.__class__ == type: device_class = device_class_or_device_instance + elif device_class_or_device_instance.__class__ == str: + if device_class_or_device_instance.__contains__("."): + device_class = get_class(device_class) + else: + fqcn_device_class = ( + "cryptoadvance.specter.devices." + + snake_case2camelcase(device_class_or_device_instance) + ) + device_class = get_class(fqcn_device_class) else: device_class = device_class_or_device_instance.__class__ + logger.debug(f"Device_class = {device_class}") if device_class == BitcoinCore: return False return True diff --git a/tests/test_hwibridge.py b/tests/test_hwibridge.py index ba532cc5d..1bb4d7767 100644 --- a/tests/test_hwibridge.py +++ b/tests/test_hwibridge.py @@ -1,5 +1,6 @@ import json, requests -from cryptoadvance.specter.devices import DeviceTypes +from cryptoadvance.specter.devices.ledger import Ledger +from cryptoadvance.specter.devices.trezor import Trezor def test_malformed_parse_error(client): @@ -134,7 +135,7 @@ def test_call_not_connected_device(client): "method": "prompt_pin", "id": 1, "params": { - "device_type": DeviceTypes.TREZOR, + "device_type": Trezor.device_type, "path": "", "passphrase": "", "chain": "test", @@ -161,7 +162,7 @@ def test_call_prompt_pin_invalid_device(client): "method": "prompt_pin", "id": 1, "params": { - "device_type": DeviceTypes.LEDGER, + "device_type": Ledger.device_type, "path": "", "passphrase": "", "chain": "test", diff --git a/tests/test_managers_service.py b/tests/test_managers_service.py index 74b7ad067..41e40bbae 100644 --- a/tests/test_managers_service.py +++ b/tests/test_managers_service.py @@ -69,6 +69,7 @@ def test_ServiceManager_get_service_x_dirs(caplog): def test_ServiceManager_get_service_packages(caplog): caplog.set_level(logging.DEBUG) + packages = ServiceManager.get_service_packages() assert "cryptoadvance.specterext.electrum.service" in packages assert "cryptoadvance.specterext.electrum.devices.electrum" in packages diff --git a/tests/test_managers_wallet.py b/tests/test_managers_wallet.py index 59f2e1cc7..4a58b25b3 100644 --- a/tests/test_managers_wallet.py +++ b/tests/test_managers_wallet.py @@ -5,13 +5,14 @@ import time from unittest.mock import MagicMock import pytest +from cryptoadvance.specter.devices.bitcoin_core import BitcoinCore +from cryptoadvance.specter.devices.generic import GenericDevice from cryptoadvance.specter.helpers import is_testnet from cryptoadvance.specter.process_controller.bitcoind_controller import ( BitcoindPlainController, ) from cryptoadvance.specter.util.mnemonic import generate_mnemonic from cryptoadvance.specter.key import Key -from cryptoadvance.specter.devices import DeviceTypes from cryptoadvance.specter.managers.wallet_manager import WalletManager from cryptoadvance.specter.specter_error import SpecterError from cryptoadvance.specter.util.descriptor import AddChecksum, Descriptor @@ -493,7 +494,7 @@ def test_singlesig_wallet_backup_and_restore(caplog, specter_regtest_configured, ) = descriptor.parse_signers(device_manager.devices, cosigners_types) assert len(cosigners_types) == 0 - assert unknown_cosigners_types[0] == DeviceTypes.GENERICDEVICE + assert unknown_cosigners_types[0] == GenericDevice.device_type # Re-create the device new_device = device_manager.add_device( @@ -543,7 +544,7 @@ def test_multisig_wallet_backup_and_restore( # Create a pair of hot wallet signers hot_wallet_1_device = device_manager.add_device( - name="hot_key_1", device_type=DeviceTypes.BITCOINCORE, keys=[] + name="hot_key_1", device_type=BitcoinCore.device_type, keys=[] ) hot_wallet_1_device.setup_device(file_password=None, wallet_manager=wallet_manager) hot_wallet_1_device.add_hot_wallet_keys( @@ -557,7 +558,7 @@ def test_multisig_wallet_backup_and_restore( keys_purposes=[], ) hot_wallet_2_device = device_manager.add_device( - name="hot_key_2", device_type=DeviceTypes.BITCOINCORE, keys=[] + name="hot_key_2", device_type=BitcoinCore.device_type, keys=[] ) hot_wallet_2_device.setup_device(file_password=None, wallet_manager=wallet_manager) hot_wallet_2_device.add_hot_wallet_keys( @@ -619,10 +620,10 @@ def test_multisig_wallet_backup_and_restore( assert cosigners_types[0]["type"] == device_type assert cosigners_types[1]["label"] == "hot_key_1" - assert cosigners_types[1]["type"] == DeviceTypes.BITCOINCORE + assert cosigners_types[1]["type"] == BitcoinCore.device_type assert cosigners_types[2]["label"] == "hot_key_2" - assert cosigners_types[2]["type"] == DeviceTypes.BITCOINCORE + assert cosigners_types[2]["type"] == BitcoinCore.device_type # Re-create the Trezor device new_device = device_manager.add_device( @@ -679,7 +680,7 @@ def test_multisig_wallet_backup_and_restore( # Now we don't know any of the cosigners' types assert len(cosigners_types) == 0 - assert unknown_cosigners_types[0] == DeviceTypes.GENERICDEVICE + assert unknown_cosigners_types[0] == GenericDevice.device_type # Re-create all three devices for i, (unknown_cosigner_key, label) in enumerate(unknown_cosigners): diff --git a/tests/test_util_reflection.py b/tests/test_util_reflection.py index 42233cac7..1a3a34c18 100644 --- a/tests/test_util_reflection.py +++ b/tests/test_util_reflection.py @@ -5,6 +5,7 @@ from typing import List from cryptoadvance.specter.device import Device from cryptoadvance.specter.devices.bitbox02 import BitBox02 from cryptoadvance.specter.specter_error import SpecterInternalException +from cryptoadvance.specter.util.migrations.migration_0001 import SpecterMigration_0001 from cryptoadvance.specter.util.reflection import ( get_class, get_subclasses_for_clazz, @@ -19,6 +20,7 @@ from cryptoadvance.specter.util.migrations.migration_0000 import SpecterMigratio from cryptoadvance.specter.services.service import Service from cryptoadvance.specterext.devhelp.service import DevhelpService from cryptoadvance.specterext.electrum.service import ElectrumService +from cryptoadvance.specterext.spectrum.service import SpectrumService from cryptoadvance.specterext.swan.service import SwanService @@ -86,9 +88,12 @@ def test_get_subclasses_for_clazz_in_cwd(caplog): def test_get_subclasses_for_class(caplog): caplog.set_level(logging.DEBUG) classlist = get_subclasses_for_clazz(SpecterMigration) - assert SpecterMigration_0000 in classlist + assert len(classlist) >= 3 classlist = get_subclasses_for_clazz(Service) - assert len(classlist) == 4 # Happy to remove that at some point - assert SwanService in classlist - assert ElectrumService in classlist - assert DevhelpService in classlist + assert len(classlist) >= 4 + # checking naively for certain Services would be counterproductive if you import + # the class. THis needs to work without importing the class! + # But we can test like this: + assert "SwanService" in [cls.__name__ for cls in classlist] + classlist = get_subclasses_for_clazz(Device) + assert len(classlist) > 5