diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed1fc6d52..88ce34a0c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,7 +45,7 @@ jobs: fi - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: dist path: dist/ @@ -60,7 +60,7 @@ jobs: steps: - name: Download artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: dist path: dist/ diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 9c15685f9..5038ca06c 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -2551,6 +2551,7 @@ def stake_list( live: bool = Options.live, quiet: bool = Options.quiet, verbose: bool = Options.verbose, + no_prompt: bool = Options.prompt, # TODO add: all-wallets, reuse_last, html_output ): """List all stake accounts for wallet.""" @@ -2579,7 +2580,12 @@ def stake_list( return self._run_command( stake.stake_list( - wallet, coldkey_ss58, self.initialize_chain(network), live, verbose + wallet, + coldkey_ss58, + self.initialize_chain(network), + live, + verbose, + no_prompt, ) ) @@ -3122,22 +3128,25 @@ def stake_move( ) origin_hotkey = wallet.hotkey.ss58_address else: - wallet = self.wallet_ask( - wallet_name, - wallet_path, - wallet_hotkey, - ask_for=[], - validate=WV.WALLET_AND_HOTKEY, - ) - origin_hotkey = wallet.hotkey.ss58_address + if is_valid_ss58_address(wallet_hotkey): + origin_hotkey = wallet_hotkey + else: + wallet = self.wallet_ask( + wallet_name, + wallet_path, + wallet_hotkey, + ask_for=[], + validate=WV.WALLET_AND_HOTKEY, + ) + origin_hotkey = wallet.hotkey.ss58_address if not interactive_selection: - if not origin_netuid: + if origin_netuid is None: origin_netuid = IntPrompt.ask( "Enter the [blue]origin subnet[/blue] (netuid) to move stake from" ) - if not destination_netuid: + if destination_netuid is None: destination_netuid = IntPrompt.ask( "Enter the [blue]destination subnet[/blue] (netuid) to move stake to" ) diff --git a/bittensor_cli/src/bittensor/chain_data.py b/bittensor_cli/src/bittensor/chain_data.py index ef8c59a28..859a2cd6a 100644 --- a/bittensor_cli/src/bittensor/chain_data.py +++ b/bittensor_cli/src/bittensor/chain_data.py @@ -623,6 +623,7 @@ class DynamicInfo(InfoBase): pending_root_emission: Balance network_registered_at: int subnet_identity: Optional[SubnetIdentity] + subnet_volume: Balance @classmethod def _fix_decoded(cls, decoded: Any) -> "DynamicInfo": @@ -646,6 +647,7 @@ def _fix_decoded(cls, decoded: Any) -> "DynamicInfo": alpha_in_emission = Balance.from_rao(decoded.get("alpha_in_emission")).set_unit( netuid ) + subnet_volume = Balance.from_rao(decoded.get("subnet_volume")).set_unit(netuid) tao_in_emission = Balance.from_rao(decoded.get("tao_in_emission")).set_unit(0) pending_alpha_emission = Balance.from_rao( decoded.get("pending_alpha_emission") @@ -689,6 +691,7 @@ def _fix_decoded(cls, decoded: Any) -> "DynamicInfo": pending_root_emission=pending_root_emission, network_registered_at=int(decoded.get("network_registered_at")), subnet_identity=subnet_identity, + subnet_volume=subnet_volume, ) def tao_to_alpha(self, tao: Balance) -> Balance: diff --git a/bittensor_cli/src/commands/stake/stake.py b/bittensor_cli/src/commands/stake/stake.py index 959fc9eb4..2ea5dd8e5 100644 --- a/bittensor_cli/src/commands/stake/stake.py +++ b/bittensor_cli/src/commands/stake/stake.py @@ -1165,6 +1165,7 @@ async def stake_list( subtensor: "SubtensorInterface", live: bool = False, verbose: bool = False, + prompt: bool = False, ): coldkey_address = coldkey_ss58 if coldkey_ss58 else wallet.coldkeypub.ss58_address @@ -1197,8 +1198,9 @@ def define_table( live: bool = False, ): title = f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]Hotkey: {hotkey_name}\nNetwork: {subtensor.network}\n\n" - if not live: - title += f"[{COLOR_PALETTE['GENERAL']['HINT']}]See below for an explanation of the columns\n" + # TODO: Add hint back in after adding columns descriptions + # if not live: + # title += f"[{COLOR_PALETTE['GENERAL']['HINT']}]See below for an explanation of the columns\n" table = Table( title=title, show_footer=True, @@ -1710,7 +1712,7 @@ def format_cell( all_hotkeys_total_global_tao += stake all_hotkeys_total_tao_value += value - if num_hotkeys > 1 and counter < num_hotkeys: + if num_hotkeys > 1 and counter < num_hotkeys and prompt: console.print("\nPress Enter to continue to the next hotkey...") input() diff --git a/bittensor_cli/src/commands/subnets/subnets.py b/bittensor_cli/src/commands/subnets/subnets.py index e5558f360..b68f9892a 100644 --- a/bittensor_cli/src/commands/subnets/subnets.py +++ b/bittensor_cli/src/commands/subnets/subnets.py @@ -981,33 +981,39 @@ async def show_root(): """ ) if delegate_selection: + valid_uids = [str(row[0]) for row in sorted_rows[:max_rows]] while True: selection = Prompt.ask( - "\nEnter the position of the delegate you want to stake to [dim](or press Enter to cancel)[/dim]", + "\nEnter the Position of the delegate you want to stake to [dim](or press Enter to cancel)[/dim]", default="", + choices=[""] + valid_uids, + show_choices=False, + show_default=False, ) if selection == "": return None - try: - idx = int(selection) - if 1 <= idx <= max_rows: - selected_hotkey = sorted_hks_delegation[idx - 1] - row_data = sorted_rows[idx - 1] - identity = "" if row_data[5] == "~" else row_data[5] - identity_str = f" ({identity})" if identity else "" - console.print( - f"\nSelected delegate: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{selected_hotkey}{identity_str}" - ) + position = int(selection) + idx = position - 1 + original_idx = sorted_hotkeys[idx][0] + selected_hotkey = root_state.hotkeys[original_idx] + + coldkey_identity = identities.get( + root_state.coldkeys[original_idx], {} + ).get("name", "") + hotkey_identity = old_identities.get(selected_hotkey) + validator_identity = ( + coldkey_identity + if coldkey_identity + else (hotkey_identity.display if hotkey_identity else "") + ) + identity_str = f" ({validator_identity})" if validator_identity else "" - return selected_hotkey - else: - console.print( - f"[red]Invalid selection. Please enter a number between 1 and {max_rows}[/red]" - ) - except ValueError: - console.print("[red]Please enter a valid number[/red]") + console.print( + f"\nSelected delegate: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{selected_hotkey}{identity_str}" + ) + return selected_hotkey async def show_subnet(netuid_: int): if not await subtensor.subnet_exists(netuid=netuid): @@ -1051,10 +1057,6 @@ async def show_subnet(netuid_: int): pad_edge=True, ) - # Add index for selection if selecting delegates - if delegate_selection: - table.add_column("#", style="cyan", justify="right") - # For hotkey_block_emission calculation emission_sum = sum( [ @@ -1245,8 +1247,6 @@ async def show_subnet(netuid_: int): ) for pos, row in enumerate(rows, 1): table_row = [] - if delegate_selection: - table_row.append(str(pos)) table_row.extend(row) table.add_row(*table_row) if delegate_selection and pos == max_rows: @@ -1299,20 +1299,24 @@ async def show_subnet(netuid_: int): if delegate_selection: while True: + valid_uids = [str(row[0]) for row in rows[:max_rows]] selection = Prompt.ask( - "\nEnter the number of the delegate you want to stake to [dim](or press Enter to cancel)[/dim]", + "\nEnter the UID of the delegate you want to stake to [dim](or press Enter to cancel)[/dim]", default="", + choices=[""] + valid_uids, + show_choices=False, + show_default=False, ) if selection == "": return None try: - idx = int(selection) - if 1 <= idx <= max_rows: - uid = int(rows[idx - 1][0]) + uid = int(selection) + # Check if the UID exists in the subnet + if uid in [int(row[0]) for row in rows]: + row_data = next(row for row in rows if int(row[0]) == uid) hotkey = subnet_state.hotkeys[uid] - row_data = rows[idx - 1] identity = "" if row_data[9] == "~" else row_data[9] identity_str = f" ({identity})" if identity else "" console.print( @@ -1321,7 +1325,7 @@ async def show_subnet(netuid_: int): return hotkey else: console.print( - f"[red]Invalid selection. Please enter a number between 1 and {max_rows}[/red]" + f"[red]Invalid UID. Please enter a valid UID from the table above[/red]" ) except ValueError: console.print("[red]Please enter a valid number[/red]")