diff --git a/bittensor_cli/cli.py b/bittensor_cli/cli.py index d3d490d25..39b401589 100755 --- a/bittensor_cli/cli.py +++ b/bittensor_cli/cli.py @@ -960,6 +960,9 @@ def __init__(self): self.subnets_app.command( "check-start", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"] )(self.subnets_check_start) + self.subnets_app.command( + "set-symbol", rich_help_panel=HELP_PANELS["SUBNETS"]["IDENTITY"] + )(self.subnets_set_symbol) # weights commands self.weights_app.command( @@ -5793,6 +5796,55 @@ def subnets_metagraph( ) ) + def subnets_set_symbol( + self, + wallet_name: str = Options.wallet_name, + wallet_path: str = Options.wallet_path, + wallet_hotkey: str = Options.wallet_hotkey, + network: Optional[list[str]] = Options.network, + netuid: int = Options.netuid, + json_output: bool = Options.json_output, + prompt: bool = Options.prompt, + quiet: bool = Options.quiet, + verbose: bool = Options.verbose, + symbol: str = typer.Argument(help="The symbol to set for your subnet."), + ): + """ + Allows the user to update their subnet symbol to a different available symbol. The full list of available symbols can be found here: + [#8CB9E9]https://github.com/opentensor/subtensor/blob/main/pallets/subtensor/src/subnets/symbols.rs#L8[/#8CB9E9] + + + EXAMPLE + + [green]$[/green] btcli subnets set-symbol [dark_orange]--netuid 1 シ[/dark_orange] + + + JSON OUTPUT: + If --json-output is used, the output will be in the following schema: + [#AFEFFF]{success: [dark_orange]bool[/dark_orange], message: [dark_orange]str[/dark_orange]}[/#AFEFFF] + """ + self.verbosity_handler(quiet, verbose, json_output) + if len(symbol) > 1: + err_console.print("Your symbol must be a single character.") + return False + wallet = self.wallet_ask( + wallet_name, + wallet_path, + wallet_hotkey, + ask_for=[WO.NAME, WO.HOTKEY], + validate=WV.WALLET_AND_HOTKEY, + ) + return self._run_command( + subnets.set_symbol( + wallet=wallet, + subtensor=self.initialize_chain(network), + netuid=netuid, + symbol=symbol, + prompt=prompt, + json_output=json_output, + ) + ) + def weights_reveal( self, network: Optional[list[str]] = Options.network, diff --git a/bittensor_cli/src/commands/subnets/subnets.py b/bittensor_cli/src/commands/subnets/subnets.py index bb42132c9..d8571f3f6 100644 --- a/bittensor_cli/src/commands/subnets/subnets.py +++ b/bittensor_cli/src/commands/subnets/subnets.py @@ -2448,3 +2448,71 @@ async def start_subnet( await get_start_schedule(subtensor, netuid) print_error(f":cross_mark: Failed to start subnet: {error_msg}") return False + + +async def set_symbol( + wallet: "Wallet", + subtensor: "SubtensorInterface", + netuid: int, + symbol: str, + prompt: bool = False, + json_output: bool = False, +) -> bool: + """ + Set a subtensor's symbol, given the netuid and symbol. + + The symbol must be a symbol that subtensor recognizes as available + (defined in https://github.com/opentensor/subtensor/blob/main/pallets/subtensor/src/subnets/symbols.rs#L8) + """ + if not await subtensor.subnet_exists(netuid): + err = f"Subnet {netuid} does not exist." + if json_output: + json_console.print_json(data={"success": False, "message": err}) + else: + err_console.print(err) + return False + + if prompt and not json_output: + sn_info = await subtensor.subnet(netuid=netuid) + if not Confirm.ask( + f"Your current subnet symbol for SN{netuid} is {sn_info.symbol}. Do you want to update it to {symbol}?" + ): + return False + + if not (unlock_status := unlock_key(wallet, print_out=False)).success: + err = unlock_status.message + if json_output: + json_console.print_json(data={"success": False, "message": err}) + else: + console.print(err) + return False + + start_call = await subtensor.substrate.compose_call( + call_module="SubtensorModule", + call_function="update_symbol", + call_params={"netuid": netuid, "symbol": symbol.encode("utf-8")}, + ) + + signed_ext = await subtensor.substrate.create_signed_extrinsic( + call=start_call, + keypair=wallet.coldkey, + ) + + response = await subtensor.substrate.submit_extrinsic( + extrinsic=signed_ext, + wait_for_inclusion=True, + ) + if await response.is_success: + message = f"Successfully updated SN{netuid}'s symbol to {symbol}." + if json_output: + json_console.print_json(data={"success": True, "message": message}) + else: + console.print(f":white_heavy_check_mark:[dark_sea_green3] {message}\n") + return True + else: + err = format_error_message(await response.error_message) + if json_output: + json_console.print_json(data={"success": False, "message": err}) + else: + err_console.print(f":cross_mark: [red]Failed[/red]: {err}") + return False diff --git a/tests/e2e_tests/test_staking_sudo.py b/tests/e2e_tests/test_staking_sudo.py index cd4bf09c3..359fbb508 100644 --- a/tests/e2e_tests/test_staking_sudo.py +++ b/tests/e2e_tests/test_staking_sudo.py @@ -10,6 +10,7 @@ * btcli subnets create * btcli subnets set-identity * btcli subnets get-identity +* btcli subnets set-symbol * btcli subnets register * btcli subnets price * btcli stake add @@ -235,6 +236,34 @@ def test_staking(local_chain, wallet_setup): assert get_identity_output["logo_url"] == sn_logo_url assert get_identity_output["additional"] == sn_add_info + # set symbol + set_symbol = exec_command_alice( + "subnets", + "set-symbol", + extra_args=[ + "--wallet-path", + wallet_path_alice, + "--wallet-name", + wallet_alice.name, + "--hotkey", + wallet_alice.hotkey_str, + "--chain", + "ws://127.0.0.1:9945", + "--netuid", + netuid, + "--json-output", + "--no-prompt", + "シ", + ], + ) + set_symbol_output = json.loads(set_symbol.stdout) + assert set_symbol_output["success"] is True, set_symbol_output + assert set_symbol_output["success"] is True, set_symbol_output + assert ( + set_symbol_output["message"] + == f"Successfully updated SN{netuid}'s symbol to シ." + ) + get_s_price = exec_command_alice( "subnets", "price",