Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
88bfed5
adds SubsubnetCountCurrent extrinsic
ibraheem-abe Sep 16, 2025
09c49af
subnet.count()
ibraheem-abe Sep 16, 2025
9512cdb
btcli subnet count
ibraheem-abe Sep 16, 2025
aed6db5
add more clarity
ibraheem-abe Sep 16, 2025
df0e04b
sudo_sub + btcli sudo sub count
ibraheem-abe Sep 16, 2025
35d686f
update help panel
ibraheem-abe Sep 16, 2025
7e6296f
add set_sub_subnet_count_extrinsic
ibraheem-abe Sep 16, 2025
c538ec7
add cmd
ibraheem-abe Sep 16, 2025
0225ada
add btcli sub or btcli subsubnets
ibraheem-abe Sep 17, 2025
2028eca
update help disp + vocab
ibraheem-abe Sep 17, 2025
42f45ba
update extrinsics
ibraheem-abe Sep 17, 2025
4a02189
update mechanism count
ibraheem-abe Sep 17, 2025
0e8c447
sudo_set_mechanism_emission
ibraheem-abe Sep 17, 2025
257e165
update mech_count
ibraheem-abe Sep 17, 2025
73f65d5
normalize_emission_weights
ibraheem-abe Sep 17, 2025
9a63dde
get_emission_split
ibraheem-abe Sep 17, 2025
ee80655
set_emission_split
ibraheem-abe Sep 17, 2025
8dc0f01
update cli cmds
ibraheem-abe Sep 17, 2025
3de8f23
update to mechanisms
ibraheem-abe Sep 17, 2025
dc86c65
add mech app
ibraheem-abe Sep 17, 2025
0cd40b6
remove from subnets
ibraheem-abe Sep 17, 2025
6f51ae2
cleanup sudo
ibraheem-abe Sep 17, 2025
8b45678
mechanisms.py
ibraheem-abe Sep 17, 2025
c8de471
wip
ibraheem-abe Sep 17, 2025
df47c71
ruff
ibraheem-abe Sep 17, 2025
849c6a0
updates cmds
ibraheem-abe Sep 17, 2025
13f5168
add get_mechagraph_info
ibraheem-abe Sep 18, 2025
5e78532
handle mech_id in subnet show
ibraheem-abe Sep 18, 2025
b7ce4bd
get_netuid_and_subuid_by_storage_index
ibraheem-abe Sep 18, 2025
8c5564c
update MetagraphInfo
ibraheem-abe Sep 18, 2025
44aa14f
update metagraph to use mechanism ids
ibraheem-abe Sep 18, 2025
8a51aa9
add mechid alias
ibraheem-abe Sep 18, 2025
271b2ce
wip
ibraheem-abe Sep 18, 2025
7905fc7
improve mech prompt info
ibraheem-abe Sep 18, 2025
cc8bad1
fmt
ibraheem-abe Sep 18, 2025
e69e645
get_all_subnet_mechanisms
ibraheem-abe Sep 18, 2025
ff9b433
add mechanisms to subnets list
ibraheem-abe Sep 18, 2025
31e1934
improves docs
ibraheem-abe Sep 18, 2025
3f898da
Merge branch 'staging' into feat/sub-subnets
thewhaleking Sep 22, 2025
4eef910
Merge branch 'staging' into feat/sub-subnets
thewhaleking Sep 23, 2025
34989b8
Update to include extrinsic identifiers
thewhaleking Sep 23, 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
349 changes: 345 additions & 4 deletions bittensor_cli/cli.py

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions bittensor_cli/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,10 @@ class WalletValidationTypes(Enum):
"GOVERNANCE": "Governance",
"TAKE": "Delegate take configuration",
},
"MECHANISMS": {
"CONFIG": "Mechanism Configuration",
"EMISSION": "Mechanism Emission",
},
"SUBNETS": {
"INFO": "Subnet Information",
"CREATION": "Subnet Creation & Management",
Expand Down
5 changes: 4 additions & 1 deletion bittensor_cli/src/bittensor/chain_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
u16_normalized_float as u16tf,
u64_normalized_float as u64tf,
decode_account_id,
get_netuid_and_subuid_by_storage_index,
)


Expand Down Expand Up @@ -1084,12 +1085,13 @@ class MetagraphInfo(InfoBase):
alpha_dividends_per_hotkey: list[
tuple[str, Balance]
] # List of dividend payout in alpha via subnet.
subuid: int = 0

@classmethod
def _fix_decoded(cls, decoded: dict) -> "MetagraphInfo":
"""Returns a MetagraphInfo object from decoded chain data."""
# Subnet index
_netuid = decoded["netuid"]
_netuid, _subuid = get_netuid_and_subuid_by_storage_index(decoded["netuid"])

# Name and symbol
decoded.update({"name": bytes(decoded.get("name")).decode()})
Expand All @@ -1102,6 +1104,7 @@ def _fix_decoded(cls, decoded: dict) -> "MetagraphInfo":
return cls(
# Subnet index
netuid=_netuid,
subuid=_subuid,
# Name and symbol
name=decoded["name"],
symbol=decoded["symbol"],
Expand Down
83 changes: 73 additions & 10 deletions bittensor_cli/src/bittensor/subtensor_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,55 @@ async def get_subnet_hyperparameters(

return SubnetHyperparameters.from_any(result)

async def get_subnet_mechanisms(
self, netuid: int, block_hash: Optional[str] = None
) -> int:
"""Return the number of mechanisms that belong to the provided subnet."""

result = await self.query(
module="SubtensorModule",
storage_function="MechanismCountCurrent",
params=[netuid],
block_hash=block_hash,
)

if result is None:
return 0
return int(result)

async def get_all_subnet_mechanisms(
self, block_hash: Optional[str] = None
) -> dict[int, int]:
"""Return mechanism counts for every subnet with a recorded value."""

results = await self.substrate.query_map(
module="SubtensorModule",
storage_function="MechanismCountCurrent",
params=[],
block_hash=block_hash,
)
res = {}
async for netuid, count in results:
res[int(netuid)] = int(count.value)
return res

async def get_mechanism_emission_split(
self, netuid: int, block_hash: Optional[str] = None
) -> list[int]:
"""Return the emission split configured for the provided subnet."""

result = await self.query(
module="SubtensorModule",
storage_function="MechanismEmissionSplit",
params=[netuid],
block_hash=block_hash,
)

if not result:
return []

return [int(value) for value in result]

async def burn_cost(self, block_hash: Optional[str] = None) -> Optional[Balance]:
result = await self.query_runtime_api(
runtime_api="SubnetRegistrationRuntimeApi",
Expand Down Expand Up @@ -1300,37 +1349,51 @@ async def get_stake_for_coldkey_and_hotkey_on_netuid(
else:
return Balance.from_rao(fixed_to_float(_result)).set_unit(int(netuid))

async def get_mechagraph_info(
self, netuid: int, mech_id: int, block_hash: Optional[str] = None
) -> Optional[MetagraphInfo]:
"""
Returns the metagraph info for a given subnet and mechanism id.
And yes, it is indeed 'mecha'graph
"""
query = await self.query_runtime_api(
runtime_api="SubnetInfoRuntimeApi",
method="get_mechagraph",
params=[netuid, mech_id],
block_hash=block_hash,
)

if query is None:
return None

return MetagraphInfo.from_any(query)

async def get_metagraph_info(
self, netuid: int, block_hash: Optional[str] = None
) -> Optional[MetagraphInfo]:
hex_bytes_result = await self.query_runtime_api(
query = await self.query_runtime_api(
runtime_api="SubnetInfoRuntimeApi",
method="get_metagraph",
params=[netuid],
block_hash=block_hash,
)

if hex_bytes_result is None:
if query is None:
return None

try:
bytes_result = bytes.fromhex(hex_bytes_result[2:])
except ValueError:
bytes_result = bytes.fromhex(hex_bytes_result)

return MetagraphInfo.from_any(bytes_result)
return MetagraphInfo.from_any(query)

async def get_all_metagraphs_info(
self, block_hash: Optional[str] = None
) -> list[MetagraphInfo]:
hex_bytes_result = await self.query_runtime_api(
query = await self.query_runtime_api(
runtime_api="SubnetInfoRuntimeApi",
method="get_all_metagraphs",
params=[],
block_hash=block_hash,
)

return MetagraphInfo.list_from_any(hex_bytes_result)
return MetagraphInfo.list_from_any(query)

async def multi_get_stake_for_coldkey_and_hotkey_on_netuid(
self,
Expand Down
21 changes: 21 additions & 0 deletions bittensor_cli/src/bittensor/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

BT_DOCS_LINK = "https://docs.learnbittensor.org"

GLOBAL_MAX_SUBNET_COUNT = 4096

console = Console()
json_console = Console()
Expand Down Expand Up @@ -1466,6 +1467,26 @@ def get_hotkey_pub_ss58(wallet: Wallet) -> str:
return wallet.hotkey.ss58_address


def get_netuid_and_subuid_by_storage_index(storage_index: int) -> tuple[int, int]:
"""Returns the netuid and subuid from the storage index.

Chain APIs (e.g., SubMetagraph response) returns netuid which is storage index that encodes both the netuid and
subuid. This function reverses the encoding to extract these components.

Parameters:
storage_index: The storage index of the subnet.

Returns:
tuple[int, int]:
- netuid subnet identifier.
- subuid identifier.
"""
return (
storage_index % GLOBAL_MAX_SUBNET_COUNT,
storage_index // GLOBAL_MAX_SUBNET_COUNT,
)


async def print_extrinsic_id(
extrinsic_receipt: Optional[AsyncExtrinsicReceipt],
) -> None:
Expand Down
Loading
Loading