Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
dafca70
fix missing classifiers
branchv Nov 5, 2025
2f75af0
migrate to flit
branchv Nov 5, 2025
c682f39
Merge pull request #698 from branchvincent/classifiers
thewhaleking Nov 7, 2025
ea2afea
Removes subvortex as the project is gone.
thewhaleking Nov 10, 2025
64c2cbf
Merge pull request #708 from opentensor/chore/thewhaleking/remove-sub…
thewhaleking Nov 10, 2025
de8d68d
Fix table width visual bug in stake move command
BANADDA Nov 15, 2025
7d8a7a2
Fix typos in some files
namkhanh20xx Nov 15, 2025
2bb11b1
Add type annotations, fix possible type errors
thewhaleking Nov 17, 2025
fe1be23
Use genesis address to verify not hotkey
thewhaleking Nov 17, 2025
61aa92e
Ruff
thewhaleking Nov 17, 2025
76189b3
Name shadowing
thewhaleking Nov 17, 2025
f0f7d4d
Be more clear about the display of the totals in `st list`
thewhaleking Nov 17, 2025
1807354
Turn off auto shutdown timer as we explicitly close the ws connection…
thewhaleking Nov 17, 2025
757db79
Merge pull request #712 from opentensor/fix/thewhaleking/2025-11-17-f…
thewhaleking Nov 17, 2025
1062771
Merge pull request #711 from Edge-Seven/Fix/typos/20251115100029
thewhaleking Nov 17, 2025
3af090a
Merge branch 'staging' into fix-stake-move-table-width
thewhaleking Nov 17, 2025
3beed72
Ruff
thewhaleking Nov 17, 2025
059d8b4
Merge pull request #709 from BANADDA/fix-stake-move-table-width
thewhaleking Nov 17, 2025
051716d
Changelog + version
thewhaleking Nov 17, 2025
34ea4d1
decode acc id
ibraheem-abe Nov 17, 2025
a1143a0
Merge pull request #713 from opentensor/changelog/9.15.3
thewhaleking Nov 17, 2025
7e586d9
Merge pull request #714 from opentensor/fix/single-swap-check
thewhaleking Nov 17, 2025
8a9bd98
Update changelog
thewhaleking Nov 17, 2025
aee16d1
Merge pull request #716 from opentensor/changelog/9.15.3-updated
thewhaleking Nov 17, 2025
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
7 changes: 0 additions & 7 deletions .github/workflows/e2e-subtensor-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ jobs:
with:
python-version: 3.13

- name: install dependencies
run: |
uv venv .venv
source .venv/bin/activate
uv pip install .[dev]

- name: Download Cached Docker Image
uses: actions/download-artifact@v4
with:
Expand All @@ -100,5 +94,4 @@ jobs:

- name: Run tests
run: |
source .venv/bin/activate
uv run pytest ${{ matrix.test-file }} -s
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Changelog

## 9.15.3 /2025-11-17

## What's Changed
* fix missing classifiers, migrate to flit by @branchvincent in https://github.com/opentensor/btcli/pull/698
* Removes subvortex as the project is gone. by @thewhaleking in https://github.com/opentensor/btcli/pull/708
* Small Bug Fixes by @thewhaleking in https://github.com/opentensor/btcli/pull/712:
* Ensures that net_claimable is always a Balance object in get_claimable_stakes_for_coldkey
* Checks that the HK owner isn't the genesis address
* Clearly show the totals in st list as representing staked vs total incl free
* Prevents a race condition which could freeze the console for extrinsic submission
* docs: fix typos in some files by @Edge-Seven in https://github.com/opentensor/btcli/pull/711
* Fix table width visual bug in stake move command by @BANADDA in https://github.com/opentensor/btcli/pull/709
* Fix: Decode account id in `btcli swap-check` by @ibraheem-abe in https://github.com/opentensor/btcli/pull/714

## New Contributors
* @branchvincent made their first contribution in https://github.com/opentensor/btcli/pull/698
* @Edge-Seven made their first contribution in https://github.com/opentensor/btcli/pull/711
* @BANADDA made their first contribution in https://github.com/opentensor/btcli/pull/709

**Full Changelog**: https://github.com/opentensor/btcli/compare/v9.15.2...v9.15.3

## 9.15.2 /2025-11-05

## What's Changed
Expand Down
1 change: 0 additions & 1 deletion MANIFEST.in

This file was deleted.

2 changes: 1 addition & 1 deletion bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6135,7 +6135,7 @@ def subnets_price(
self.verbosity_handler(quiet=quiet, verbose=verbose, json_output=json_output)

subtensor = self.initialize_chain(network)
non_archives = ["finney", "latent-lite", "subvortex"]
non_archives = ["finney", "latent-lite"]
if not current_only and subtensor.network in non_archives + [
Constants.network_map[x] for x in non_archives
]:
Expand Down
6 changes: 1 addition & 5 deletions bittensor_cli/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,18 @@ class Constants:
"finney",
"test",
"archive",
"subvortex",
"rao",
"dev",
"latent-lite",
]
finney_entrypoint = "wss://entrypoint-finney.opentensor.ai:443"
finney_test_entrypoint = "wss://test.finney.opentensor.ai:443"
archive_entrypoint = "wss://archive.chain.opentensor.ai:443"
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"
local_entrypoint = "ws://127.0.0.1:9944"
latent_lite_entrypoint = "wss://lite.sub.latent.to:443"
lite_nodes = [finney_entrypoint, subvortex_entrypoint, latent_lite_entrypoint]
lite_nodes = [finney_entrypoint, latent_lite_entrypoint]
network_map = {
"finney": finney_entrypoint,
"test": finney_test_entrypoint,
Expand All @@ -32,7 +29,6 @@ class Constants:
"dev": dev_entrypoint,
"rao": rao_entrypoint,
"latent-lite": latent_lite_entrypoint,
"subvortex": subvortex_entrypoint,
}
genesis_block_hash_map = {
"finney": "0x2f0555cc76fc2840a25a6ea3b9637146806f1f44b090c175ffde2a7e5ab36c03",
Expand Down
7 changes: 5 additions & 2 deletions bittensor_cli/src/bittensor/extrinsics/transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
from async_substrate_interface.errors import SubstrateRequestException

from bittensor_cli.src.bittensor.balances import Balance
from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface
from bittensor_cli.src.bittensor.subtensor_interface import (
SubtensorInterface,
GENESIS_ADDRESS,
)
from bittensor_cli.src.bittensor.utils import (
console,
err_console,
Expand Down Expand Up @@ -173,7 +176,7 @@ async def do_transfer() -> tuple[bool, str, str, AsyncExtrinsicReceipt]:
# Ask before moving on.
if prompt:
hk_owner = await subtensor.get_hotkey_owner(destination, check_exists=False)
if hk_owner and hk_owner != destination:
if hk_owner and hk_owner not in (destination, GENESIS_ADDRESS):
if not Confirm.ask(
f"The destination appears to be a hotkey, owned by [bright_magenta]{hk_owner}[/bright_magenta]. "
f"Only proceed if you are absolutely sure that [bright_magenta]{destination}[/bright_magenta] is the "
Expand Down
22 changes: 15 additions & 7 deletions bittensor_cli/src/bittensor/subtensor_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
get_hotkey_pub_ss58,
)

GENESIS_ADDRESS = "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM"


class ParamWithTypes(TypedDict):
name: str # Name of the parameter.
Expand Down Expand Up @@ -118,6 +120,7 @@ def __init__(self, network, use_disk_cache: bool = False):
ss58_format=SS58_FORMAT,
type_registry=TYPE_REGISTRY,
chain_name="Bittensor",
ws_shutdown_timer=None,
)

def __str__(self):
Expand Down Expand Up @@ -1116,7 +1119,7 @@ async def does_hotkey_exist(
block_hash=block_hash,
reuse_block_hash=reuse_block,
)
return_val = result != "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM"
return_val = result != GENESIS_ADDRESS
return return_val

async def get_hotkey_owner(
Expand Down Expand Up @@ -2103,7 +2106,7 @@ async def get_claimable_stakes_for_coldkey(
if not stakes_info:
return {}

root_stakes = {}
root_stakes: dict[str, Balance] = {}
for stake_info in stakes_info:
if stake_info.netuid == 0 and stake_info.stake.rao > 0:
root_stakes[stake_info.hotkey_ss58] = stake_info.stake
Expand Down Expand Up @@ -2149,8 +2152,8 @@ async def get_claimable_stakes_for_coldkey(
self.substrate.query_multi(batch_claimed_calls, block_hash=block_hash),
)

claimable_rates = {}
claimed_amounts = {}
claimable_rates: dict[str, dict[int, float]] = {}
claimed_amounts: dict[tuple[str, int], Balance] = {}
for idx, (_, result) in enumerate(batch_claimable):
hotkey = unique_hotkeys[idx]
if result:
Expand All @@ -2166,12 +2169,17 @@ async def get_claimable_stakes_for_coldkey(

# Calculate the claimable stake for each pair
results = {}
already_claimed: Balance
net_claimable: Balance
rate: float
root_stake: Balance
claimable_stake: Balance
for hotkey, netuid in target_pairs:
root_stake = root_stakes[hotkey]
rate = claimable_rates[hotkey].get(netuid, 0)
rate = claimable_rates[hotkey].get(netuid, 0.0)
claimable_stake = rate * root_stake
already_claimed = claimed_amounts.get((hotkey, netuid), 0)
net_claimable = max(claimable_stake - already_claimed, 0)
already_claimed = claimed_amounts.get((hotkey, netuid), Balance(0))
net_claimable = max(claimable_stake - already_claimed, Balance(0))
if hotkey not in results:
results[hotkey] = {}
results[hotkey][netuid] = net_claimable.set_unit(netuid)
Expand Down
20 changes: 12 additions & 8 deletions bittensor_cli/src/commands/stake/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def define_table(

def create_table(
hotkey_: str,
substakes: list[StakeInfo],
substakes_: list[StakeInfo],
claimable_amounts_: dict[str, dict[int, Balance]],
):
name_ = (
Expand All @@ -164,9 +164,9 @@ def create_table(
rows = []
total_tao_value_ = Balance(0)
total_swapped_tao_value_ = Balance(0)
root_stakes = [s for s in substakes if s.netuid == 0]
root_stakes = [s for s in substakes_ if s.netuid == 0]
other_stakes = sorted(
[s for s in substakes if s.netuid != 0],
[s for s in substakes_ if s.netuid != 0],
key=lambda x: dynamic_info[x.netuid]
.alpha_to_tao(Balance.from_rao(int(x.stake.rao)).set_unit(x.netuid))
.tao,
Expand Down Expand Up @@ -626,7 +626,7 @@ def format_cell(
input()

total_tao_value = (
f"τ {millify_tao(all_hks_tao_value.tao)}"
f"τ {millify_tao(all_hks_tao_value.tao + balance.tao)}"
if not verbose
else all_hks_tao_value
)
Expand All @@ -638,10 +638,14 @@ def format_cell(
console.print("\n\n")
console.print(
f"Wallet:\n"
f" Coldkey SS58: [{COLOR_PALETTE['GENERAL']['COLDKEY']}]{coldkey_address}[/{COLOR_PALETTE['GENERAL']['COLDKEY']}]\n"
f" Free Balance: [{COLOR_PALETTE['GENERAL']['BALANCE']}]{balance}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]\n"
f" Total TAO Value ({Balance.unit}): [{COLOR_PALETTE['GENERAL']['BALANCE']}]{total_tao_value}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]"
# f"\n Total TAO Swapped Value ({Balance.unit}): [{COLOR_PALETTE['GENERAL']['BALANCE']}]{total_swapped_tao_value}[/{COLOR_PALETTE['GENERAL']['BALANCE']}]"
f" Coldkey SS58: "
f"[{COLOR_PALETTE.G.CK}]{coldkey_address}[/{COLOR_PALETTE.G.CK}]\n"
f" Free Balance: "
f"[{COLOR_PALETTE.G.BALANCE}]{balance}[/{COLOR_PALETTE.G.BALANCE}]\n"
f" Total TAO Swapped Value ({Balance.unit}): "
f"[{COLOR_PALETTE.G.BALANCE}]{total_swapped_tao_value}[/{COLOR_PALETTE.G.BALANCE}]\n"
f" Total TAO Value (including free balance) ({Balance.unit}): "
f"[{COLOR_PALETTE.G.BALANCE}]{total_tao_value}[/{COLOR_PALETTE.G.BALANCE}]\n"
)
dict_output["free_balance"] = balance.tao
dict_output["total_tao_value"] = all_hks_tao_value.tao
Expand Down
29 changes: 24 additions & 5 deletions bittensor_cli/src/commands/stake/move.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,39 +108,58 @@ async def display_stake_movement_cross_subnets(
)

table.add_column(
"origin netuid", justify="center", style=COLOR_PALETTE["GENERAL"]["SYMBOL"]
"origin netuid",
justify="center",
style=COLOR_PALETTE["GENERAL"]["SYMBOL"],
max_width=14,
)
table.add_column(
"origin hotkey", justify="center", style=COLOR_PALETTE["GENERAL"]["HOTKEY"]
"origin hotkey",
justify="center",
style=COLOR_PALETTE["GENERAL"]["HOTKEY"],
max_width=15,
)
table.add_column(
"dest netuid", justify="center", style=COLOR_PALETTE["GENERAL"]["SYMBOL"]
"dest netuid",
justify="center",
style=COLOR_PALETTE["GENERAL"]["SYMBOL"],
max_width=12,
)
table.add_column(
"dest hotkey", justify="center", style=COLOR_PALETTE["GENERAL"]["HOTKEY"]
"dest hotkey",
justify="center",
style=COLOR_PALETTE["GENERAL"]["HOTKEY"],
max_width=15,
)
table.add_column(
f"amount ({Balance.get_unit(origin_netuid)})",
justify="center",
style=COLOR_PALETTE["STAKE"]["TAO"],
max_width=18,
)
table.add_column(
f"rate ({Balance.get_unit(destination_netuid)}/{Balance.get_unit(origin_netuid)})",
justify="center",
style=COLOR_PALETTE["POOLS"]["RATE"],
max_width=20,
)
table.add_column(
f"received ({Balance.get_unit(destination_netuid)})",
justify="center",
style=COLOR_PALETTE["POOLS"]["TAO_EQUIV"],
max_width=18,
)
table.add_column(
f"Fee ({Balance.get_unit(origin_netuid)})",
justify="center",
style=COLOR_PALETTE["STAKE"]["STAKE_AMOUNT"],
max_width=15,
)
table.add_column(
"Extrinsic Fee (τ)", justify="center", style=COLOR_PALETTE.STAKE.TAO
"Extrinsic Fee (τ)",
justify="center",
style=COLOR_PALETTE.STAKE.TAO,
max_width=18,
)

table.add_row(
Expand Down
11 changes: 6 additions & 5 deletions bittensor_cli/src/commands/wallets.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
)
from bittensor_cli.src.bittensor.extrinsics.transfer import transfer_extrinsic
from bittensor_cli.src.bittensor.networking import int_to_ip
from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface
from bittensor_cli.src.bittensor.subtensor_interface import (
SubtensorInterface,
GENESIS_ADDRESS,
)
from bittensor_cli.src.bittensor.utils import (
RAO_PER_TAO,
console,
Expand Down Expand Up @@ -2261,10 +2264,8 @@ async def check_swap_status(
chain_reported_completion_block, destination_address = await subtensor.query(
"SubtensorModule", "ColdkeySwapScheduled", [origin_ss58]
)
if (
chain_reported_completion_block != 0
and destination_address != "5C4hrfjw9DjXZTzV3MwzrrAr9P1MJhSrvWGWqi1eSuyUpnhM"
):
destination_address = decode_account_id(destination_address[0])
if chain_reported_completion_block != 0 and destination_address != GENESIS_ADDRESS:
is_pending = True
else:
is_pending = False
Expand Down
4 changes: 2 additions & 2 deletions bittensor_cli/src/commands/weights.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,13 @@ async def reveal(self, weight_uids, weight_vals) -> tuple[bool, str, Optional[st

return (
True,
"Successfully revealed previously commited weights hash.",
"Successfully revealed previously committed weights hash.",
ext_id,
)
else:
# bittensor.logging.error(
# msg=msg,
# prefix=f"Failed to reveal previously commited weights hash for salt: {salt}",
# prefix=f"Failed to reveal previously committed weights hash for salt: {salt}",
# suffix="<red>Failed: </red>",
# )
return False, "Failed to reveal weights.", None
Expand Down
Loading
Loading