diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 094e4fce9..a0a8eeff7 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -2951,7 +2951,7 @@ def stake_add( ), exit_early=False, ) - if selected_hotkey is None: + if not selected_hotkey: print_error("No delegate selected. Exiting.") raise typer.Exit() include_hotkeys = selected_hotkey diff --git a/bittensor_cli/src/commands/stake/add.py b/bittensor_cli/src/commands/stake/add.py index 2950da876..6932a2298 100644 --- a/bittensor_cli/src/commands/stake/add.py +++ b/bittensor_cli/src/commands/stake/add.py @@ -1,7 +1,6 @@ import asyncio from functools import partial -import typer from typing import TYPE_CHECKING, Optional from rich.table import Table from rich.prompt import Confirm, Prompt @@ -20,7 +19,6 @@ unlock_key, ) from bittensor_wallet import Wallet -from bittensor_wallet.errors import KeyFileError if TYPE_CHECKING: from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface @@ -338,7 +336,7 @@ async def stake_extrinsic( if prompt: if not Confirm.ask("Would you like to continue?"): - raise typer.Exit() + return False if not unlock_key(wallet).success: return False diff --git a/bittensor_cli/src/commands/stake/list.py b/bittensor_cli/src/commands/stake/list.py index 8523320ac..d5b5493b9 100644 --- a/bittensor_cli/src/commands/stake/list.py +++ b/bittensor_cli/src/commands/stake/list.py @@ -1,7 +1,6 @@ import asyncio from typing import TYPE_CHECKING, Optional -import typer from bittensor_wallet import Wallet from rich.prompt import Prompt @@ -428,7 +427,7 @@ def format_cell( if not hotkeys_to_substakes: print_error(f"No stakes found for coldkey ss58: ({coldkey_address})") - raise typer.Exit() + return if live: # Select one hotkey for live monitoring diff --git a/bittensor_cli/src/commands/stake/move.py b/bittensor_cli/src/commands/stake/move.py index 20b6d8f25..371f3ccaf 100644 --- a/bittensor_cli/src/commands/stake/move.py +++ b/bittensor_cli/src/commands/stake/move.py @@ -1,10 +1,8 @@ import asyncio from typing import TYPE_CHECKING -import typer from bittensor_wallet import Wallet -from bittensor_wallet.errors import KeyFileError from rich.table import Table from rich.prompt import Confirm, Prompt @@ -72,7 +70,7 @@ async def display_stake_movement_cross_subnets( if received_amount < Balance.from_tao(0): print_error("Not enough Alpha to pay the transaction fee.") - raise typer.Exit() + raise ValueError ideal_amount = amount_to_move * price total_slippage = ideal_amount - received_amount @@ -228,7 +226,7 @@ async def stake_move_transfer_selection( if not hotkey_stakes: print_error("You have no stakes to move.") - raise typer.Exit() + raise ValueError # Display hotkeys with stakes table = Table( @@ -358,7 +356,7 @@ async def stake_swap_selection( if not hotkey_stakes: print_error(f"No stakes found for hotkey: {wallet.hotkey_str}") - raise typer.Exit() + raise ValueError # Display available stakes table = Table( @@ -441,7 +439,10 @@ async def move_stake( prompt: bool = True, ): if interactive_selection: - selection = await stake_move_transfer_selection(subtensor, wallet) + try: + selection = stake_move_transfer_selection(subtensor, wallet) + except ValueError: + return False origin_hotkey = selection["origin_hotkey"] origin_netuid = selection["origin_netuid"] amount = selection["amount"] @@ -472,7 +473,7 @@ async def move_stake( f"in Netuid: " f"[{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{origin_netuid}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}]" ) - raise typer.Exit() + return False console.print( f"\nOrigin Netuid: " @@ -510,16 +511,19 @@ async def move_stake( # Slippage warning if prompt: - await display_stake_movement_cross_subnets( - subtensor=subtensor, - origin_netuid=origin_netuid, - destination_netuid=destination_netuid, - origin_hotkey=origin_hotkey, - destination_hotkey=destination_hotkey, - amount_to_move=amount_to_move_as_balance, - ) + try: + await display_stake_movement_cross_subnets( + subtensor=subtensor, + origin_netuid=origin_netuid, + destination_netuid=destination_netuid, + origin_hotkey=origin_hotkey, + destination_hotkey=destination_hotkey, + amount_to_move=amount_to_move_as_balance, + ) + except ValueError: + return False if not Confirm.ask("Would you like to continue?"): - raise typer.Exit() + return False # Perform moving operation. if not unlock_key(wallet).success: @@ -681,17 +685,20 @@ async def transfer_stake( # Slippage warning if prompt: - await display_stake_movement_cross_subnets( - subtensor=subtensor, - origin_netuid=origin_netuid, - destination_netuid=dest_netuid, - origin_hotkey=origin_hotkey, - destination_hotkey=origin_hotkey, - amount_to_move=amount_to_transfer, - ) + try: + await display_stake_movement_cross_subnets( + subtensor=subtensor, + origin_netuid=origin_netuid, + destination_netuid=dest_netuid, + origin_hotkey=origin_hotkey, + destination_hotkey=origin_hotkey, + amount_to_move=amount_to_transfer, + ) + except ValueError: + return False if not Confirm.ask("Would you like to continue?"): - raise typer.Exit() + return False # Perform transfer operation if not unlock_key(wallet).success: @@ -786,7 +793,10 @@ async def swap_stake( """ hotkey_ss58 = wallet.hotkey.ss58_address if interactive_selection: - selection = await stake_swap_selection(subtensor, wallet) + try: + selection = await stake_swap_selection(subtensor, wallet) + except ValueError: + return False origin_netuid = selection["origin_netuid"] amount = selection["amount"] destination_netuid = selection["destination_netuid"] @@ -834,17 +844,20 @@ async def swap_stake( # Slippage warning if prompt: - await display_stake_movement_cross_subnets( - subtensor=subtensor, - origin_netuid=origin_netuid, - destination_netuid=destination_netuid, - origin_hotkey=hotkey_ss58, - destination_hotkey=hotkey_ss58, - amount_to_move=amount_to_swap, - ) + try: + await display_stake_movement_cross_subnets( + subtensor=subtensor, + origin_netuid=origin_netuid, + destination_netuid=destination_netuid, + origin_hotkey=hotkey_ss58, + destination_hotkey=hotkey_ss58, + amount_to_move=amount_to_swap, + ) + except ValueError: + return False if not Confirm.ask("Would you like to continue?"): - raise typer.Exit() + return False # Perform swap operation if not unlock_key(wallet).success: diff --git a/bittensor_cli/src/commands/stake/remove.py b/bittensor_cli/src/commands/stake/remove.py index fc298de47..1097faf7b 100644 --- a/bittensor_cli/src/commands/stake/remove.py +++ b/bittensor_cli/src/commands/stake/remove.py @@ -2,10 +2,8 @@ from functools import partial from typing import TYPE_CHECKING, Optional -import typer from bittensor_wallet import Wallet -from bittensor_wallet.errors import KeyFileError from rich.prompt import Confirm, Prompt from rich.table import Table @@ -67,13 +65,16 @@ async def unstake( all_sn_dynamic_info = {info.netuid: info for info in all_sn_dynamic_info_} if interactive: - hotkeys_to_unstake_from, unstake_all_from_hk = await _unstake_selection( - all_sn_dynamic_info, - ck_hk_identities, - old_identities, - stake_infos, - netuid=netuid, - ) + try: + hotkeys_to_unstake_from, unstake_all_from_hk = await _unstake_selection( + all_sn_dynamic_info, + ck_hk_identities, + old_identities, + stake_infos, + netuid=netuid, + ) + except ValueError: + return False if unstake_all_from_hk: hotkey_to_unstake_all = hotkeys_to_unstake_from[0] unstake_all_alpha = Confirm.ask( @@ -266,7 +267,7 @@ async def unstake( _print_table_and_slippage(table, max_float_slippage, safe_staking) if prompt: if not Confirm.ask("Would you like to continue?"): - raise typer.Exit() + return False # Execute extrinsics if not unlock_key(wallet).success: @@ -823,7 +824,7 @@ async def _unstake_selection( ): if not stake_infos: print_error("You have no stakes to unstake.") - raise typer.Exit() + raise ValueError hotkey_stakes = {} for stake_info in stake_infos: @@ -840,7 +841,7 @@ async def _unstake_selection( print_error(f"You have no stakes to unstake in subnet {netuid}.") else: print_error("You have no stakes to unstake.") - raise typer.Exit() + raise ValueError hotkeys_info = [] for idx, (hotkey_ss58, netuid_stakes) in enumerate(hotkey_stakes.items()): diff --git a/bittensor_cli/src/commands/subnets/subnets.py b/bittensor_cli/src/commands/subnets/subnets.py index 856812c01..be595ee8e 100644 --- a/bittensor_cli/src/commands/subnets/subnets.py +++ b/bittensor_cli/src/commands/subnets/subnets.py @@ -2,10 +2,8 @@ import json import sqlite3 from typing import TYPE_CHECKING, Optional, cast -import typer from bittensor_wallet import Wallet -from bittensor_wallet.errors import KeyFileError from rich.prompt import Confirm, Prompt from rich.console import Group from rich.progress import Progress, BarColumn, TextColumn @@ -814,7 +812,7 @@ async def show_root(): root_info = next((s for s in all_subnets if s.netuid == 0), None) if root_info is None: print_error("The root subnet does not exist") - raise typer.Exit() + return False root_state, identities, old_identities = await asyncio.gather( subtensor.get_subnet_state(netuid=0, block_hash=block_hash), @@ -1017,7 +1015,7 @@ async def show_root(): async def show_subnet(netuid_: int): if not await subtensor.subnet_exists(netuid=netuid): err_console.print(f"[red]Subnet {netuid} does not exist[/red]") - raise typer.Exit() + return False block_hash = await subtensor.substrate.get_chain_head() ( subnet_info, @@ -1036,15 +1034,15 @@ async def show_subnet(netuid_: int): ) if subnet_state is None: print_error(f"Subnet {netuid_} does not exist") - raise typer.Exit() + return False if subnet_info is None: print_error(f"Subnet {netuid_} does not exist") - raise typer.Exit() + return False if len(subnet_state.hotkeys) == 0: print_error(f"Subnet {netuid_} is currently empty with 0 UIDs registered.") - raise typer.Exit() + return False # Define table properties table = Table( @@ -1381,7 +1379,7 @@ async def create( " are you sure you wish to continue?" ): console.print(":cross_mark: Aborted!") - raise typer.Exit() + return False identity = prompt_for_identity( current_identity=current_identity, @@ -2135,7 +2133,7 @@ async def get_identity(subtensor: "SubtensorInterface", netuid: int, title: str if not await subtensor.subnet_exists(netuid): print_error(f"Subnet {netuid} does not exist.") - raise typer.Exit() + return None with console.status( ":satellite: [bold green]Querying subnet identity...", spinner="earth" diff --git a/bittensor_cli/src/commands/sudo.py b/bittensor_cli/src/commands/sudo.py index 9e9098f53..ef9895d26 100644 --- a/bittensor_cli/src/commands/sudo.py +++ b/bittensor_cli/src/commands/sudo.py @@ -1,7 +1,6 @@ import asyncio from typing import TYPE_CHECKING, Union, Optional -import typer from bittensor_wallet import Wallet from rich import box from rich.table import Column, Table @@ -593,7 +592,7 @@ async def sudo_set_hyperparameter( if success: console.print("\n") print_verbose("Fetching hyperparameters") - await get_hyperparameters(subtensor, netuid=netuid) + return await get_hyperparameters(subtensor, netuid=netuid) async def get_hyperparameters(subtensor: "SubtensorInterface", netuid: int): @@ -606,7 +605,7 @@ async def get_hyperparameters(subtensor: "SubtensorInterface", netuid: int): subnet_info = await subtensor.subnet(netuid) if subnet_info is None: print_error(f"Subnet with netuid {netuid} does not exist.") - raise typer.Exit() + return False table = Table( Column("[white]HYPERPARAMETER", style=COLOR_PALETTE["SUDO"]["HYPERPARAMETER"]), diff --git a/bittensor_cli/src/commands/wallets.py b/bittensor_cli/src/commands/wallets.py index 237f401f1..3df948ba3 100644 --- a/bittensor_cli/src/commands/wallets.py +++ b/bittensor_cli/src/commands/wallets.py @@ -14,7 +14,6 @@ from rich.table import Column, Table from rich.tree import Tree from rich.padding import Padding -import typer from bittensor_cli.src import COLOR_PALETTE from bittensor_cli.src.bittensor import utils @@ -120,7 +119,7 @@ async def regen_hotkey( if json_path: if not os.path.exists(json_path) or not os.path.isfile(json_path): err_console.print(f"File {json_path} does not exist") - raise typer.Exit() + return False with open(json_path, "r") as f: json_str = f.read() diff --git a/bittensor_cli/version.py b/bittensor_cli/version.py index b035a7bd5..223118ebd 100644 --- a/bittensor_cli/version.py +++ b/bittensor_cli/version.py @@ -15,5 +15,6 @@ def version_as_int(version): __new_signature_version__ = 360 return __version_as_int__ + __version__ = "9.0.3" __version_as_int__ = version_as_int(__version__) diff --git a/tests/e2e_tests/test_root.py b/tests/e2e_tests/test_root.py index 5a7674bb9..cb567554c 100644 --- a/tests/e2e_tests/test_root.py +++ b/tests/e2e_tests/test_root.py @@ -16,6 +16,7 @@ * btcli root undelegate-stake """ + @pytest.mark.skip(reason="Root no longer applicable. We will update this.") def test_root_commands(local_chain, wallet_setup): """ diff --git a/tests/e2e_tests/test_wallet_interactions.py b/tests/e2e_tests/test_wallet_interactions.py index ad44c5a13..076f03b3e 100644 --- a/tests/e2e_tests/test_wallet_interactions.py +++ b/tests/e2e_tests/test_wallet_interactions.py @@ -419,7 +419,7 @@ def test_wallet_identities(local_chain, wallet_setup): alice_identity["name"], "--web-url", alice_identity["url"], - "--image-url", + "--image-url", alice_identity["image"], "--discord", alice_identity["discord"], @@ -445,7 +445,6 @@ def test_wallet_identities(local_chain, wallet_setup): assert alice_identity["description"] in set_id_output[11] assert alice_identity["additional"] in set_id_output[12] - # TODO: Currently coldkey + hotkey are the same for test wallets. # Maybe we can add a new key to help in distinguishing assert wallet_alice.coldkeypub.ss58_address in set_id_output[5] @@ -471,7 +470,6 @@ def test_wallet_identities(local_chain, wallet_setup): assert alice_identity["discord"] in get_identity_output[9] assert alice_identity["description"] in get_identity_output[10] assert alice_identity["additional"] in get_identity_output[11] - # Sign a message using hotkey sign_using_hotkey = exec_command_alice( diff --git a/tests/e2e_tests/utils.py b/tests/e2e_tests/utils.py index a568af517..665a4fa2f 100644 --- a/tests/e2e_tests/utils.py +++ b/tests/e2e_tests/utils.py @@ -73,8 +73,7 @@ def extract_coldkey_balance(text: str, wallet_name: str, coldkey_address: str) - Returns a dictionary with all zeros if the wallet name or coldkey address is not found. """ pattern = ( - rf"{wallet_name}\s+{coldkey_address}\s+" - r"τ\s*([\d,]+\.\d+)" # Free Balance + rf"{wallet_name}\s+{coldkey_address}\s+" r"τ\s*([\d,]+\.\d+)" # Free Balance ) match = re.search(pattern, text) @@ -140,9 +139,7 @@ def validate_wallet_overview( pattern += r"[\d.]+\s+" # VTRUST pattern += r"\*?\s*" # VPERMIT (optional *) pattern += r"[\d]+\s+" # UPDATED - pattern += ( - r"(?!none)\w+\s+" if axon_active else r"none\s+" - ) # AXON + pattern += r"(?!none)\w+\s+" if axon_active else r"none\s+" # AXON pattern += rf"{hotkey_ss58[:10]}\s*" # HOTKEY_SS58 # Search for the pattern in the wallet information