Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## 9.0.1 /2025-02-13

## What's Changed
* Fixes root tempo being 0 by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/312
* Backmerge main to staging 900 by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/313
* Fixes fmt err msg by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/314
* Adds subnet identities set/get by @ibraheem-opentensor in https://github.com/opentensor/btcli/pull/316
* Fix return type annotation for `alpha_to_tao_with_slippage` by @thewhaleking in https://github.com/opentensor/btcli/pull/311
* Updates live view of btcli stake list

**Full Changelog**: https://github.com/opentensor/btcli/compare/v9.0.0...v9.0.1

## 9.0.0 /2025-02-13

## What's Changed
Expand Down
2 changes: 1 addition & 1 deletion bittensor_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
from .cli import CLIManager


__version__ = "9.0.0"
__version__ = "9.0.1"

__all__ = ["CLIManager", "__version__"]
123 changes: 121 additions & 2 deletions bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class GitError(Exception):
pass


__version__ = "9.0.0"
__version__ = "9.0.1"


_core_version = re.match(r"^\d+\.\d+\.\d+", __version__).group(0)
Expand Down Expand Up @@ -656,7 +656,7 @@ def __init__(self):
self.config_app.command("set")(self.set_config)
self.config_app.command("get")(self.get_config)
self.config_app.command("clear")(self.del_config)
self.config_app.command("metagraph", hidden=True)(self.metagraph_config)
# self.config_app.command("metagraph", hidden=True)(self.metagraph_config)

# wallet commands
self.wallet_app.command(
Expand Down Expand Up @@ -804,6 +804,12 @@ def __init__(self):
self.subnets_app.command(
"price", rich_help_panel=HELP_PANELS["SUBNETS"]["INFO"]
)(self.subnets_price)
self.subnets_app.command(
"set-identity", rich_help_panel=HELP_PANELS["SUBNETS"]["IDENTITY"]
)(self.subnets_set_identity)
self.subnets_app.command(
"get-identity", rich_help_panel=HELP_PANELS["SUBNETS"]["IDENTITY"]
)(self.subnets_get_identity)

# weights commands
self.weights_app.command(
Expand Down Expand Up @@ -4452,6 +4458,7 @@ def subnets_create(
validate=WV.WALLET_AND_HOTKEY,
)
identity = prompt_for_subnet_identity(
current_identity={},
subnet_name=subnet_name,
github_repo=github_repo,
subnet_contact=subnet_contact,
Expand Down Expand Up @@ -4482,6 +4489,118 @@ def subnets_create(
verbose=verbose,
)

def subnets_get_identity(
self,
network: Optional[list[str]] = Options.network,
netuid: int = Options.netuid,
quiet: bool = Options.quiet,
verbose: bool = Options.verbose,
):
"""
Get the identity information for a subnet.

This command displays the identity information of a subnet including name, GitHub repo, contact details, etc.

[green]$[/green] btcli subnets get-identity --netuid 1
"""
self.verbosity_handler(quiet, verbose)
return self._run_command(
subnets.get_identity(
self.initialize_chain(network),
netuid,
)
)

def subnets_set_identity(
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,
subnet_name: Optional[str] = typer.Option(
None, "--subnet-name", "--name", help="Name of the subnet"
),
github_repo: Optional[str] = typer.Option(
None, "--github-repo", "--repo", help="GitHub repository URL"
),
subnet_contact: Optional[str] = typer.Option(
None,
"--subnet-contact",
"--contact",
"--email",
help="Contact email for subnet",
),
subnet_url: Optional[str] = typer.Option(
None, "--subnet-url", "--url", help="Subnet URL"
),
discord: Optional[str] = typer.Option(
None, "--discord-handle", "--discord", help="Discord handle"
),
description: Optional[str] = typer.Option(
None, "--description", help="Description"
),
additional_info: Optional[str] = typer.Option(
None, "--additional-info", help="Additional information"
),
prompt: bool = Options.prompt,
quiet: bool = Options.quiet,
verbose: bool = Options.verbose,
):
"""
Set or update the identity information for a subnet.

This command allows subnet owners to set or update identity information like name, GitHub repo, contact details, etc.

[bold]Common Examples:[/bold]

1. Interactive subnet identity setting:
[green]$[/green] btcli subnets set-identity --netuid 1

2. Set subnet identity with specific values:
[green]$[/green] btcli subnets set-identity --netuid 1 --subnet-name MySubnet --github-repo https://github.com/myorg/mysubnet --subnet-contact team@mysubnet.net
"""
self.verbosity_handler(quiet, verbose)
wallet = self.wallet_ask(
wallet_name,
wallet_path,
wallet_hotkey,
ask_for=[WO.NAME],
validate=WV.WALLET,
)

current_identity = self._run_command(
subnets.get_identity(
self.initialize_chain(network),
netuid,
f"Current Subnet {netuid}'s Identity",
),
exit_early=False,
)
if current_identity is None:
raise typer.Exit()

identity = prompt_for_subnet_identity(
current_identity=current_identity,
subnet_name=subnet_name,
github_repo=github_repo,
subnet_contact=subnet_contact,
subnet_url=subnet_url,
discord=discord,
description=description,
additional=additional_info,
)

return self._run_command(
subnets.set_identity(
wallet,
self.initialize_chain(network),
netuid,
identity,
prompt,
)
)

def subnets_pow_register(
self,
wallet_name: Optional[str] = Options.wallet_name,
Expand Down
3 changes: 2 additions & 1 deletion bittensor_cli/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Constants:
subvortex_entrypoint = "ws://subvortex.info:9944"
local_entrypoint = "ws://127.0.0.1:9944"
rao_entrypoint = "wss://rao.chain.opentensor.ai:443"
dev_entrypoint = "wss://dev.chain.opentensor.ai:443 "
dev_entrypoint = "wss://dev.chain.opentensor.ai:443"
local_entrypoint = "ws://127.0.0.1:9944"
latent_lite_entrypoint = "wss://lite.sub.latent.to:443"
network_map = {
Expand Down Expand Up @@ -710,6 +710,7 @@ class WalletValidationTypes(Enum):
"INFO": "Subnet Information",
"CREATION": "Subnet Creation & Management",
"REGISTER": "Neuron Registration",
"IDENTITY": "Subnet Identity Management",
},
"WEIGHTS": {"COMMIT_REVEAL": "Commit / Reveal"},
}
Expand Down
4 changes: 3 additions & 1 deletion bittensor_cli/src/bittensor/chain_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,9 @@ def tao_to_alpha_with_slippage(self, tao: Balance) -> tuple[Balance, Balance]:
)
return alpha_returned, slippage, slippage_pct_float

def alpha_to_tao_with_slippage(self, alpha: Balance) -> tuple[Balance, Balance]:
def alpha_to_tao_with_slippage(
self, alpha: Balance
) -> tuple[Balance, Balance, float]:
"""
Returns an estimate of how much TAO would a staker receive if they unstake their alpha using the current pool state.
Args:
Expand Down
3 changes: 2 additions & 1 deletion bittensor_cli/src/bittensor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ def prompt_for_identity(


def prompt_for_subnet_identity(
current_identity: dict,
subnet_name: Optional[str],
github_repo: Optional[str],
subnet_contact: Optional[str],
Expand Down Expand Up @@ -1210,7 +1211,7 @@ def prompt_for_subnet_identity(
prompt,
rejection=rejection_func,
rejection_text=rejection_msg,
default=None, # Maybe we can add some defaults later
default=current_identity.get(key, ""),
show_default=True,
)

Expand Down
4 changes: 2 additions & 2 deletions bittensor_cli/src/commands/stake/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ async def safe_stake_extrinsic(
await response.process_events()
if not await response.is_success:
err_out(
f"\n{failure_prelude} with error: {format_error_message(await response.error_message, subtensor.substrate)}"
f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
)
else:
block_hash = await subtensor.substrate.get_chain_head()
Expand Down Expand Up @@ -188,7 +188,7 @@ async def stake_extrinsic(
await response.process_events()
if not await response.is_success:
err_out(
f"\n{failure_prelude} with error: {format_error_message(await response.error_message, subtensor.substrate)}"
f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
)
else:
new_balance, new_stake = await asyncio.gather(
Expand Down
24 changes: 8 additions & 16 deletions bittensor_cli/src/commands/stake/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async def get_stake_data(block_hash: str = None):
coldkey_ss58=coldkey_address, block_hash=block_hash
),
subtensor.get_delegate_identities(block_hash=block_hash),
subtensor.all_subnets(),
subtensor.all_subnets(block_hash=block_hash),
)
# sub_stakes = substakes[coldkey_address]
dynamic_info = {info.netuid: info for info in _dynamic_info}
Expand Down Expand Up @@ -199,7 +199,7 @@ def create_table(hotkey_: str, substakes: list[StakeInfo]):
issuance = pool.alpha_out if pool.is_dynamic else tao_locked

# Per block emission cell
per_block_emission = substake_.emission.tao / pool.tempo
per_block_emission = substake_.emission.tao / (pool.tempo or 1)
# Alpha ownership and TAO ownership cells
if alpha_value.tao > 0.00009:
if issuance.tao != 0:
Expand Down Expand Up @@ -319,7 +319,7 @@ def format_cell(
alpha_value = Balance.from_rao(int(substake.stake.rao)).set_unit(netuid)
tao_value = pool.alpha_to_tao(alpha_value)
total_tao_value += tao_value
swapped_tao_value, slippage = pool.alpha_to_tao_with_slippage(
swapped_tao_value, slippage, slippage_pct = pool.alpha_to_tao_with_slippage(
substake.stake
)
total_swapped_tao_value += swapped_tao_value
Expand All @@ -341,7 +341,7 @@ def format_cell(
"price": pool.price.tao,
"tao_value": tao_value.tao,
"swapped_value": swapped_tao_value.tao,
"emission": substake.emission.tao / pool.tempo,
"emission": substake.emission.tao / (pool.tempo or 1),
"tao_ownership": tao_ownership.tao,
}

Expand Down Expand Up @@ -376,15 +376,6 @@ def format_cell(
millify=True if not verbose else False,
)

if pool.is_dynamic:
slippage_pct = (
100 * float(slippage) / float(slippage + swapped_tao_value)
if slippage + swapped_tao_value != 0
else 0
)
else:
slippage_pct = 0

if netuid != 0:
swap_cell = (
format_cell(
Expand All @@ -400,7 +391,7 @@ def format_cell(
else:
swap_cell = f"[{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}]N/A[/{COLOR_PALETTE['STAKE']['NOT_REGISTERED']}] ({slippage_pct}%)"

emission_value = substake.emission.tao / pool.tempo
emission_value = substake.emission.tao / (pool.tempo or 1)
emission_cell = format_cell(
emission_value,
prev.get("emission"),
Expand Down Expand Up @@ -443,11 +434,12 @@ def format_cell(
return table, current_data

# Main execution
block_hash = await subtensor.substrate.get_chain_head()
(
sub_stakes,
registered_delegate_info,
dynamic_info,
) = await get_stake_data()
) = await get_stake_data(block_hash)
balance = await subtensor.get_balance(coldkey_address)

# Iterate over substakes and aggregate them by hotkey.
Expand Down Expand Up @@ -536,7 +528,7 @@ def format_cell(
table, current_data = create_live_table(
selected_stakes,
registered_delegate_info,
dynamic_info,
dynamic_info_,
hotkey_name,
previous_data,
)
Expand Down
4 changes: 2 additions & 2 deletions bittensor_cli/src/commands/stake/move.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ async def transfer_stake(
if not await response.is_success:
err_console.print(
f":cross_mark: [red]Failed[/red] with error: "
f"{format_error_message(await response.error_message, subtensor.substrate)}"
f"{format_error_message(await response.error_message)}"
)
return False

Expand Down Expand Up @@ -971,7 +971,7 @@ async def swap_stake(
if not await response.is_success:
err_console.print(
f":cross_mark: [red]Failed[/red] with error: "
f"{format_error_message(await response.error_message, subtensor.substrate)}"
f"{format_error_message(await response.error_message)}"
)
return False

Expand Down
4 changes: 2 additions & 2 deletions bittensor_cli/src/commands/stake/remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ async def _unstake_extrinsic(
if not await response.is_success:
err_out(
f"{failure_prelude} with error: "
f"{format_error_message(await response.error_message, subtensor.substrate)}"
f"{format_error_message(await response.error_message)}"
)
return

Expand Down Expand Up @@ -674,7 +674,7 @@ async def _safe_unstake_extrinsic(
await response.process_events()
if not await response.is_success:
err_out(
f"\n{failure_prelude} with error: {format_error_message(await response.error_message, subtensor.substrate)}"
f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
)
return

Expand Down
Loading
Loading