diff --git a/src/krux/key.py b/src/krux/key.py index 7559f4e0f..448fd7be9 100644 --- a/src/krux/key.py +++ b/src/krux/key.py @@ -360,7 +360,13 @@ def get_policy_type_name(policy_type): def get_network_name(network): - """Returns human-readable name for a network object (Mainnet or Testnet)""" + """Returns human-readable name for a network object""" if not network: return None - return "Mainnet" if network == NETWORKS["main"] else "Testnet" + if network == NETWORKS["test"]: + return "Testnet" + if network == NETWORKS["signet"]: + return "Signet" + if network == NETWORKS["regtest"]: + return "Regtest" + return "Mainnet" diff --git a/src/krux/krux_settings.py b/src/krux/krux_settings.py index c78150501..8edf43f86 100644 --- a/src/krux/krux_settings.py +++ b/src/krux/krux_settings.py @@ -30,6 +30,8 @@ FLASH_PATH, MAIN_TXT, TEST_TXT, + SIGNET_TXT, + REGTEST_TXT, ) from .key import ( @@ -138,7 +140,9 @@ class DefaultWallet(SettingsNamespace): """Bitcoin-specific settings""" namespace = "settings.wallet" - network = CategorySetting("network", MAIN_TXT, [MAIN_TXT, TEST_TXT]) + network = CategorySetting( + "network", MAIN_TXT, [MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT] + ) script_type = CategorySetting( "script_type", "Native Segwit - 84", SINGLESIG_SCRIPT_NAMES ) diff --git a/src/krux/pages/__init__.py b/src/krux/pages/__init__.py index 5e954c093..307606a4b 100644 --- a/src/krux/pages/__init__.py +++ b/src/krux/pages/__init__.py @@ -21,11 +21,16 @@ # THE SOFTWARE. import gc import time +from krux.settings import REGTEST_TXT, SIGNET_TXT, TEST_TXT import lcd import _thread from ..context import Context from .keypads import Keypad -from ..themes import theme, WHITE, GREEN, DARKGREY +from ..themes import ( + theme, + WHITE, + DARKGREY, +) from ..input import ( BUTTON_ENTER, BUTTON_PAGE, @@ -904,21 +909,32 @@ def draw_wallet_indicator(self): def draw_network_indicator(self): """Draws test at top if testnet is enabled""" - if self.ctx.is_logged_in() and self.ctx.wallet.key.network["name"] == "Testnet": + if self.ctx.is_logged_in(): + netname = self.ctx.wallet.key.network["name"].lower() + + if netname == TEST_TXT: + color = theme.test_color + elif netname == SIGNET_TXT: + color = theme.signet_color + elif netname == REGTEST_TXT: + color = theme.regtest_color + else: + color = theme.main_color + if not kboard.is_m5stickv: self.ctx.display.draw_string( 12, STATUS_BAR_HEIGHT - FONT_HEIGHT - 1, - "Test", - GREEN, + netname, + color, theme.info_bg_color, ) else: self.ctx.display.draw_string( 6, STATUS_BAR_HEIGHT - FONT_HEIGHT - 1, - "T", - GREEN, + netname[0] if netname != "" else "", + color, theme.info_bg_color, ) diff --git a/src/krux/pages/settings_page.py b/src/krux/pages/settings_page.py index 16045a923..f74b5590c 100644 --- a/src/krux/pages/settings_page.py +++ b/src/krux/pages/settings_page.py @@ -23,7 +23,7 @@ import lcd from ..display import FONT_HEIGHT, FONT_WIDTH, PORTRAIT -from ..themes import theme, MAIN_TXT_COLOR, TEST_TXT_COLOR +from ..themes import theme from ..settings import ( CategorySetting, NumberSetting, @@ -36,6 +36,8 @@ Settings, MAIN_TXT, TEST_TXT, + SIGNET_TXT, + REGTEST_TXT, TouchSettings, ButtonsSettings, t, @@ -63,8 +65,10 @@ DISPLAY_TEST_TIME = 5000 # 5 seconds CATEGORY_SETTING_COLOR_DICT = { - MAIN_TXT: MAIN_TXT_COLOR, - TEST_TXT: TEST_TXT_COLOR, + MAIN_TXT: theme.main_color, + TEST_TXT: theme.test_color, + SIGNET_TXT: theme.signet_color, + REGTEST_TXT: theme.regtest_color, True: theme.go_color, False: theme.no_esc_color, } diff --git a/src/krux/pages/utils.py b/src/krux/pages/utils.py index 73447e80a..0e96b7e40 100644 --- a/src/krux/pages/utils.py +++ b/src/krux/pages/utils.py @@ -189,6 +189,15 @@ def generate_wallet_info(self, network, policy, script, derivation, is_login=Fal @staticmethod def get_network_color(network_name: str): """Returns the correct theme color to write network""" - from ..themes import TEST_TXT_COLOR, MAIN_TXT_COLOR + from ..themes import theme + + if network_name == "Testnet": + return theme.test_color + + if network_name == "Signet": + return theme.signet_color + + if network_name == "Regtest": + return theme.regtest_color - return MAIN_TXT_COLOR if network_name == "Mainnet" else TEST_TXT_COLOR + return theme.main_color diff --git a/src/krux/pages/wallet_settings.py b/src/krux/pages/wallet_settings.py index 459d6f3b3..c6a8de669 100644 --- a/src/krux/pages/wallet_settings.py +++ b/src/krux/pages/wallet_settings.py @@ -47,10 +47,7 @@ NAME_MINISCRIPT, ) -from ..settings import ( - MAIN_TXT, - TEST_TXT, -) +from ..settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT from ..key import P2PKH, P2SH, P2SH_P2WPKH, P2SH_P2WSH, P2WPKH, P2WSH, P2TR @@ -306,13 +303,25 @@ def _coin_type(self): [ ("Mainnet", lambda: None), ("Testnet", lambda: None), + ("Signet", lambda: None), + ("Regtest", lambda: None), ], disable_statusbar=True, ) index, _ = submenu.run_loop() if index == submenu.back_index: return None - return NETWORKS[TEST_TXT] if index == 1 else NETWORKS[MAIN_TXT] + + if index == 1: + return NETWORKS[TEST_TXT] + + if index == 2: + return NETWORKS[SIGNET_TXT] + + if index == 3: + return NETWORKS[REGTEST_TXT] + + return NETWORKS[MAIN_TXT] def _policy_type(self): """Policy type selection menu""" diff --git a/src/krux/settings.py b/src/krux/settings.py index 51ff5dd7e..3c227f43f 100644 --- a/src/krux/settings.py +++ b/src/krux/settings.py @@ -42,6 +42,8 @@ # Network settings MAIN_TXT = "main" TEST_TXT = "test" +SIGNET_TXT = "signet" +REGTEST_TXT = "regtest" THIN_SPACE = " " # "\u2009" ELLIPSIS = "…" # "\u2026" diff --git a/src/krux/themes.py b/src/krux/themes.py index cc1086761..4ad1d0daa 100644 --- a/src/krux/themes.py +++ b/src/krux/themes.py @@ -34,6 +34,7 @@ WHITE = 0xFFFF GREEN = 0xE007 DARKGREEN = 0x8005 +LIGHT_GREEN = 0x1005 RED = 0x00F8 LIGHT_PINK = 0xDFFC PINK = 0x1FF8 @@ -45,9 +46,6 @@ LIGHTBLUE = 0xBD0E CYAN = 0xFF07 -MAIN_TXT_COLOR = ORANGE -TEST_TXT_COLOR = GREEN - THEMES = { ThemeSettings.DARK_THEME_NAME: { @@ -62,6 +60,10 @@ "toggle": CYAN, "error": RED, "highlight": LIGHTBLUE, + "main": WHITE, + "test": GREEN, + "signet": LIGHT_PINK, + "regtest": LIGHT_GREEN, }, ThemeSettings.LIGHT_THEME_NAME: { "background": WHITE, @@ -75,6 +77,10 @@ "toggle": BLUE, "error": RED, "highlight": BLUE, + "main": BLACK, + "test": DARKGREEN, + "signet": PURPLE, + "regtest": BLUE, }, ThemeSettings.ORANGE_THEME_NAME: { "background": BLACK, @@ -88,6 +94,10 @@ "toggle": CYAN, "error": RED, "highlight": YELLOW, + "main": ORANGE, + "test": GREEN, + "signet": LIGHT_PINK, + "regtest": LIGHT_GREEN, }, ThemeSettings.PINK_THEME_NAME: { "background": BLACK, @@ -101,6 +111,10 @@ "toggle": CYAN, "error": RED, "highlight": PINK, + "main": LIGHT_PINK, + "test": GREEN, + "signet": PINK, + "regtest": LIGHT_GREEN, }, ThemeSettings.GREEN_THEME_NAME: { "background": BLACK, @@ -114,10 +128,15 @@ "toggle": CYAN, "error": RED, "highlight": CYAN, + "main": GREEN, + "test": CYAN, + "signet": LIGHT_PINK, + "regtest": LIGHT_GREEN, }, } +# pylint: disable=too-many-instance-attributes class Theme: """Themes handler""" @@ -141,6 +160,10 @@ def update(self): self.toggle_color = THEMES[current_theme]["toggle"] self.error_color = THEMES[current_theme]["error"] self.highlight_color = THEMES[current_theme]["highlight"] + self.main_color = THEMES[current_theme]["main"] + self.test_color = THEMES[current_theme]["test"] + self.signet_color = THEMES[current_theme]["signet"] + self.regtest_color = THEMES[current_theme]["regtest"] theme = Theme() diff --git a/src/krux/wallet.py b/src/krux/wallet.py index 732c3235d..0289bc969 100644 --- a/src/krux/wallet.py +++ b/src/krux/wallet.py @@ -22,6 +22,7 @@ from embit.descriptor.descriptor import Descriptor from embit.descriptor.arguments import Key from embit.networks import NETWORKS +from .settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT from .krux_settings import t from .qr import FORMAT_BBQR, FORMAT_NONE from .key import ( @@ -54,6 +55,20 @@ def __init__(self, key): self.policy = None self.persisted = False self._network = None + + if ( + key is not None + and key.network is not None + and key.network + in ( + NETWORKS[MAIN_TXT], + NETWORKS[TEST_TXT], + NETWORKS[SIGNET_TXT], + NETWORKS[REGTEST_TXT], + ) + ): + self._network = key.network + if self.key and self.key.policy_type == TYPE_SINGLESIG: if self.key.script_type == P2PKH: self.descriptor = Descriptor.from_string( @@ -90,20 +105,19 @@ def get_scriptpubkey_type(self): def which_network(self): """Returns network (NETWORKS.keys()) using current wallet key, else from descriptor""" - if self._network is None: - if self.key: - self._network = [ - k for k, v in NETWORKS.items() if v == self.key.network - ][0] - else: - # use first key; restrict networks to "main" and "test", version to pubkeys - version = self.descriptor.keys[0].key.version - for em_network in ("main", "test"): - for em_vertype in ("xpub", "ypub", "zpub", "Ypub", "Zpub"): - if version == NETWORKS[em_network][em_vertype]: - self._network = em_network - break - return self._network + if self._network is not None: + for net in (TEST_TXT, SIGNET_TXT, REGTEST_TXT): + if self._network == NETWORKS[net]: + return net + + if self.descriptor: + version = self.descriptor.keys[0].key.version + for net in (TEST_TXT, SIGNET_TXT, REGTEST_TXT): + for ver in ("xpub", "ypub", "zpub", "Ypub", "Zpub"): + if version == NETWORKS[net][ver]: + return net + + return MAIN_TXT def is_multisig(self): """Returns a boolean indicating whether or not the wallet is multisig""" @@ -163,7 +177,7 @@ def _determine_descriptor_policy(self, descriptor): def _determine_descriptor_network(self, descriptor): """Returns the network from descriptor's xpub version""" version = descriptor.keys[0].key.version - for em_network in ("main", "test"): + for em_network in (MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT): for em_vertype in ("xpub", "ypub", "zpub", "Ypub", "Zpub"): if version == NETWORKS[em_network][em_vertype]: return NETWORKS[em_network] @@ -513,7 +527,7 @@ def parse_address(address_data): if not isinstance(sc, Script): try: - address_to_scriptpubkey(addr) + sc = address_to_scriptpubkey(addr) except: raise ValueError("invalid address") diff --git a/tests/pages/__init__.py b/tests/pages/__init__.py index f9543cf09..b13ac00e1 100644 --- a/tests/pages/__init__.py +++ b/tests/pages/__init__.py @@ -4,11 +4,10 @@ def create_ctx(mocker, btn_seq, wallet=None, printer=None, touch_seq=None): """Helper to create mocked context obj""" from krux.krux_settings import Settings, THERMAL_ADAFRUIT_TXT - from krux.context import Context HASHED_IMAGE_BYTES = b"3\x0fr\x7fKY\x15\t\x83\xaab\x92\x0f&\x820\xb4\x14\x87\x19\xee\x95F\x9c\x8f\x0c\xbdo\xbc\x1d\xcbT" - ctx: Context = mock_context(mocker) + ctx = mock_context(mocker) ctx.power_manager.battery_charge_remaining.return_value = 1 ctx.input.wait_for_button = mocker.MagicMock(side_effect=btn_seq) ctx.input.wait_for_fastnav_button = ctx.input.wait_for_button diff --git a/tests/pages/home_pages/test_addresses.py b/tests/pages/home_pages/test_addresses.py index ed52758e1..b6c9f475d 100644 --- a/tests/pages/home_pages/test_addresses.py +++ b/tests/pages/home_pages/test_addresses.py @@ -247,6 +247,36 @@ def test_scan_address(mocker, m5stickv, tdata): [], False, ), + # 21 - Single-sig testnet, not loaded, owned address, search successful + ( + tdata.SINGLESIG_ACTION_KEY_TEST_P2WPKH, + None, + False, + "tb1q4fhuxhrmz26kkuxxwataqw323cs2l3mgerz6kp", + True, + [BUTTON_ENTER, BUTTON_ENTER, BUTTON_ENTER], + True, + ), + # 22 - Single-sig signet, not loaded, owned address, search successful + ( + tdata.SINGLESIG_ACTION_KEY_SIGNET_P2WPKH, + None, + False, + "tb1q4fhuxhrmz26kkuxxwataqw323cs2l3mgerz6kp", + True, + [BUTTON_ENTER, BUTTON_ENTER, BUTTON_ENTER], + True, + ), + # 23 - Single-sig regtest, not loaded, owned address, search successful + ( + tdata.SINGLESIG_ACTION_KEY_REGTEST_P2WPKH, + None, + False, + "bcrt1q4fhuxhrmz26kkuxxwataqw323cs2l3mgm2mhpg", + True, + [BUTTON_ENTER, BUTTON_ENTER, BUTTON_ENTER], + True, + ), ] case_num = 0 for case in cases: @@ -564,23 +594,44 @@ def test_export_address(mocker, m5stickv, tdata): BUTTON_PAGE, # move to back BUTTON_ENTER, # exit screen ] - wallet = Wallet(tdata.SINGLESIG_ACTION_KEY_TEST_P2WPKH) - ctx = create_ctx(mocker, btn_seq, wallet, None) - addresses_ui = Addresses(ctx) - # SDHandler - mocker.patch( - "os.listdir", - return_value=["somefile", "otherfile"], - ) + cases = [ + ( + tdata.SINGLESIG_ACTION_KEY, + "49,bc1qlrznrpahpuxmtsattnexgka5p27xrzlsftl8jf\n", + ), + ( + tdata.SINGLESIG_ACTION_KEY_TEST_P2WPKH, + "49,tb1q8e9cxkrvg2d3q72wp9t33739pcnygrdyp2dm38\n", + ), + ( + tdata.SINGLESIG_ACTION_KEY_SIGNET_P2WPKH, + "49,tb1q8e9cxkrvg2d3q72wp9t33739pcnygrdyp2dm38\n", + ), + ( + tdata.SINGLESIG_ACTION_KEY_REGTEST_P2WPKH, + "49,bcrt1q8e9cxkrvg2d3q72wp9t33739pcnygrdyrr5kxw\n", + ), + ] - mocker.spy(addresses_ui, "export_address") + for i, case in enumerate(cases): + print(f"Case {i}:") + wallet = Wallet(case[0]) + ctx = create_ctx(mocker, btn_seq, wallet, None) + addresses_ui = Addresses(ctx) - m = mock_open() - with patch("builtins.open", m): - addresses_ui.addresses_menu() - m().write.assert_any_call("0,tb1q4fhuxhrmz26kkuxxwataqw323cs2l3mgerz6kp\n") - m().write.assert_any_call("49,tb1q8e9cxkrvg2d3q72wp9t33739pcnygrdyp2dm38\n") + # SDHandler + mocker.patch( + "os.listdir", + return_value=["somefile", "otherfile"], + ) + + mocker.spy(addresses_ui, "export_address") + + m = mock_open() + with patch("builtins.open", m): + addresses_ui.addresses_menu() + m().write.assert_any_call(case[1]) addresses_ui.export_address.assert_called() diff --git a/tests/pages/home_pages/test_home.py b/tests/pages/home_pages/test_home.py index 2ee00eaaf..3194dc7da 100644 --- a/tests/pages/home_pages/test_home.py +++ b/tests/pages/home_pages/test_home.py @@ -64,11 +64,17 @@ def tdata(mocker): ) SINGLESIG_ACTION_KEY = Key(ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["main"]) SINGLESIG_ACTION_KEY_TEST = Key( - ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["test"], script_type=P2TR + ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["test"], script_type=P2WPKH ) SINGLESIG_ACTION_KEY_TEST_P2WPKH = Key( ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["test"], script_type=P2WPKH ) + SINGLESIG_ACTION_KEY_SIGNET_P2WPKH = Key( + ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["signet"], script_type=P2WPKH + ) + SINGLESIG_ACTION_KEY_REGTEST_P2WPKH = Key( + ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["regtest"], script_type=P2WPKH + ) LEGACY1_KEY = Key( TEST_12_WORD_MNEMONIC, TYPE_SINGLESIG, @@ -176,6 +182,8 @@ def tdata(mocker): "SINGLESIG_ACTION_KEY", "SINGLESIG_ACTION_KEY_TEST", "SINGLESIG_ACTION_KEY_TEST_P2WPKH", + "SINGLESIG_ACTION_KEY_SIGNET_P2WPKH", + "SINGLESIG_ACTION_KEY_REGTEST_P2WPKH", "LEGACY1_KEY", "LEGACY1_MULTISIG_KEY", "NESTEDSW1_KEY", @@ -231,6 +239,8 @@ def tdata(mocker): SINGLESIG_ACTION_KEY, SINGLESIG_ACTION_KEY_TEST, SINGLESIG_ACTION_KEY_TEST_P2WPKH, + SINGLESIG_ACTION_KEY_SIGNET_P2WPKH, + SINGLESIG_ACTION_KEY_REGTEST_P2WPKH, LEGACY1_KEY, LEGACY1_MULTISIG_KEY, NESTEDSW1_KEY, @@ -414,25 +424,111 @@ def test_change_passphrase_menu(mocker, amigo, tdata): def test_cancel_customize_wallet_menu(mocker, amigo, tdata): from krux.pages.home_pages.home import Home from krux.wallet import Wallet - from krux.input import BUTTON_ENTER, BUTTON_PAGE_PREV + from krux.input import BUTTON_ENTER, BUTTON_PAGE_PREV, BUTTON_PAGE - BTN_SEQUENCE = [ - BUTTON_PAGE_PREV, # Move to No - BUTTON_ENTER, # Press No + cases = [ + # Case 0: Start with a mainnet wallet and cancel customization + ( + [ + BUTTON_PAGE_PREV, # Move to No + BUTTON_ENTER, # Press No + ], + "Mainnet", + "Mainnet", + ), + # Case 1: Start with a mainnet wallet, start the customization and cancel it + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Mainnet", + ), + # Case 2: Start with a mainnet wallet, start the customization and cancel it + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Mainnet", + ), + # Case 3: Start with a mainnet wallet, start the customization and select mainnet + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_ENTER, # Press Mainnet + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Mainnet", + ), + # Case 4: Start with a mainnet wallet, start the customization and select testnet + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE, # Move to Testnet + BUTTON_ENTER, # Press Testnet + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Testnet", + ), + # Case 5: Start with a mainnet wallet, start the customization and select signet + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE, # Move to Testnet + BUTTON_PAGE, # Move to Signet + BUTTON_ENTER, # Press Signet + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Signet", + ), + # Case 6: Start with a mainnet wallet, start the customization and select regtest + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE, # Move to Testnet + BUTTON_PAGE, # Move to Signet + BUTTON_PAGE, # Move to Regtest + BUTTON_ENTER, # Press Regtest + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Regtest", + ), ] - # Wallet before customization - wallet = Wallet(tdata.SINGLESIG_SIGNING_KEY) - assert wallet.key.network["name"] == "Mainnet" + for n, case in enumerate(cases): + print(f"Case {n}: {case}") - ctx = create_ctx(mocker, BTN_SEQUENCE, wallet=wallet) - home = Home(ctx) - home.customize() + # Wallet before customization + wallet = Wallet(tdata.SINGLESIG_SIGNING_KEY) + assert wallet.key.network["name"] == case[1] - # Wallet after cancel customization - # should remain the same as before - assert ctx.input.wait_for_button.call_count == len(BTN_SEQUENCE) - assert ctx.wallet.key.network["name"] == "Mainnet" + ctx = create_ctx(mocker, case[0], wallet=wallet) + home = Home(ctx) + home.customize() + + # Wallet after customization + assert ctx.input.wait_for_button.call_count == len(case[0]) + assert ctx.wallet.key.network["name"] == case[2] def test_customize_wallet_menu(mocker, amigo, tdata): @@ -440,23 +536,71 @@ def test_customize_wallet_menu(mocker, amigo, tdata): from krux.wallet import Wallet from krux.input import BUTTON_ENTER, BUTTON_PAGE, BUTTON_PAGE_PREV - BTN_SEQUENCE = [ - BUTTON_ENTER, # Agree to customize - BUTTON_ENTER, # Enter "Network" - BUTTON_PAGE, # Change to "Testnet" - BUTTON_ENTER, # Confirm "Testnet" - BUTTON_PAGE_PREV, # Go to Back - BUTTON_ENTER, # Exit + cases = [ + # Mainet -> Mainnet + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + BUTTON_ENTER, # Confirm "Mainnet" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Mainnet", + ), + # Mainet -> Testnet + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + BUTTON_PAGE, # Change to "Testnet" + BUTTON_ENTER, # Confirm "Testnet" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Testnet", + ), + # Mainet -> Signet + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + *([BUTTON_PAGE] * 2), # Change to "Signet" + BUTTON_ENTER, # Confirm "Signet" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Signet", + ), + # Mainet -> Regtest + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + *([BUTTON_PAGE] * 3), # Change to "Regtest" + BUTTON_ENTER, # Confirm "Regtest" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Regtest", + ), ] - wallet = Wallet(tdata.SINGLESIG_SIGNING_KEY) - ctx = create_ctx(mocker, BTN_SEQUENCE, wallet=wallet) - assert ctx.wallet.key.network["name"] == "Mainnet" - home = Home(ctx) - home.customize() + for n, case in enumerate(cases): + print(f"Case {n}: {case}") + wallet = Wallet(tdata.SINGLESIG_12_WORD_KEY) + ctx = create_ctx(mocker, case[0], wallet=wallet) + assert ctx.wallet.key.network["name"] == case[1] + home = Home(ctx) + home.customize() - assert ctx.input.wait_for_button.call_count == len(BTN_SEQUENCE) - assert ctx.wallet.key.network["name"] == "Testnet" + assert ctx.wallet.key.network["name"] == case[2] + assert ctx.input.wait_for_button.call_count == len(case[0]) + n += 1 def test_cancel_load_bip85_menu(mocker, amigo, tdata): diff --git a/tests/pages/test_login.py b/tests/pages/test_login.py index 2023fbab3..8a120f395 100644 --- a/tests/pages/test_login.py +++ b/tests/pages/test_login.py @@ -13,7 +13,9 @@ def mock_retro_compatibility(mocker, amigo): class MockDefaultWallet: namespace = "settings.wallet" - network = CategorySetting("network", "main", ["main", "test"]) + network = CategorySetting( + "network", "main", ["main", "test", "signet", "regtest"] + ) script_type = CategorySetting("script_type", "test", ["test"]) multisig = CategorySetting("multisig", True, [True, False]) diff --git a/tests/shared_mocks.py b/tests/shared_mocks.py index ee6a7097f..c6498660e 100644 --- a/tests/shared_mocks.py +++ b/tests/shared_mocks.py @@ -791,7 +791,7 @@ def board_embed_fire(): ) -def mock_context(mocker): +def mock_context(mocker: MagicMock): import board if board.config["type"] == "m5stickv": diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 19a445d36..1c8bd3955 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -1,3 +1,4 @@ +from re import S import pytest from ur.ur_decoder import URDecoder @@ -9,6 +10,7 @@ def tdata(mocker): from ur.ur import UR from krux.bbqr import encode_bbqr from embit.networks import NETWORKS + from krux.settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT from krux.key import ( Key, P2PKH, @@ -28,15 +30,48 @@ def tdata(mocker): TEST_MNEMONIC2 = "brush badge sing still venue panther kitchen please help panel bundle excess sign couch stove increase human once effort candy goat top tiny major" TEST_MNEMONIC3 = "range fatigue into stadium endless kitchen royal present rally welcome scatter twice" - SINGLESIG_KEY = Key( - TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"] - ) # default account=0, script=P2WPKH - LEGACY1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"], "", 1, P2PKH) + SINGLESIG_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT]) + SINGLESIG_KEY_TESTNET = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT]) + SINGLESIG_KEY_SIGNET = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT]) + SINGLESIG_KEY_REGTEST = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT]) + # default account=0, script=P2WPKH + + LEGACY1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT], "", 1, P2PKH) + LEGACY1_KEY_TESTNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT], "", 1, P2PKH + ) + LEGACY1_KEY_SIGNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT], "", 1, P2PKH + ) + LEGACY1_KEY_REGTEST = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT], "", 1, P2PKH + ) + # default account=1, script=P2PKH + NESTEDSW1_KEY = Key( - TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"], "", 1, P2SH_P2WPKH + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT], "", 1, P2SH_P2WPKH ) - TAPROOT1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"], "", 1, P2TR) + NESTEDSW1_KEY_TESTNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT], "", 1, P2SH_P2WPKH + ) + NESTEDSW1_KEY_SIGNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT], "", 1, P2SH_P2WPKH + ) + NESTEDSW1_KEY_REGTEST = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT], "", 1, P2SH_P2WPKH + ) + # default account=1, script=P2WSH_P2WPKH + TAPROOT1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT], "", 1, P2TR) + TAPROOT1_KEY_TESTNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT], "", 1, P2TR + ) + TAPROOT1_KEY_SIGNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT], "", 1, P2TR + ) + TAPROOT1_KEY_REGTEST = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT], "", 1, P2TR + ) # p2sh wallet without cosigner indexes MULTISIG_LEGACY_NO_COSIGNER_1 = Key( TEST_MNEMONIC1, TYPE_MULTISIG, NETWORKS["main"], "", None, P2SH @@ -93,6 +128,7 @@ def tdata(mocker): # MULTISIG_NATIVE_SW_3 [d3a80c8b/48h/0h/0h/2h]xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv KRUX_LEGACY1_DESCRIPTOR = "pkh([55f8fc5d/44h/0h/1h]xpub6C1dUaopHgps6X75i61KaJEDm4qkFeqjhm4by1ebvpgAsKDaEhGLgNX88bvuWPm4rSVe7GsYvQLDAXXLnxNsAbd3VwRihgM3q1kEkixBAbE)" + KRUX_LEGACY1_DESCRIPTOR_TESTNET = "pkh([55f8fc5d/44h/1h/1h]tpubDCxMZswvJHvfY7cXBB1DusWNpcc6MV2Dv6eTFAYfY4xPewEbzCUUhfRiYaga2u71R3dbVx4PijdjpNRdxxvvjcZq3aMYcDASTZzYK44fegG/<0;1>/*)" KRUX_LEGACY1_XPUB = "[55f8fc5d/44h/0h/1h]xpub6C1dUaopHgps6X75i61KaJEDm4qkFeqjhm4by1ebvpgAsKDaEhGLgNX88bvuWPm4rSVe7GsYvQLDAXXLnxNsAbd3VwRihgM3q1kEkixBAbE" # This is a non-extended pubkey (the first-one) derived from KRUX_LEGACY1_DESCRIPTOR @@ -101,6 +137,7 @@ def tdata(mocker): ) KRUX_NESTEDSW1_DESCRIPTOR = "sh(wpkh([55f8fc5d/49h/0h/1h]xpub6Ca1JGnSFNZ7jjwturEn944t8B9kBgiTKtmr3maTbryEyDyYY9xycVSQaFxeUPjbHyX7MUvLUbdoDVK7XZ7Fib9We4BQRRk8bZjW2UPRjHV))" + KRUX_NESTEDSW1_DESCRIPTOR_TESTNET = "sh(wpkh([55f8fc5d/49h/1h/1h]tpubDDYHYR15Go9atMZsjP6yuGBdL8qJJGHbfbJQBssrGPmaJYaLhoqchx4mn5tLwziyWXyML37NpbF5goGPEcfvtiKR1UJhMk4ArVh28wGmU98/<0;1>/*))" KRUX_NESTEDSW1_XPUB = "[55f8fc5d/49h/0h/1h]xpub6Ca1JGnSFNZ7jjwturEn944t8B9kBgiTKtmr3maTbryEyDyYY9xycVSQaFxeUPjbHyX7MUvLUbdoDVK7XZ7Fib9We4BQRRk8bZjW2UPRjHV" KRUX_NESTEDSW1_YPUB = "[55f8fc5d/49h/0h/1h]ypub6XQGbwTMQ46bb391kD2QM9APJ9JC8JhxF1J4qAULysM82Knmnp8YEZ6YbTvEUJPWhcdv6xWtwFzM6mvgFFXGWpq7WPsq1LZcsHo9R97uuE4" KRUX_NESTEDSW1_YPUB_DESCRIPTOR = "sh(wpkh(" + KRUX_NESTEDSW1_YPUB + "))" @@ -109,8 +146,8 @@ def tdata(mocker): KRUX_NATIVESW1_XPUB = "[55f8fc5d/84h/0h/1h]xpub6DPMTPxGMqdu43FvwYdC6eHCPJWckCkx1rLJ1HEG7259GyWQD5P17WB2oowP9SpQdC8ogrmXfwfoazvf6Te8svtxWh4UTwTqyRdG5G54FxW" KRUX_NATIVESW1_ZPUB = "[55f8fc5d/84h/0h/1h]zpub6s3t4jJ6fCirkdeAcGCSWpUCjEoWdSjwr5Nja522s2puPB8riPi8MdVJrDrZ9G8FSUNRBoxebGNuMa9nXrUAUQGAFNTKdm6pWskYrMahu1i" KRUX_NATIVESW1_ZPUB_DESCRIPTOR = "wpkh(" + KRUX_NATIVESW1_ZPUB + ")" - KRUX_TAPROOT1_DESCRIPTOR = "tr([55f8fc5d/86h/0h/1h]xpub6CNGwJbVG9sQsJjtwLiemRFAfvDafL8zRthnHWNQbRz1PwAm28T1v5hLmJhFft71oEDCbA3xHemnScW5VWheP1BxXNVnoYboyw6t4wuKu5q)" + KRUX_TAPROOT1_DESCRIPTOR_TESTNET = "tr([55f8fc5d/86h/1h/1h]tpubDD6e1Di1uHy5PizN7knRiWgfiHQCY7iLM1a7N5ie1XXAe6GGjhJTJgZjVA38E4HsUVtFqWU6m2QhtgB5YiRMdV324yRjGoXRuT3yLFsvqiG/<0;1>/*)" KRUX_TAPROOT1_XPUB = "[55f8fc5d/86h/0h/1h]xpub6CNGwJbVG9sQsJjtwLiemRFAfvDafL8zRthnHWNQbRz1PwAm28T1v5hLmJhFft71oEDCbA3xHemnScW5VWheP1BxXNVnoYboyw6t4wuKu5q" SPECTER_SINGLESIG_DESCRIPTOR = "wpkh([55f8fc5d/84h/0h/0h]xpub6DPMTPxGMqdtzMwpqT1dDQaVdyaEppEm2qYSaJ7ANsuES7HkNzrXJst1Ed8D7NAnijUdgSDUFgph1oj5LKKAD5gyxWNhNP2AuDqaKYqzphA/0/*)" @@ -213,7 +250,7 @@ def tdata(mocker): xpub6F2P6Pz5KLPgCc6pTBd2xxCunaSYWc8CdkL28W5z15pJrN3aCYY7mCUAkCMtqrgT2wdhAGgRnJxAkCCUpGKoXKxQ57yffEGmPwtYA3DEXwu d3a80c8b: - xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv + xpub6FKYY6y3oVi7ihSCszFKRSSINGLESIG_KEY_TESTNET eZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv """ BLUEWALLET_MULTISIG_WALLET_DATA_INVALID_KEYS = """ @@ -260,8 +297,8 @@ def tdata(mocker): ) UNAMBIGUOUS_SINGLESIG_DESCRIPTOR = "wpkh([55f8fc5d/84h/0h/0h]xpub6DPMTPxGMqdtzMwpqT1dDQaVdyaEppEm2qYSaJ7ANsuES7HkNzrXJst1Ed8D7NAnijUdgSDUFgph1oj5LKKAD5gyxWNhNP2AuDqaKYqzphA/<0;1>/*)" + UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET = "wpkh([55f8fc5d/84h/1h/0h]tpubDCDuqu5HtBX2aD7wxvnHcj1DgFN1UVgzLkA1Ms4Va4P7TpJ3jDknkPLwWT2SqrKXNNAtJBCPcbJ8Tcpm6nLxgFapCZyhKgqwcEGv1BVpD7s/<0;1>/*)" AMBIGUOUS_SINGLESIG_DESCRIPTOR = "wpkh([55f8fc5d/84h/0h/0h]xpub6DPMTPxGMqdtzMwpqT1dDQaVdyaEppEm2qYSaJ7ANsuES7HkNzrXJst1Ed8D7NAnijUdgSDUFgph1oj5LKKAD5gyxWNhNP2AuDqaKYqzphA)" - UNAMBIGUOUS_MULTISIG_DESCRIPTOR = "wsh(sortedmulti(2,[55f8fc5d/48h/0h/0h/2h]xpub6EKmKYGYc1WY6t9d3d9SksR8keSaPZbFa6tqsGiH4xVxx8d2YyxSX7WG6yXEX3CmG54dPCxaapDw1XsjwCmfoqP7tbsAeqMVfKvqSAu4ndy/<0;1>/*,[3e15470d/48h/0h/0h/2h]xpub6F2P6Pz5KLPgCc6pTBd2xxCunaSYWc8CdkL28W5z15pJrN3aCYY7mCUAkCMtqrgT2wdhAGgRnJxAkCCUpGKoXKxQ57yffEGmPwtYA3DEXwu/<0;1>/*,[d3a80c8b/48h/0h/0h/2h]xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv/<0;1>/*))" AMBIGUOUS_MULTISIG_DESCRIPTOR = "wsh(sortedmulti(2,[55f8fc5d/48h/0h/0h/2h]xpub6EKmKYGYc1WY6t9d3d9SksR8keSaPZbFa6tqsGiH4xVxx8d2YyxSX7WG6yXEX3CmG54dPCxaapDw1XsjwCmfoqP7tbsAeqMVfKvqSAu4ndy,[3e15470d/48h/0h/0h/2h]xpub6F2P6Pz5KLPgCc6pTBd2xxCunaSYWc8CdkL28W5z15pJrN3aCYY7mCUAkCMtqrgT2wdhAGgRnJxAkCCUpGKoXKxQ57yffEGmPwtYA3DEXwu,[d3a80c8b/48h/0h/0h/2h]xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv))" @@ -283,9 +320,21 @@ def tdata(mocker): "TEST_MNEMONIC2", "TEST_MNEMONIC3", "SINGLESIG_KEY", + "SINGLESIG_KEY_TESTNET", + "SINGLESIG_KEY_SIGNET", + "SINGLESIG_KEY_REGTEST", "LEGACY1_KEY", + "LEGACY1_KEY_TESTNET", + "LEGACY1_KEY_SIGNET", + "LEGACY1_KEY_REGTEST", "NESTEDSW1_KEY", + "NESTEDSW1_KEY_TESTNET", + "NESTEDSW1_KEY_SIGNET", + "NESTEDSW1_KEY_REGTEST", "TAPROOT1_KEY", + "TAPROOT1_KEY_TESTNET", + "TAPROOT1_KEY_SIGNET", + "TAPROOT1_KEY_REGTEST", "MULTISIG_LEGACY_NO_COSIGNER_1", "MULTISIG_LEGACY_NO_COSIGNER_2", "MULTISIG_LEGACY_NO_COSIGNER_3", @@ -301,9 +350,11 @@ def tdata(mocker): "MINISCRIPT_KEY", "TAP_MINISCRIPT_KEY", "KRUX_LEGACY1_DESCRIPTOR", + "KRUX_LEGACY1_DESCRIPTOR_TESTNET", "KRUX_LEGACY1_XPUB", "KRUX_LEGACY1_RAW_PUBKEY", "KRUX_NESTEDSW1_DESCRIPTOR", + "KRUX_NESTEDSW1_DESCRIPTOR_TESTNET", "KRUX_NESTEDSW1_XPUB", "KRUX_NESTEDSW1_YPUB", "KRUX_NESTEDSW1_YPUB_DESCRIPTOR", @@ -312,6 +363,7 @@ def tdata(mocker): "KRUX_NATIVESW1_ZPUB", "KRUX_NATIVESW1_ZPUB_DESCRIPTOR", "KRUX_TAPROOT1_DESCRIPTOR", + "KRUX_TAPROOT1_DESCRIPTOR_TESTNET", "KRUX_TAPROOT1_XPUB", "SPECTER_SINGLESIG_DESCRIPTOR", "SPECTER_SINGLESIG_WALLET_DATA", @@ -341,6 +393,7 @@ def tdata(mocker): "UR_BYTES_MULTISIG_DESCRIPTOR", "UR_BYTES_MULTISIG_WALLET_DATA", "UNAMBIGUOUS_SINGLESIG_DESCRIPTOR", + "UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET", "AMBIGUOUS_SINGLESIG_DESCRIPTOR", "UNAMBIGUOUS_MULTISIG_DESCRIPTOR", "AMBIGUOUS_MULTISIG_DESCRIPTOR", @@ -358,9 +411,21 @@ def tdata(mocker): TEST_MNEMONIC2, TEST_MNEMONIC3, SINGLESIG_KEY, + SINGLESIG_KEY_TESTNET, + SINGLESIG_KEY_SIGNET, + SINGLESIG_KEY_REGTEST, LEGACY1_KEY, + LEGACY1_KEY_TESTNET, + LEGACY1_KEY_SIGNET, + LEGACY1_KEY_REGTEST, NESTEDSW1_KEY, + NESTEDSW1_KEY_TESTNET, + NESTEDSW1_KEY_SIGNET, + NESTEDSW1_KEY_REGTEST, TAPROOT1_KEY, + TAPROOT1_KEY_TESTNET, + TAPROOT1_KEY_SIGNET, + TAPROOT1_KEY_REGTEST, MULTISIG_LEGACY_NO_COSIGNER_1, MULTISIG_LEGACY_NO_COSIGNER_2, MULTISIG_LEGACY_NO_COSIGNER_3, @@ -376,9 +441,11 @@ def tdata(mocker): MINISCRIPT_KEY, TAP_MINISCRIPT_KEY, KRUX_LEGACY1_DESCRIPTOR, + KRUX_LEGACY1_DESCRIPTOR_TESTNET, KRUX_LEGACY1_XPUB, KRUX_LEGACY1_RAW_PUBKEY, KRUX_NESTEDSW1_DESCRIPTOR, + KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, KRUX_NESTEDSW1_XPUB, KRUX_NESTEDSW1_YPUB, KRUX_NESTEDSW1_YPUB_DESCRIPTOR, @@ -387,6 +454,7 @@ def tdata(mocker): KRUX_NATIVESW1_ZPUB, KRUX_NATIVESW1_ZPUB_DESCRIPTOR, KRUX_TAPROOT1_DESCRIPTOR, + KRUX_TAPROOT1_DESCRIPTOR_TESTNET, KRUX_TAPROOT1_XPUB, SPECTER_SINGLESIG_DESCRIPTOR, SPECTER_SINGLESIG_WALLET_DATA, @@ -416,6 +484,7 @@ def tdata(mocker): UR_BYTES_MULTISIG_DESCRIPTOR, UR_BYTES_MULTISIG_WALLET_DATA, UNAMBIGUOUS_SINGLESIG_DESCRIPTOR, + UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, AMBIGUOUS_SINGLESIG_DESCRIPTOR, UNAMBIGUOUS_MULTISIG_DESCRIPTOR, AMBIGUOUS_MULTISIG_DESCRIPTOR, @@ -432,52 +501,160 @@ def tdata(mocker): def test_init_singlesig(mocker, m5stickv, tdata): from embit.descriptor import Descriptor + from krux.key import get_network_name from krux.wallet import Wallet, to_unambiguous_descriptor + from krux.settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT + from embit.networks import NETWORKS cases = [ - # key, descriptor, label, policy - (None, None, None, None), + # key, descriptor, label, policy, network + # Case 0: All None + (None, None, None, None, None), + # Case 1: Single sig, p2wpkh, mainnet ( tdata.SINGLESIG_KEY, tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR, "Single-sig", {"type": "p2wpkh"}, + NETWORKS[MAIN_TXT], ), + # Case 2: Single sig, p2wpkh, testnet + ( + tdata.SINGLESIG_KEY_TESTNET, + tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2wpkh"}, + NETWORKS[TEST_TXT], + ), + # Case 3: Single sig, p2wpkh, signet + ( + tdata.SINGLESIG_KEY_SIGNET, + tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2wpkh"}, + NETWORKS[SIGNET_TXT], + ), + # Case 4: Single sig, p2wpkh, regtest + ( + tdata.SINGLESIG_KEY_REGTEST, + tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2wpkh"}, + NETWORKS[REGTEST_TXT], + ), + # Case 5: Single sig, p2pkh, mainnet ( tdata.LEGACY1_KEY, tdata.KRUX_LEGACY1_DESCRIPTOR, "Single-sig", {"type": "p2pkh"}, + NETWORKS[MAIN_TXT], + ), + # Case 6: Single sig, p2pkh, testnet + ( + tdata.LEGACY1_KEY_TESTNET, + tdata.KRUX_LEGACY1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2pkh"}, + NETWORKS[TEST_TXT], ), + # Case 7: Single sig, p2pkh, signet + ( + tdata.LEGACY1_KEY_SIGNET, + tdata.KRUX_LEGACY1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2pkh"}, + NETWORKS[SIGNET_TXT], + ), + # Case 8: Single sig, p2pkh, regtest + ( + tdata.LEGACY1_KEY_REGTEST, + tdata.KRUX_LEGACY1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2pkh"}, + NETWORKS[REGTEST_TXT], + ), + # Case 9: Single sig, p2sh-p2wpkh, mainnet ( tdata.NESTEDSW1_KEY, tdata.KRUX_NESTEDSW1_DESCRIPTOR, "Single-sig", {"type": "p2sh-p2wpkh"}, + NETWORKS[MAIN_TXT], + ), + # Case 10: Single sig, p2sh-p2wpkh, testnet + ( + tdata.NESTEDSW1_KEY_TESTNET, + tdata.KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2sh-p2wpkh"}, + NETWORKS[TEST_TXT], + ), + # Case 11: Single sig, p2sh-p2wpkh, signet + ( + tdata.NESTEDSW1_KEY_SIGNET, + tdata.KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2sh-p2wpkh"}, + NETWORKS[SIGNET_TXT], + ), + # Case 12: Single sig, p2sh-p2wpkh, regtest + ( + tdata.NESTEDSW1_KEY_REGTEST, + tdata.KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2sh-p2wpkh"}, + NETWORKS[REGTEST_TXT], ), + # Case 13: Single sig, p2tr, mainnet ( tdata.TAPROOT1_KEY, tdata.KRUX_TAPROOT1_DESCRIPTOR, "Single-sig", {"type": "p2tr"}, + NETWORKS[MAIN_TXT], + ), + # Case 14: Single sig, p2tr, testnet + ( + tdata.TAPROOT1_KEY_TESTNET, + tdata.KRUX_TAPROOT1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2tr"}, + NETWORKS[TEST_TXT], + ), + # Case 15: Single sig, p2tr, sigtnet + ( + tdata.TAPROOT1_KEY_SIGNET, + tdata.KRUX_TAPROOT1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2tr"}, + NETWORKS[SIGNET_TXT], + ), + # Case 16: Single sig, p2tr, regtest + ( + tdata.TAPROOT1_KEY_REGTEST, + tdata.KRUX_TAPROOT1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2tr"}, + NETWORKS[REGTEST_TXT], ), ] - for _case in cases: + for i, _case in enumerate(cases): + print(f"Case {i}") wallet = Wallet(_case[0]) - assert isinstance(wallet, Wallet) if wallet.descriptor: # don't fail simply because of a difference between ambiguous and unambiguous - try: - assert wallet.descriptor.to_string() == _case[1] - except AssertionError: - test_descr = to_unambiguous_descriptor( - Descriptor.from_string(_case[1]) - ).to_string() - assert wallet.descriptor.to_string() == test_descr + test_descr = to_unambiguous_descriptor( + Descriptor.from_string(_case[1]) + ).to_string() + assert wallet.descriptor.to_string() == test_descr assert wallet.label == _case[2] assert wallet.policy == _case[3] + if wallet.key: + assert get_network_name(wallet.key.network) == _case[4]["name"] + def test_init_multisig(mocker, m5stickv, tdata): from krux.wallet import Wallet