From 64405fdd1e2d1092a6c16651f20eca8a16724c0c Mon Sep 17 00:00:00 2001 From: bdhimes Date: Fri, 19 Sep 2025 15:19:46 +0200 Subject: [PATCH 1/4] Update changelog+version --- CHANGELOG.md | 5 +++++ pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56ea625bc..27b5ca54b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 9.11.2 /2025-09-19 +* Fix: Stake movement between non-root sns by @ibraheem-abe in https://github.com/opentensor/btcli/pull/629 + +**Full Changelog**: https://github.com/opentensor/btcli/compare/v9.11.1...v9.11.2 + ## 9.11.1 /2025-09-16 * Transfer not staking warning by @thewhaleking in https://github.com/opentensor/btcli/pull/618 diff --git a/pyproject.toml b/pyproject.toml index 56814fe27..b7c11b579 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "bittensor-cli" -version = "9.11.1" +version = "9.11.2" description = "Bittensor CLI" readme = "README.md" authors = [ From b9d8cd325905f950903d1fbe7b831d5a04207ae2 Mon Sep 17 00:00:00 2001 From: bdhimes Date: Fri, 19 Sep 2025 15:22:11 +0200 Subject: [PATCH 2/4] Revert "Merge pull request #628 from opentensor/feat/thewhaleking/trim-uids" This reverts commit dd051a3cf8645ef7b315569c30ad97a47fbdc997, reversing changes made to aad303e1364cdabcf607883b279da842632f3620. --- bittensor_cli/cli.py | 50 ------------------ bittensor_cli/src/__init__.py | 1 - bittensor_cli/src/commands/sudo.py | 56 --------------------- tests/e2e_tests/test_hyperparams_setting.py | 49 ------------------ 4 files changed, 156 deletions(-) diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 4484f5288..88ae40580 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -960,9 +960,6 @@ def __init__(self): self.sudo_app.command("get-take", rich_help_panel=HELP_PANELS["SUDO"]["TAKE"])( self.sudo_get_take ) - self.sudo_app.command("trim", rich_help_panel=HELP_PANELS["SUDO"]["CONFIG"])( - self.sudo_trim - ) # subnets commands self.subnets_app.command( @@ -5346,53 +5343,6 @@ def sudo_get_take( sudo.display_current_take(self.initialize_chain(network), wallet) ) - def sudo_trim( - self, - network: Optional[list[str]] = Options.network, - wallet_name: Optional[str] = Options.wallet_name, - wallet_path: Optional[str] = Options.wallet_path, - wallet_hotkey: Optional[str] = Options.wallet_hotkey, - netuid: int = Options.netuid, - max_uids: int = typer.Option( - None, - "--max", - "--max-uids", - help="The maximum number of allowed uids to which to trim", - prompt="Max UIDs", - ), - quiet: bool = Options.quiet, - verbose: bool = Options.verbose, - json_output: bool = Options.json_output, - prompt: bool = Options.prompt, - period: int = Options.period, - ): - """ - Allows subnet owners to trim UIDs on their subnet to a specified max number of netuids. - - EXAMPLE - [green]$[/green] btcli sudo trim --netuid 95 --wallet-name my_wallet --wallet-hotkey my_hotkey --max 6 - """ - self.verbosity_handler(quiet, verbose, json_output) - - wallet = self.wallet_ask( - wallet_name, - wallet_path, - wallet_hotkey, - ask_for=[WO.NAME, WO.PATH], - validate=WV.WALLET, - ) - self._run_command( - sudo.trim( - subtensor=self.initialize_chain(network), - wallet=wallet, - netuid=netuid, - max_n=max_uids, - period=period, - json_output=json_output, - prompt=prompt, - ) - ) - def subnets_list( self, network: Optional[list[str]] = Options.network, diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index 6ee781a46..ba96fe488 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -666,7 +666,6 @@ class WalletValidationTypes(Enum): "user_liquidity_enabled": ("toggle_user_liquidity", False), "bonds_reset_enabled": ("sudo_set_bonds_reset_enabled", False), "transfers_enabled": ("sudo_set_toggle_transfer", False), - "min_allowed_uids": ("sudo_set_min_allowed_uids", True), } HYPERPARAMS_MODULE = { diff --git a/bittensor_cli/src/commands/sudo.py b/bittensor_cli/src/commands/sudo.py index bb4bb43de..e6ac31185 100644 --- a/bittensor_cli/src/commands/sudo.py +++ b/bittensor_cli/src/commands/sudo.py @@ -955,59 +955,3 @@ async def _do_set_take() -> bool: result_ = await _do_set_take() return result_ - - -async def trim( - wallet: Wallet, - subtensor: "SubtensorInterface", - netuid: int, - max_n: int, - period: int, - prompt: bool, - json_output: bool, -) -> bool: - """ - Trims a subnet's UIDs to a specified amount - """ - print_verbose("Confirming subnet owner") - subnet_owner = await subtensor.query( - module="SubtensorModule", - storage_function="SubnetOwner", - params=[netuid], - ) - if subnet_owner != wallet.coldkeypub.ss58_address: - err_msg = "This wallet doesn't own the specified subnet." - if json_output: - json_console.print_json(data={"success": False, "message": err_msg}) - else: - err_console.print(f":cross_mark: [red]{err_msg}[/red]") - return False - if prompt and not json_output: - if not Confirm.ask( - f"You are about to trim UIDs on SN{netuid} to a limit of {max_n}", - default=False, - ): - err_console.print(":cross_mark: [red]User aborted.[/red]") - call = await subtensor.substrate.compose_call( - call_module="AdminUtils", - call_function="sudo_trim_to_max_allowed_uids", - call_params={"netuid": netuid, "max_n": max_n}, - ) - success, err_msg = await subtensor.sign_and_send_extrinsic( - call=call, wallet=wallet, era={"period": period} - ) - if not success: - if json_output: - json_console.print_json(data={"success": False, "message": err_msg}) - else: - err_console.print(f":cross_mark: [red]{err_msg}[/red]") - return False - else: - msg = f"Successfully trimmed UIDs on SN{netuid} to {max_n}" - if json_output: - json_console.print_json(data={"success": True, "message": msg}) - else: - console.print( - f":white_heavy_check_mark: [dark_sea_green3]{msg}[/dark_sea_green3]" - ) - return True diff --git a/tests/e2e_tests/test_hyperparams_setting.py b/tests/e2e_tests/test_hyperparams_setting.py index 916b00cac..3af86c140 100644 --- a/tests/e2e_tests/test_hyperparams_setting.py +++ b/tests/e2e_tests/test_hyperparams_setting.py @@ -120,53 +120,4 @@ def test_hyperparams_setting(local_chain, wallet_setup): cmd_json = json.loads(cmd.stdout) assert cmd_json["success"] is True, (key, new_val, cmd.stdout, cmd_json) print(f"Successfully set hyperparameter {key} to value {new_val}") - # also test hidden hyperparam - cmd = exec_command_alice( - command="sudo", - sub_command="set", - extra_args=[ - "--wallet-path", - wallet_path_alice, - "--network", - "ws://127.0.0.1:9945", - "--wallet-name", - wallet_alice.name, - "--wallet-hotkey", - wallet_alice.hotkey_str, - "--netuid", - netuid, - "--json-out", - "--no-prompt", - "--param", - "min_allowed_uids", - "--value", - "110", - ], - ) - cmd_json = json.loads(cmd.stdout) - assert cmd_json["success"] is True, (cmd.stdout, cmd_json) print("Successfully set hyperparameters") - print("Testing trimming UIDs") - cmd = exec_command_alice( - command="sudo", - sub_command="trim", - extra_args=[ - "--wallet-path", - wallet_path_alice, - "--network", - "ws://127.0.0.1:9945", - "--wallet-name", - wallet_alice.name, - "--wallet-hotkey", - wallet_alice.hotkey_str, - "--netuid", - netuid, - "--max", - "120", - "--json-out", - "--no-prompt", - ], - ) - cmd_json = json.loads(cmd.stdout) - assert cmd_json["success"] is True, (cmd.stdout, cmd_json) - print("Successfully trimmed UIDs") From 036e4a06a21d95d53893203da7de78938d3937ed Mon Sep 17 00:00:00 2001 From: bdhimes Date: Fri, 19 Sep 2025 15:42:25 +0200 Subject: [PATCH 3/4] Fix test by making user_liquidity_enabled root sudo only --- bittensor_cli/src/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index ba96fe488..f93aed504 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -663,7 +663,7 @@ class WalletValidationTypes(Enum): ), "yuma3_enabled": ("sudo_set_yuma3_enabled", False), "alpha_sigmoid_steepness": ("sudo_set_alpha_sigmoid_steepness", True), - "user_liquidity_enabled": ("toggle_user_liquidity", False), + "user_liquidity_enabled": ("toggle_user_liquidity", True), "bonds_reset_enabled": ("sudo_set_bonds_reset_enabled", False), "transfers_enabled": ("sudo_set_toggle_transfer", False), } From 3c075ebff4896d0d8cab587f5f229c38818ded0e Mon Sep 17 00:00:00 2001 From: bdhimes Date: Fri, 19 Sep 2025 15:54:40 +0200 Subject: [PATCH 4/4] Revert "Revert "Merge pull request #628 from opentensor/feat/thewhaleking/trim-uids"" This reverts commit b9d8cd325905f950903d1fbe7b831d5a04207ae2. --- bittensor_cli/cli.py | 50 ++++++++++++++++++ bittensor_cli/src/__init__.py | 1 + bittensor_cli/src/commands/sudo.py | 56 +++++++++++++++++++++ tests/e2e_tests/test_hyperparams_setting.py | 49 ++++++++++++++++++ 4 files changed, 156 insertions(+) diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index 88ae40580..4484f5288 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -960,6 +960,9 @@ def __init__(self): self.sudo_app.command("get-take", rich_help_panel=HELP_PANELS["SUDO"]["TAKE"])( self.sudo_get_take ) + self.sudo_app.command("trim", rich_help_panel=HELP_PANELS["SUDO"]["CONFIG"])( + self.sudo_trim + ) # subnets commands self.subnets_app.command( @@ -5343,6 +5346,53 @@ def sudo_get_take( sudo.display_current_take(self.initialize_chain(network), wallet) ) + def sudo_trim( + self, + network: Optional[list[str]] = Options.network, + wallet_name: Optional[str] = Options.wallet_name, + wallet_path: Optional[str] = Options.wallet_path, + wallet_hotkey: Optional[str] = Options.wallet_hotkey, + netuid: int = Options.netuid, + max_uids: int = typer.Option( + None, + "--max", + "--max-uids", + help="The maximum number of allowed uids to which to trim", + prompt="Max UIDs", + ), + quiet: bool = Options.quiet, + verbose: bool = Options.verbose, + json_output: bool = Options.json_output, + prompt: bool = Options.prompt, + period: int = Options.period, + ): + """ + Allows subnet owners to trim UIDs on their subnet to a specified max number of netuids. + + EXAMPLE + [green]$[/green] btcli sudo trim --netuid 95 --wallet-name my_wallet --wallet-hotkey my_hotkey --max 6 + """ + self.verbosity_handler(quiet, verbose, json_output) + + wallet = self.wallet_ask( + wallet_name, + wallet_path, + wallet_hotkey, + ask_for=[WO.NAME, WO.PATH], + validate=WV.WALLET, + ) + self._run_command( + sudo.trim( + subtensor=self.initialize_chain(network), + wallet=wallet, + netuid=netuid, + max_n=max_uids, + period=period, + json_output=json_output, + prompt=prompt, + ) + ) + def subnets_list( self, network: Optional[list[str]] = Options.network, diff --git a/bittensor_cli/src/__init__.py b/bittensor_cli/src/__init__.py index f93aed504..111cd0d8f 100644 --- a/bittensor_cli/src/__init__.py +++ b/bittensor_cli/src/__init__.py @@ -666,6 +666,7 @@ class WalletValidationTypes(Enum): "user_liquidity_enabled": ("toggle_user_liquidity", True), "bonds_reset_enabled": ("sudo_set_bonds_reset_enabled", False), "transfers_enabled": ("sudo_set_toggle_transfer", False), + "min_allowed_uids": ("sudo_set_min_allowed_uids", True), } HYPERPARAMS_MODULE = { diff --git a/bittensor_cli/src/commands/sudo.py b/bittensor_cli/src/commands/sudo.py index e6ac31185..bb4bb43de 100644 --- a/bittensor_cli/src/commands/sudo.py +++ b/bittensor_cli/src/commands/sudo.py @@ -955,3 +955,59 @@ async def _do_set_take() -> bool: result_ = await _do_set_take() return result_ + + +async def trim( + wallet: Wallet, + subtensor: "SubtensorInterface", + netuid: int, + max_n: int, + period: int, + prompt: bool, + json_output: bool, +) -> bool: + """ + Trims a subnet's UIDs to a specified amount + """ + print_verbose("Confirming subnet owner") + subnet_owner = await subtensor.query( + module="SubtensorModule", + storage_function="SubnetOwner", + params=[netuid], + ) + if subnet_owner != wallet.coldkeypub.ss58_address: + err_msg = "This wallet doesn't own the specified subnet." + if json_output: + json_console.print_json(data={"success": False, "message": err_msg}) + else: + err_console.print(f":cross_mark: [red]{err_msg}[/red]") + return False + if prompt and not json_output: + if not Confirm.ask( + f"You are about to trim UIDs on SN{netuid} to a limit of {max_n}", + default=False, + ): + err_console.print(":cross_mark: [red]User aborted.[/red]") + call = await subtensor.substrate.compose_call( + call_module="AdminUtils", + call_function="sudo_trim_to_max_allowed_uids", + call_params={"netuid": netuid, "max_n": max_n}, + ) + success, err_msg = await subtensor.sign_and_send_extrinsic( + call=call, wallet=wallet, era={"period": period} + ) + if not success: + if json_output: + json_console.print_json(data={"success": False, "message": err_msg}) + else: + err_console.print(f":cross_mark: [red]{err_msg}[/red]") + return False + else: + msg = f"Successfully trimmed UIDs on SN{netuid} to {max_n}" + if json_output: + json_console.print_json(data={"success": True, "message": msg}) + else: + console.print( + f":white_heavy_check_mark: [dark_sea_green3]{msg}[/dark_sea_green3]" + ) + return True diff --git a/tests/e2e_tests/test_hyperparams_setting.py b/tests/e2e_tests/test_hyperparams_setting.py index 3af86c140..916b00cac 100644 --- a/tests/e2e_tests/test_hyperparams_setting.py +++ b/tests/e2e_tests/test_hyperparams_setting.py @@ -120,4 +120,53 @@ def test_hyperparams_setting(local_chain, wallet_setup): cmd_json = json.loads(cmd.stdout) assert cmd_json["success"] is True, (key, new_val, cmd.stdout, cmd_json) print(f"Successfully set hyperparameter {key} to value {new_val}") + # also test hidden hyperparam + cmd = exec_command_alice( + command="sudo", + sub_command="set", + extra_args=[ + "--wallet-path", + wallet_path_alice, + "--network", + "ws://127.0.0.1:9945", + "--wallet-name", + wallet_alice.name, + "--wallet-hotkey", + wallet_alice.hotkey_str, + "--netuid", + netuid, + "--json-out", + "--no-prompt", + "--param", + "min_allowed_uids", + "--value", + "110", + ], + ) + cmd_json = json.loads(cmd.stdout) + assert cmd_json["success"] is True, (cmd.stdout, cmd_json) print("Successfully set hyperparameters") + print("Testing trimming UIDs") + cmd = exec_command_alice( + command="sudo", + sub_command="trim", + extra_args=[ + "--wallet-path", + wallet_path_alice, + "--network", + "ws://127.0.0.1:9945", + "--wallet-name", + wallet_alice.name, + "--wallet-hotkey", + wallet_alice.hotkey_str, + "--netuid", + netuid, + "--max", + "120", + "--json-out", + "--no-prompt", + ], + ) + cmd_json = json.loads(cmd.stdout) + assert cmd_json["success"] is True, (cmd.stdout, cmd_json) + print("Successfully trimmed UIDs")