Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
690d295
Speeds up from 51 seconds to 3 for me
thewhaleking Mar 25, 2026
a9ef489
Bump page size
thewhaleking Mar 25, 2026
27c5a38
Merge pull request #876 from opentensor/fix/thewhaleking/fix-speed-is…
thewhaleking Mar 25, 2026
fb9f692
update get_all_subnet_netuids
ibraheem-abe Mar 25, 2026
354b30d
update get_auto_stake_destinations
ibraheem-abe Mar 25, 2026
8243b35
update get_all_subnet_mechanisms
ibraheem-abe Mar 25, 2026
2b080f1
update get_all_subnet_ema_tao_inflow
ibraheem-abe Mar 25, 2026
7297287
update get_subnet_prices
ibraheem-abe Mar 25, 2026
df67034
update get_crowdloan_contributors
ibraheem-abe Mar 25, 2026
a475880
update get_crowdloans
ibraheem-abe Mar 25, 2026
12b20d7
update get_coldkey_swap_disputes
ibraheem-abe Mar 25, 2026
6313f55
update get_coldkey_swap_announcements
ibraheem-abe Mar 25, 2026
f1c4ddd
update burned_register_extrinsic
ibraheem-abe Mar 25, 2026
a5a8183
update get_netuids_for_hotkey
ibraheem-abe Mar 25, 2026
4d58c9e
update get_claimed_amount_all_netuids
ibraheem-abe Mar 25, 2026
4068a3e
update subnet show/metagraph
ibraheem-abe Mar 25, 2026
ac39d57
Merge pull request #877 from opentensor/fix/speed-issue-with-network-…
ibraheem-abe Mar 25, 2026
af2d038
update stake move
ibraheem-abe Mar 25, 2026
35573b5
update wizard
ibraheem-abe Mar 25, 2026
4cb9823
update view
ibraheem-abe Mar 25, 2026
1e4be77
update set_auto_stake_destination
ibraheem-abe Mar 25, 2026
cbab0b8
update remove
ibraheem-abe Mar 25, 2026
72e0520
update inspect
ibraheem-abe Mar 26, 2026
fe433a4
update stake list
ibraheem-abe Mar 26, 2026
0620a4c
add utils
ibraheem-abe Mar 26, 2026
5d8ca8d
update sudo
ibraheem-abe Mar 26, 2026
6d04b95
update view & wizard
ibraheem-abe Mar 26, 2026
154e933
update staking cmds
ibraheem-abe Mar 26, 2026
dda55b8
update auto staking
ibraheem-abe Mar 26, 2026
7fe612c
stake list
ibraheem-abe Mar 26, 2026
e2a1fc0
remove deprecated funcs + classes
ibraheem-abe Mar 26, 2026
87c9077
Merge pull request #878 from opentensor/update/deprecate-old-identities
ibraheem-abe Mar 26, 2026
8d1e098
With the upcoming release of ASI 2.0 (probably in a month or two), we…
thewhaleking Mar 30, 2026
94d42f8
Merge pull request #880 from opentensor/feat/thewhaleking/stricter-ve…
thewhaleking Mar 30, 2026
4e3416c
fix: resolve proxy address for stake queries in move/transfer/swap an…
bitloi Mar 31, 2026
4128ea9
Bumps workflow versions, uses permission in release
thewhaleking Apr 1, 2026
668d67a
Merge pull request #881 from bitloi/fix/proxy-address-resolution-stak…
thewhaleking Apr 1, 2026
7973807
Merge pull request #882 from latent-to/chore/thewhaleking/bump-workfl…
thewhaleking Apr 1, 2026
32a6f69
inspect hotkey support (#883)
thewhaleking Apr 1, 2026
22d7108
Correctly uses the already-formatted error message in a failure for u…
thewhaleking Apr 1, 2026
32b7e05
Correctly uses the already-formatted error message in a failure for u…
thewhaleking Apr 1, 2026
2272651
Merge pull request #888 from bitloi/fix/wallet-create-safety-bugs
bitloi Apr 2, 2026
d4b79ce
fix: guard stake add rate inversions on zero prices (#886)
bitloi Apr 2, 2026
8dc24f6
Consolidate text fixtures in one place
thewhaleking Apr 2, 2026
cbec563
Adds more tests
thewhaleking Apr 2, 2026
6dd47af
Adds more tests
thewhaleking Apr 2, 2026
253a354
Ruff
thewhaleking Apr 2, 2026
6d71a6e
Update contributing guide
thewhaleking Apr 2, 2026
372aff3
Better interactivity in `st move`
thewhaleking Apr 2, 2026
197aedf
Adds tests
thewhaleking Apr 2, 2026
33f5532
Ruff
thewhaleking Apr 2, 2026
fde30ed
Updates tests
thewhaleking Apr 2, 2026
9644a28
More reuse
thewhaleking Apr 2, 2026
1e77f60
Merge branch 'feat/thewhaleking/improved-test-cvg' into feat/thewhale…
thewhaleking Apr 2, 2026
936d151
Improved test coverage (#889)
thewhaleking Apr 2, 2026
6cfcb4e
Update bittensor_cli/cli.py
thewhaleking Apr 2, 2026
6a7a939
fix proxy allow-death transfer balance check (#891)
bitloi Apr 2, 2026
93ab54c
Merge pull request #892 from latent-to/feat/thewhaleking/better-move-…
thewhaleking Apr 2, 2026
c187c26
Changelog + version
thewhaleking Apr 2, 2026
f35a42b
Merge pull request #893 from latent-to/changelog/9.20.1
thewhaleking Apr 2, 2026
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
10 changes: 5 additions & 5 deletions .github/workflows/e2e-subtensor-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
test-files: ${{ steps.get-tests.outputs.test-files }}
steps:
- name: Check-out repository under $GITHUB_WORKSPACE
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Find test files
id: get-tests
Expand Down Expand Up @@ -158,7 +158,7 @@ jobs:
run: docker save -o subtensor-localnet.tar ${{ steps.set-image.outputs.image }}

- name: Upload Docker Image as Artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: subtensor-localnet
path: subtensor-localnet.tar
Expand All @@ -180,15 +180,15 @@ jobs:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Check-out repository
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Install uv
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v8.0.0
with:
python-version: 3.13

- name: Download Cached Docker Image
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: subtensor-localnet

Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ jobs:
build:
name: Build Python distribution
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v6

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: '3.10'
python-version: '3.12'

- name: Install dependencies
run: |
Expand All @@ -45,7 +47,7 @@ jobs:
fi
- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: dist
path: dist/
Expand All @@ -60,7 +62,7 @@ jobs:

steps:
- name: Download artifact
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: dist
path: dist/
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ruff-formatter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Ruff format check
uses: astral-sh/ruff-action@v3
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ jobs:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- name: Check-out repository
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Install uv
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v8.0.0
with:
python-version: ${{ matrix.python-version }}

Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## 9.20.1 /2026-04-02

## What's Changed
* Fully_exhaust=True for by @thewhaleking in https://github.com/latent-to/btcli/pull/876
* Fix/speed issue with network calls by @ibraheem-abe in https://github.com/latent-to/btcli/pull/877
* Update/deprecate old identities by @ibraheem-abe in https://github.com/latent-to/btcli/pull/878
* ASI version <2.0 by @thewhaleking in https://github.com/latent-to/btcli/pull/880
* fix: resolve proxy address for stake queries in move/transfer/swap and sudo trim by @bitloi in https://github.com/latent-to/btcli/pull/881
* Bumps workflow versions, uses permission in release by @thewhaleking in https://github.com/latent-to/btcli/pull/882
* inspect hotkey support by @thewhaleking in https://github.com/latent-to/btcli/pull/883
* unstake: format error message incorrect by @thewhaleking in https://github.com/latent-to/btcli/pull/884
* fix: error handling in wallet_create() and new_coldkey() by @bitloi in https://github.com/latent-to/btcli/pull/888
* fix: prevent division by zero in stake add when subnet price is zero by @bitloi in https://github.com/latent-to/btcli/pull/886
* Improved test coverage by @thewhaleking in https://github.com/latent-to/btcli/pull/889
* fix: proxy allow-death transfer balance check by @bitloi in https://github.com/latent-to/btcli/pull/891
* Better st move interactivity by @thewhaleking in https://github.com/latent-to/btcli/pull/892

## New Contributors
* @bitloi made their first contribution in https://github.com/latent-to/btcli/pull/881

**Full Changelog**: https://github.com/latent-to/btcli/compare/v9.20.0...v9.20.1

## 9.20.0 /2026-03-24

## What's Changed
Expand Down
80 changes: 48 additions & 32 deletions bittensor_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2913,32 +2913,52 @@ def wallet_inspect(
),
wallet_name: str = Options.wallet_name,
wallet_path: str = Options.wallet_path,
wallet_hotkey: str = Options.wallet_hotkey,
wallet_hotkey: str = Options.edit_help(
"wallet_hotkey",
help_text="Deprecated option, "
"preserved for backwards compatibility to not break workflows which utilise it.",
),
ss58_address: Optional[str] = typer.Option(
None,
"--ss58-address",
"--ss58",
help="SS58 address of the coldkey to inspect. Allows inspecting any coldkey without a local wallet file.",
),
network: Optional[list[str]] = Options.network,
netuids: str = Options.netuids,
quiet: bool = Options.quiet,
verbose: bool = Options.verbose,
json_output: bool = Options.json_output,
):
"""
Displays the details of the user's wallet pairs (coldkey, hotkey) on the Bittensor network.
Displays the details of the user's wallet (coldkey) on the Bittensor network.

The output is presented as a table with the below columns:
The output is presented as two separate tables:

[bold]Coldkey Overview[/bold]:

- [blue bold]Coldkey[/blue bold]: The coldkey associated with the user's wallet.

- [blue bold]Balance[/blue bold]: The balance of the coldkey.

- [blue bold]Delegate[/blue bold]: The name of the delegate to which the coldkey has staked TAO.

- [blue bold]Stake[/blue bold]: The amount of stake held by both the coldkey and hotkey.
- [blue bold]Stake[/blue bold]: The amount of stake delegated.

- [blue bold]Emission[/blue bold]: The emission or rewards earned from staking.
- [blue bold]Emission[/blue bold]: The daily emission earned from delegation.

[bold]Hotkey Details[/bold]:

- [blue bold]Netuid[/blue bold]: The network unique identifier of the subnet where the hotkey is active (i.e., validating).
- [blue bold]Coldkey[/blue bold]: The parent coldkey of the hotkey.

- [blue bold]Netuid[/blue bold]: The network unique identifier of the subnet where the hotkey is active.

- [blue bold]Hotkey[/blue bold]: The hotkey associated with the neuron on the network.

- [blue bold]Stake[/blue bold]: The amount of stake held by the hotkey.

- [blue bold]Emission[/blue bold]: The emission or rewards earned from staking.

USAGE

This command can be used to inspect a single wallet or all the wallets located at a specified path. It is useful for a comprehensive overview of a user's participation and performance in the Bittensor network.
Expand All @@ -2949,10 +2969,10 @@ def wallet_inspect(

[green]$[/green] btcli wallet inspect --all -n 1 -n 2 -n 3

[green]$[/green] btcli wallet inspect --ss58-address 5FHneW46...

[bold]Note[/bold]: The `inspect` command is for displaying information only and does not perform any transactions or state changes on the blockchain. It is intended to be used with Bittensor CLI and not as a standalone function in user code.
"""
print_error("This command is disabled on the 'rao' network.")
raise typer.Exit()
self.verbosity_handler(quiet, verbose, json_output, False)

if netuids:
Expand All @@ -2962,18 +2982,28 @@ def wallet_inspect(
"Netuids must be a comma-separated list of ints, e.g., `--netuids 1,2,3,4`.",
)

if ss58_address:
return self._run_command(
wallets.inspect(
None,
self.initialize_chain(network),
netuids_filter=netuids,
all_wallets=False,
ss58_address=ss58_address,
)
)

# if all-wallets is entered, ask for path
ask_for = [WO.NAME, WO.PATH] if not all_wallets else [WO.PATH]
validate = WV.WALLET if not all_wallets else WV.NONE
wallet = self.wallet_ask(
wallet_name, wallet_path, wallet_hotkey, ask_for=ask_for, validate=validate
wallet_name, wallet_path, None, ask_for=ask_for, validate=validate
)

self.initialize_chain(network)
return self._run_command(
wallets.inspect(
wallet,
self.subtensor,
self.initialize_chain(network),
netuids_filter=netuids,
all_wallets=all_wallets,
)
Expand Down Expand Up @@ -5482,33 +5512,20 @@ def stake_move(
console.print(
"[dim]This command moves stake from one hotkey to another hotkey while keeping the same coldkey.[/dim]"
)
interactive_selection = False
if not destination_hotkey:
dest_wallet_or_ss58 = Prompt.ask(
"Enter the [blue]destination wallet[/blue] where destination hotkey is located or "
"[blue]ss58 address[/blue]"
"Enter the [blue]ss58 address[/blue] of the hotkey to move the stake to, leave blank for other options"
)
if is_valid_ss58_address(dest_wallet_or_ss58):
destination_hotkey = dest_wallet_or_ss58
elif dest_wallet_or_ss58.strip() == "":
interactive_selection = True
else:
dest_wallet = self.wallet_ask(
dest_wallet_or_ss58,
wallet_path,
None,
ask_for=[WO.NAME, WO.PATH],
validate=WV.WALLET,
)
destination_hotkey = Prompt.ask(
"Enter the [blue]destination hotkey[/blue] name",
default=dest_wallet.hotkey_str,
)
destination_wallet = self.wallet_ask(
dest_wallet_or_ss58,
wallet_path,
destination_hotkey,
ask_for=[WO.NAME, WO.PATH, WO.HOTKEY],
validate=WV.WALLET_AND_HOTKEY,
print_error(
"Invalid destination hotkey ss58 address. Please enter a valid ss58 address."
)
destination_hotkey = get_hotkey_pub_ss58(destination_wallet)
raise typer.Exit()
else:
if is_valid_ss58_address(destination_hotkey):
destination_hotkey = destination_hotkey
Expand All @@ -5527,7 +5544,6 @@ def stake_move(
wallet_name, wallet_path, wallet_hotkey, ask_for=[WO.NAME, WO.PATH]
)

interactive_selection = False
if not wallet_hotkey:
origin_hotkey = Prompt.ask(
"Enter the [blue]origin hotkey[/blue] name or "
Expand Down
43 changes: 0 additions & 43 deletions bittensor_cli/src/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from enum import Enum
from dataclasses import dataclass
from typing import Any, Optional


class Constants:
Expand Down Expand Up @@ -37,47 +35,6 @@ class Constants:
delegates_detail_url = "https://raw.githubusercontent.com/opentensor/bittensor-delegates/main/public/delegates.json"


@dataclass
class DelegatesDetails:
display: str
additional: list[tuple[str, str]]
web: str
legal: Optional[str] = None
riot: Optional[str] = None
email: Optional[str] = None
pgp_fingerprint: Optional[str] = None
image: Optional[str] = None
twitter: Optional[str] = None

@classmethod
def from_chain_data(cls, data: dict[str, Any]) -> "DelegatesDetails":
def decode(key: str, default=""):
try:
if isinstance(data.get(key), dict):
value = next(data.get(key).values())
return bytes(value[0]).decode("utf-8")
elif isinstance(data.get(key), int):
return data.get(key)
elif isinstance(data.get(key), tuple):
return bytes(data.get(key)[0]).decode("utf-8")
else:
return default
except (UnicodeDecodeError, TypeError):
return default

return cls(
display=decode("display"),
additional=decode("additional", []),
web=decode("web"),
legal=decode("legal"),
riot=decode("riot"),
email=decode("email"),
pgp_fingerprint=decode("pgp_fingerprint", None),
image=decode("image"),
twitter=decode("twitter"),
)


class Defaults:
netuid = 1
rate_tolerance = 0.005
Expand Down
8 changes: 5 additions & 3 deletions bittensor_cli/src/bittensor/extrinsics/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,11 +708,13 @@ async def burned_register_extrinsic(
f":satellite: Checking Account on [bold]subnet:{netuid}[/bold]...",
spinner="aesthetic",
) as status:
block_hash = await subtensor.substrate.get_chain_head()
my_uid = await subtensor.query(
"SubtensorModule", "Uids", [netuid, get_hotkey_pub_ss58(wallet)]
module="SubtensorModule",
storage_function="Uids",
params=[netuid, get_hotkey_pub_ss58(wallet)],
block_hash=block_hash,
)
block_hash = await subtensor.substrate.get_chain_head()

print_verbose("Checking if already registered", status)
neuron = await subtensor.neuron_for_uid(
uid=my_uid, netuid=netuid, block_hash=block_hash
Expand Down
4 changes: 2 additions & 2 deletions bittensor_cli/src/bittensor/extrinsics/transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,10 @@ async def do_transfer() -> tuple[bool, str, str, Optional[AsyncExtrinsicReceipt]
f" would bring you under the existential deposit: [bright_cyan]{existential_deposit}[/bright_cyan].\n"
)
return False, None
if account_balance < amount and allow_death:
if proxy_balance < amount and allow_death:
print_error(
"[bold red]Not enough balance[/bold red]:\n\n"
f" balance: [bright_red]{account_balance}[/bright_red]\n"
f" balance: [bright_red]{proxy_balance}[/bright_red]\n"
f" amount: [bright_red]{amount}[/bright_red]\n"
)
return False, None
Expand Down
Loading
Loading