bittensor-cli 9.0.0rc3__py3-none-any.whl → 9.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bittensor_cli/__init__.py +2 -2
- bittensor_cli/cli.py +228 -80
- bittensor_cli/src/__init__.py +50 -25
- bittensor_cli/src/bittensor/chain_data.py +3 -1
- bittensor_cli/src/bittensor/extrinsics/registration.py +26 -34
- bittensor_cli/src/bittensor/extrinsics/root.py +5 -11
- bittensor_cli/src/bittensor/extrinsics/transfer.py +15 -13
- bittensor_cli/src/bittensor/subtensor_interface.py +4 -6
- bittensor_cli/src/bittensor/utils.py +129 -19
- bittensor_cli/src/commands/stake/add.py +4 -4
- bittensor_cli/src/commands/stake/children_hotkeys.py +12 -18
- bittensor_cli/src/commands/stake/list.py +8 -16
- bittensor_cli/src/commands/stake/move.py +2 -2
- bittensor_cli/src/commands/stake/remove.py +3 -3
- bittensor_cli/src/commands/subnets/subnets.py +181 -64
- bittensor_cli/src/commands/sudo.py +68 -35
- bittensor_cli/src/commands/wallets.py +54 -42
- bittensor_cli/src/commands/weights.py +9 -13
- {bittensor_cli-9.0.0rc3.dist-info → bittensor_cli-9.0.1.dist-info}/METADATA +3 -3
- bittensor_cli-9.0.1.dist-info/RECORD +34 -0
- bittensor_cli-9.0.0rc3.dist-info/RECORD +0 -34
- {bittensor_cli-9.0.0rc3.dist-info → bittensor_cli-9.0.1.dist-info}/WHEEL +0 -0
- {bittensor_cli-9.0.0rc3.dist-info → bittensor_cli-9.0.1.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-9.0.0rc3.dist-info → bittensor_cli-9.0.1.dist-info}/top_level.txt +0 -0
@@ -35,12 +35,13 @@ from bittensor_cli.src.bittensor.utils import (
|
|
35
35
|
update_metadata_table,
|
36
36
|
prompt_for_identity,
|
37
37
|
get_subnet_name,
|
38
|
+
unlock_key,
|
38
39
|
)
|
39
40
|
|
40
41
|
if TYPE_CHECKING:
|
41
42
|
from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface
|
42
43
|
|
43
|
-
TAO_WEIGHT = 0.
|
44
|
+
TAO_WEIGHT = 0.18
|
44
45
|
|
45
46
|
# helpers and extrinsics
|
46
47
|
|
@@ -183,7 +184,7 @@ async def register_subnetwork_extrinsic(
|
|
183
184
|
await response.process_events()
|
184
185
|
if not await response.is_success:
|
185
186
|
err_console.print(
|
186
|
-
f":cross_mark: [red]Failed[/red]: {format_error_message(await response.error_message
|
187
|
+
f":cross_mark: [red]Failed[/red]: {format_error_message(await response.error_message)}"
|
187
188
|
)
|
188
189
|
await asyncio.sleep(0.5)
|
189
190
|
return False
|
@@ -326,7 +327,7 @@ async def subnets_list(
|
|
326
327
|
if netuid == 0:
|
327
328
|
emission_tao = 0.0
|
328
329
|
else:
|
329
|
-
emission_tao = subnet.
|
330
|
+
emission_tao = subnet.tao_in_emission.tao
|
330
331
|
|
331
332
|
alpha_in_value = (
|
332
333
|
f"{millify_tao(subnet.alpha_in.tao)}"
|
@@ -399,7 +400,7 @@ async def subnets_list(
|
|
399
400
|
)
|
400
401
|
|
401
402
|
total_emissions = round(
|
402
|
-
sum(
|
403
|
+
sum(subnet.tao_in_emission.tao for subnet in subnets if subnet.netuid != 0),
|
403
404
|
4,
|
404
405
|
)
|
405
406
|
total_rate = round(
|
@@ -528,7 +529,7 @@ async def subnets_list(
|
|
528
529
|
if netuid == 0:
|
529
530
|
emission_tao = 0.0
|
530
531
|
else:
|
531
|
-
emission_tao = subnet.
|
532
|
+
emission_tao = subnet.tao_in_emission.tao
|
532
533
|
|
533
534
|
market_cap = (subnet.alpha_in.tao + subnet.alpha_out.tao) * subnet.price.tao
|
534
535
|
supply = subnet.alpha_in.tao + subnet.alpha_out.tao
|
@@ -657,7 +658,7 @@ async def subnets_list(
|
|
657
658
|
# Calculate totals
|
658
659
|
total_netuids = len(subnets)
|
659
660
|
_total_emissions = sum(
|
660
|
-
|
661
|
+
subnet.tao_in_emission.tao for subnet in subnets if subnet.netuid != 0
|
661
662
|
)
|
662
663
|
total_emissions = (
|
663
664
|
f"{millify_tao(_total_emissions)}"
|
@@ -665,9 +666,7 @@ async def subnets_list(
|
|
665
666
|
else f"{_total_emissions:,.2f}"
|
666
667
|
)
|
667
668
|
|
668
|
-
total_rate = sum(
|
669
|
-
float(subnet.price.tao) for subnet in subnets if subnet.netuid != 0
|
670
|
-
)
|
669
|
+
total_rate = sum(subnet.price.tao for subnet in subnets if subnet.netuid != 0)
|
671
670
|
total_rate = (
|
672
671
|
f"{millify_tao(total_rate)}" if not verbose else f"{total_rate:,.2f}"
|
673
672
|
)
|
@@ -804,6 +803,7 @@ async def subnets_list(
|
|
804
803
|
async def show(
|
805
804
|
subtensor: "SubtensorInterface",
|
806
805
|
netuid: int,
|
806
|
+
sort: bool = False,
|
807
807
|
max_rows: Optional[int] = None,
|
808
808
|
delegate_selection: bool = False,
|
809
809
|
verbose: bool = False,
|
@@ -850,18 +850,6 @@ async def show(
|
|
850
850
|
)
|
851
851
|
|
852
852
|
table.add_column("[bold white]Position", style="white", justify="center")
|
853
|
-
# table.add_column(
|
854
|
-
# f"[bold white]Total Stake ({Balance.get_unit(0)})",
|
855
|
-
# style=COLOR_PALETTE["POOLS"]["ALPHA_IN"],
|
856
|
-
# justify="center",
|
857
|
-
# )
|
858
|
-
# ------- Temporary columns for testing -------
|
859
|
-
# table.add_column(
|
860
|
-
# "Alpha (τ)",
|
861
|
-
# style=COLOR_PALETTE["POOLS"]["EXTRA_2"],
|
862
|
-
# no_wrap=True,
|
863
|
-
# justify="right",
|
864
|
-
# )
|
865
853
|
table.add_column(
|
866
854
|
"Tao (τ)",
|
867
855
|
style=COLOR_PALETTE["POOLS"]["EXTRA_2"],
|
@@ -869,7 +857,6 @@ async def show(
|
|
869
857
|
justify="right",
|
870
858
|
footer=f"{tao_sum:.4f} τ" if verbose else f"{millify_tao(tao_sum)} τ",
|
871
859
|
)
|
872
|
-
# ------- End Temporary columns for testing -------
|
873
860
|
table.add_column(
|
874
861
|
f"[bold white]Emission ({Balance.get_unit(0)}/block)",
|
875
862
|
style=COLOR_PALETTE["POOLS"]["EMISSION"],
|
@@ -903,7 +890,7 @@ async def show(
|
|
903
890
|
for netuid_ in range(len(all_subnets)):
|
904
891
|
subnet = all_subnets[netuid_]
|
905
892
|
emission_on_subnet = (
|
906
|
-
root_state.emission_history[netuid_][idx] / subnet.tempo
|
893
|
+
root_state.emission_history[netuid_][idx] / (subnet.tempo or 1)
|
907
894
|
)
|
908
895
|
total_emission_per_block += subnet.alpha_to_tao(
|
909
896
|
Balance.from_rao(emission_on_subnet)
|
@@ -1075,14 +1062,6 @@ async def show(
|
|
1075
1062
|
pad_edge=True,
|
1076
1063
|
)
|
1077
1064
|
|
1078
|
-
# For hotkey_block_emission calculation
|
1079
|
-
emission_sum = sum(
|
1080
|
-
[
|
1081
|
-
subnet_state.emission[idx].tao
|
1082
|
-
for idx in range(len(subnet_state.emission))
|
1083
|
-
]
|
1084
|
-
)
|
1085
|
-
|
1086
1065
|
# For table footers
|
1087
1066
|
alpha_sum = sum(
|
1088
1067
|
[
|
@@ -1102,7 +1081,16 @@ async def show(
|
|
1102
1081
|
for idx in range(len(subnet_state.tao_stake))
|
1103
1082
|
]
|
1104
1083
|
)
|
1105
|
-
|
1084
|
+
dividends_sum = sum(
|
1085
|
+
subnet_state.dividends[idx] for idx in range(len(subnet_state.dividends))
|
1086
|
+
)
|
1087
|
+
emission_sum = sum(
|
1088
|
+
[
|
1089
|
+
subnet_state.emission[idx].tao
|
1090
|
+
for idx in range(len(subnet_state.emission))
|
1091
|
+
]
|
1092
|
+
)
|
1093
|
+
|
1106
1094
|
owner_hotkeys = await subtensor.get_owned_hotkeys(subnet_info.owner_coldkey)
|
1107
1095
|
if subnet_info.owner_hotkey not in owner_hotkeys:
|
1108
1096
|
owner_hotkeys.append(subnet_info.owner_hotkey)
|
@@ -1118,25 +1106,24 @@ async def show(
|
|
1118
1106
|
sorted_indices = sorted(
|
1119
1107
|
range(len(subnet_state.hotkeys)),
|
1120
1108
|
key=lambda i: (
|
1121
|
-
#
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1109
|
+
# If sort is True, sort only by UIDs
|
1110
|
+
i
|
1111
|
+
if sort
|
1112
|
+
else (
|
1113
|
+
# Otherwise
|
1114
|
+
# Sort by owner status first
|
1115
|
+
not (
|
1116
|
+
subnet_state.coldkeys[i] == subnet_info.owner_coldkey
|
1117
|
+
or subnet_state.hotkeys[i] in owner_hotkeys
|
1118
|
+
),
|
1119
|
+
# Then sort by stake amount (higher stakes first)
|
1120
|
+
-subnet_state.total_stake[i].tao,
|
1121
|
+
)
|
1128
1122
|
),
|
1129
1123
|
)
|
1130
1124
|
|
1131
1125
|
rows = []
|
1132
1126
|
for idx in sorted_indices:
|
1133
|
-
hotkey_block_emission = (
|
1134
|
-
subnet_state.emission[idx].tao / emission_sum
|
1135
|
-
if emission_sum != 0
|
1136
|
-
else 0
|
1137
|
-
)
|
1138
|
-
relative_emissions_sum += hotkey_block_emission
|
1139
|
-
|
1140
1127
|
# Get identity for this uid
|
1141
1128
|
coldkey_identity = identities.get(subnet_state.coldkeys[idx], {}).get(
|
1142
1129
|
"name", ""
|
@@ -1175,11 +1162,9 @@ async def show(
|
|
1175
1162
|
f"τ {tao_stake.tao:.4f}"
|
1176
1163
|
if verbose
|
1177
1164
|
else f"τ {millify_tao(tao_stake)}", # Tao Stake
|
1178
|
-
|
1179
|
-
f"{
|
1180
|
-
f"{subnet_state.
|
1181
|
-
# f"{Balance.from_tao(hotkey_block_emission).set_unit(netuid_).tao:.5f}", # Emissions relative
|
1182
|
-
f"{Balance.from_tao(subnet_state.emission[idx].tao).set_unit(netuid_).tao:.5f} {subnet_info.symbol}", # Emissions
|
1165
|
+
f"{subnet_state.dividends[idx]:.6f}", # Dividends
|
1166
|
+
f"{subnet_state.incentives[idx]:.6f}", # Incentive
|
1167
|
+
f"{Balance.from_tao(subnet_state.emission[idx].tao).set_unit(netuid_).tao:.6f} {subnet_info.symbol}", # Emissions
|
1183
1168
|
f"{subnet_state.hotkeys[idx][:6]}"
|
1184
1169
|
if not verbose
|
1185
1170
|
else f"{subnet_state.hotkeys[idx]}", # Hotkey
|
@@ -1201,7 +1186,6 @@ async def show(
|
|
1201
1186
|
if verbose
|
1202
1187
|
else f"{millify_tao(stake_sum)} {subnet_info.symbol}",
|
1203
1188
|
)
|
1204
|
-
# ------- Temporary columns for testing -------
|
1205
1189
|
table.add_column(
|
1206
1190
|
f"Alpha ({Balance.get_unit(netuid_)})",
|
1207
1191
|
style=COLOR_PALETTE["POOLS"]["EXTRA_2"],
|
@@ -1220,24 +1204,14 @@ async def show(
|
|
1220
1204
|
if verbose
|
1221
1205
|
else f"{millify_tao(tao_sum)} {subnet_info.symbol}",
|
1222
1206
|
)
|
1223
|
-
# ------- End Temporary columns for testing -------
|
1224
1207
|
table.add_column(
|
1225
1208
|
"Dividends",
|
1226
1209
|
style=COLOR_PALETTE["POOLS"]["EMISSION"],
|
1227
1210
|
no_wrap=True,
|
1228
1211
|
justify="center",
|
1229
|
-
footer=f"{
|
1212
|
+
footer=f"{dividends_sum:.3f}",
|
1230
1213
|
)
|
1231
1214
|
table.add_column("Incentive", style="#5fd7ff", no_wrap=True, justify="center")
|
1232
|
-
|
1233
|
-
# Hiding relative emissions for now
|
1234
|
-
# table.add_column(
|
1235
|
-
# "Emissions",
|
1236
|
-
# style="light_goldenrod2",
|
1237
|
-
# no_wrap=True,
|
1238
|
-
# justify="center",
|
1239
|
-
# footer=f"{relative_emissions_sum:.3f}",
|
1240
|
-
# )
|
1241
1215
|
table.add_column(
|
1242
1216
|
f"Emissions ({Balance.get_unit(netuid_)})",
|
1243
1217
|
style=COLOR_PALETTE["POOLS"]["EMISSION"],
|
@@ -1349,7 +1323,7 @@ async def show(
|
|
1349
1323
|
return hotkey
|
1350
1324
|
else:
|
1351
1325
|
console.print(
|
1352
|
-
|
1326
|
+
"[red]Invalid UID. Please enter a valid UID from the table above[/red]"
|
1353
1327
|
)
|
1354
1328
|
except ValueError:
|
1355
1329
|
console.print("[red]Please enter a valid number[/red]")
|
@@ -2053,3 +2027,146 @@ async def metagraph_cmd(
|
|
2053
2027
|
table.add_row(*row)
|
2054
2028
|
|
2055
2029
|
console.print(table)
|
2030
|
+
|
2031
|
+
|
2032
|
+
def create_identity_table(title: str = None):
|
2033
|
+
if not title:
|
2034
|
+
title = "Subnet Identity"
|
2035
|
+
|
2036
|
+
table = Table(
|
2037
|
+
Column(
|
2038
|
+
"Item",
|
2039
|
+
justify="right",
|
2040
|
+
style=COLOR_PALETTE["GENERAL"]["SUBHEADING_MAIN"],
|
2041
|
+
no_wrap=True,
|
2042
|
+
),
|
2043
|
+
Column("Value", style=COLOR_PALETTE["GENERAL"]["SUBHEADING"]),
|
2044
|
+
title=f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]{title}\n",
|
2045
|
+
show_footer=True,
|
2046
|
+
show_edge=False,
|
2047
|
+
header_style="bold white",
|
2048
|
+
border_style="bright_black",
|
2049
|
+
style="bold",
|
2050
|
+
title_justify="center",
|
2051
|
+
show_lines=False,
|
2052
|
+
pad_edge=True,
|
2053
|
+
)
|
2054
|
+
return table
|
2055
|
+
|
2056
|
+
|
2057
|
+
async def set_identity(
|
2058
|
+
wallet: "Wallet",
|
2059
|
+
subtensor: "SubtensorInterface",
|
2060
|
+
netuid: int,
|
2061
|
+
subnet_identity: dict,
|
2062
|
+
prompt: bool = False,
|
2063
|
+
) -> bool:
|
2064
|
+
"""Set identity information for a subnet"""
|
2065
|
+
|
2066
|
+
if not await subtensor.subnet_exists(netuid):
|
2067
|
+
err_console.print(f"Subnet {netuid} does not exist")
|
2068
|
+
return False
|
2069
|
+
|
2070
|
+
identity_data = {
|
2071
|
+
"netuid": netuid,
|
2072
|
+
"subnet_name": subnet_identity.get("subnet_name", ""),
|
2073
|
+
"github_repo": subnet_identity.get("github_repo", ""),
|
2074
|
+
"subnet_contact": subnet_identity.get("subnet_contact", ""),
|
2075
|
+
"subnet_url": subnet_identity.get("subnet_url", ""),
|
2076
|
+
"discord": subnet_identity.get("discord", ""),
|
2077
|
+
"description": subnet_identity.get("description", ""),
|
2078
|
+
"additional": subnet_identity.get("additional", ""),
|
2079
|
+
}
|
2080
|
+
|
2081
|
+
if not unlock_key(wallet).success:
|
2082
|
+
return False
|
2083
|
+
|
2084
|
+
if prompt:
|
2085
|
+
if not Confirm.ask(
|
2086
|
+
"Are you sure you want to set subnet's identity? This is subject to a fee."
|
2087
|
+
):
|
2088
|
+
return False
|
2089
|
+
|
2090
|
+
call = await subtensor.substrate.compose_call(
|
2091
|
+
call_module="SubtensorModule",
|
2092
|
+
call_function="set_subnet_identity",
|
2093
|
+
call_params=identity_data,
|
2094
|
+
)
|
2095
|
+
|
2096
|
+
with console.status(
|
2097
|
+
" :satellite: [dark_sea_green3]Setting subnet identity on-chain...",
|
2098
|
+
spinner="earth",
|
2099
|
+
):
|
2100
|
+
success, err_msg = await subtensor.sign_and_send_extrinsic(call, wallet)
|
2101
|
+
|
2102
|
+
if not success:
|
2103
|
+
err_console.print(f"[red]:cross_mark: Failed![/red] {err_msg}")
|
2104
|
+
return False
|
2105
|
+
|
2106
|
+
console.print(
|
2107
|
+
":white_heavy_check_mark: [dark_sea_green3]Successfully set subnet identity\n"
|
2108
|
+
)
|
2109
|
+
|
2110
|
+
subnet = await subtensor.subnet(netuid)
|
2111
|
+
identity = subnet.subnet_identity if subnet else None
|
2112
|
+
|
2113
|
+
if identity:
|
2114
|
+
table = create_identity_table(title=f"New Subnet {netuid} Identity")
|
2115
|
+
table.add_row("Netuid", str(netuid))
|
2116
|
+
for key in [
|
2117
|
+
"subnet_name",
|
2118
|
+
"github_repo",
|
2119
|
+
"subnet_contact",
|
2120
|
+
"subnet_url",
|
2121
|
+
"discord",
|
2122
|
+
"description",
|
2123
|
+
"additional",
|
2124
|
+
]:
|
2125
|
+
value = getattr(identity, key, None)
|
2126
|
+
table.add_row(key, str(value) if value else "~")
|
2127
|
+
console.print(table)
|
2128
|
+
|
2129
|
+
return True
|
2130
|
+
|
2131
|
+
|
2132
|
+
async def get_identity(subtensor: "SubtensorInterface", netuid: int, title: str = None):
|
2133
|
+
"""Fetch and display existing subnet identity information."""
|
2134
|
+
if not title:
|
2135
|
+
title = "Subnet Identity"
|
2136
|
+
|
2137
|
+
if not await subtensor.subnet_exists(netuid):
|
2138
|
+
print_error(
|
2139
|
+
f"Subnet {netuid} does not exist."
|
2140
|
+
)
|
2141
|
+
raise typer.Exit()
|
2142
|
+
|
2143
|
+
with console.status(
|
2144
|
+
":satellite: [bold green]Querying subnet identity...", spinner="earth"
|
2145
|
+
):
|
2146
|
+
subnet = await subtensor.subnet(netuid)
|
2147
|
+
identity = subnet.subnet_identity if subnet else None
|
2148
|
+
|
2149
|
+
if not identity:
|
2150
|
+
err_console.print(
|
2151
|
+
f"Existing subnet identity not found"
|
2152
|
+
f" for subnet [blue]{netuid}[/blue]"
|
2153
|
+
f" on {subtensor}"
|
2154
|
+
)
|
2155
|
+
return {}
|
2156
|
+
|
2157
|
+
if identity:
|
2158
|
+
table = create_identity_table(title=f"Current Subnet {netuid} Identity")
|
2159
|
+
table.add_row("Netuid", str(netuid))
|
2160
|
+
for key in [
|
2161
|
+
"subnet_name",
|
2162
|
+
"github_repo",
|
2163
|
+
"subnet_contact",
|
2164
|
+
"subnet_url",
|
2165
|
+
"discord",
|
2166
|
+
"description",
|
2167
|
+
"additional",
|
2168
|
+
]:
|
2169
|
+
value = getattr(identity, key, None)
|
2170
|
+
table.add_row(key, str(value) if value else "~")
|
2171
|
+
console.print(table)
|
2172
|
+
return identity
|
@@ -3,7 +3,6 @@ from typing import TYPE_CHECKING, Union, Optional
|
|
3
3
|
|
4
4
|
import typer
|
5
5
|
from bittensor_wallet import Wallet
|
6
|
-
from bittensor_wallet.errors import KeyFileError
|
7
6
|
from rich import box
|
8
7
|
from rich.table import Column, Table
|
9
8
|
from rich.prompt import Confirm
|
@@ -17,6 +16,8 @@ from bittensor_cli.src.bittensor.utils import (
|
|
17
16
|
print_error,
|
18
17
|
print_verbose,
|
19
18
|
normalize_hyperparameters,
|
19
|
+
unlock_key,
|
20
|
+
blocks_to_duration,
|
20
21
|
)
|
21
22
|
|
22
23
|
if TYPE_CHECKING:
|
@@ -106,13 +107,10 @@ async def set_hyperparameter_extrinsic(
|
|
106
107
|
)
|
107
108
|
return False
|
108
109
|
|
109
|
-
|
110
|
-
wallet.unlock_coldkey()
|
111
|
-
except KeyFileError:
|
112
|
-
err_console.print("Error decrypting coldkey (possibly incorrect password)")
|
110
|
+
if not unlock_key(wallet).success:
|
113
111
|
return False
|
114
112
|
|
115
|
-
extrinsic = HYPERPARAMS.get(parameter)
|
113
|
+
extrinsic, sudo_ = HYPERPARAMS.get(parameter, ("", False))
|
116
114
|
if extrinsic is None:
|
117
115
|
err_console.print(":cross_mark: [red]Invalid hyperparameter specified.[/red]")
|
118
116
|
return False
|
@@ -152,11 +150,17 @@ async def set_hyperparameter_extrinsic(
|
|
152
150
|
call_params[str(value_argument["name"])] = value
|
153
151
|
|
154
152
|
# create extrinsic call
|
155
|
-
|
153
|
+
call_ = await substrate.compose_call(
|
156
154
|
call_module="AdminUtils",
|
157
155
|
call_function=extrinsic,
|
158
156
|
call_params=call_params,
|
159
157
|
)
|
158
|
+
if sudo_:
|
159
|
+
call = await substrate.compose_call(
|
160
|
+
call_module="Sudo", call_function="sudo", call_params={"call": call_}
|
161
|
+
)
|
162
|
+
else:
|
163
|
+
call = call_
|
160
164
|
success, err_msg = await subtensor.sign_and_send_extrinsic(
|
161
165
|
call, wallet, wait_for_inclusion, wait_for_finalization
|
162
166
|
)
|
@@ -266,14 +270,22 @@ def format_call_data(call_data: dict) -> str:
|
|
266
270
|
call_info = call_details[0]
|
267
271
|
call_function, call_args = next(iter(call_info.items()))
|
268
272
|
|
269
|
-
#
|
270
|
-
formatted_args =
|
271
|
-
|
272
|
-
|
273
|
-
|
273
|
+
# Format arguments, handle nested/large payloads
|
274
|
+
formatted_args = []
|
275
|
+
for arg_name, arg_value in call_args.items():
|
276
|
+
if isinstance(arg_value, (tuple, list, dict)):
|
277
|
+
# For large nested, show abbreviated version
|
278
|
+
content_str = str(arg_value)
|
279
|
+
if len(content_str) > 20:
|
280
|
+
formatted_args.append(f"{arg_name}: ... [{len(content_str)}] ...")
|
281
|
+
else:
|
282
|
+
formatted_args.append(f"{arg_name}: {arg_value}")
|
283
|
+
else:
|
284
|
+
formatted_args.append(f"{arg_name}: {arg_value}")
|
274
285
|
|
275
286
|
# Format the final output string
|
276
|
-
|
287
|
+
args_str = ", ".join(formatted_args)
|
288
|
+
return f"{module}.{call_function}({args_str})"
|
277
289
|
|
278
290
|
|
279
291
|
def _validate_proposal_hash(proposal_hash: str) -> bool:
|
@@ -464,19 +476,20 @@ async def sudo_set_hyperparameter(
|
|
464
476
|
|
465
477
|
normalized_value: Union[str, bool]
|
466
478
|
if param_name in [
|
467
|
-
"
|
479
|
+
"registration_allowed",
|
468
480
|
"network_pow_registration_allowed",
|
469
481
|
"commit_reveal_weights_enabled",
|
470
482
|
"liquid_alpha_enabled",
|
471
483
|
]:
|
472
|
-
normalized_value = param_value.lower() in ["true", "1"]
|
484
|
+
normalized_value = param_value.lower() in ["true", "True", "1"]
|
473
485
|
else:
|
474
486
|
normalized_value = param_value
|
475
487
|
|
476
488
|
is_allowed_value, value = allowed_value(param_name, normalized_value)
|
477
489
|
if not is_allowed_value:
|
478
490
|
err_console.print(
|
479
|
-
f"Hyperparameter {param_name} value is not within bounds.
|
491
|
+
f"Hyperparameter [dark_orange]{param_name}[/dark_orange] value is not within bounds. "
|
492
|
+
f"Value is {normalized_value} but must be {value}"
|
480
493
|
)
|
481
494
|
return
|
482
495
|
|
@@ -572,24 +585,30 @@ async def get_senate(subtensor: "SubtensorInterface"):
|
|
572
585
|
return console.print(table)
|
573
586
|
|
574
587
|
|
575
|
-
async def proposals(subtensor: "SubtensorInterface"):
|
588
|
+
async def proposals(subtensor: "SubtensorInterface", verbose: bool):
|
576
589
|
console.print(
|
577
590
|
":satellite: Syncing with chain: [white]{}[/white] ...".format(
|
578
591
|
subtensor.network
|
579
592
|
)
|
580
593
|
)
|
581
|
-
print_verbose("Fetching senate members & proposals")
|
582
594
|
block_hash = await subtensor.substrate.get_chain_head()
|
583
|
-
senate_members, all_proposals = await asyncio.gather(
|
595
|
+
senate_members, all_proposals, current_block = await asyncio.gather(
|
584
596
|
_get_senate_members(subtensor, block_hash),
|
585
597
|
_get_proposals(subtensor, block_hash),
|
598
|
+
subtensor.substrate.get_block_number(block_hash),
|
586
599
|
)
|
587
600
|
|
588
|
-
print_verbose("Fetching member information from Chain")
|
589
601
|
registered_delegate_info: dict[
|
590
602
|
str, DelegatesDetails
|
591
603
|
] = await subtensor.get_delegate_identities()
|
592
604
|
|
605
|
+
title = (
|
606
|
+
f"[bold #4196D6]Bittensor Governance Proposals[/bold #4196D6]\n"
|
607
|
+
f"[steel_blue3]Current Block:[/steel_blue3] {current_block}\t"
|
608
|
+
f"[steel_blue3]Network:[/steel_blue3] {subtensor.network}\n\n"
|
609
|
+
f"[steel_blue3]Active Proposals:[/steel_blue3] {len(all_proposals)}\t"
|
610
|
+
f"[steel_blue3]Senate Size:[/steel_blue3] {len(senate_members)}\n"
|
611
|
+
)
|
593
612
|
table = Table(
|
594
613
|
Column(
|
595
614
|
"[white]HASH",
|
@@ -604,8 +623,8 @@ async def proposals(subtensor: "SubtensorInterface"):
|
|
604
623
|
style="rgb(50,163,219)",
|
605
624
|
),
|
606
625
|
Column("[white]END", style="bright_cyan"),
|
607
|
-
Column("[white]CALLDATA", style="dark_sea_green"),
|
608
|
-
title=
|
626
|
+
Column("[white]CALLDATA", style="dark_sea_green", width=30),
|
627
|
+
title=title,
|
609
628
|
show_footer=True,
|
610
629
|
box=box.SIMPLE_HEAVY,
|
611
630
|
pad_edge=False,
|
@@ -613,16 +632,36 @@ async def proposals(subtensor: "SubtensorInterface"):
|
|
613
632
|
border_style="bright_black",
|
614
633
|
)
|
615
634
|
for hash_, (call_data, vote_data) in all_proposals.items():
|
635
|
+
blocks_remaining = vote_data.end - current_block
|
636
|
+
if blocks_remaining > 0:
|
637
|
+
duration_str = blocks_to_duration(blocks_remaining)
|
638
|
+
vote_end_cell = f"{vote_data.end} [dim](in {duration_str})[/dim]"
|
639
|
+
else:
|
640
|
+
vote_end_cell = f"{vote_data.end} [red](expired)[/red]"
|
641
|
+
|
642
|
+
ayes_threshold = (
|
643
|
+
(len(vote_data.ayes) / vote_data.threshold * 100)
|
644
|
+
if vote_data.threshold > 0
|
645
|
+
else 0
|
646
|
+
)
|
647
|
+
nays_threshold = (
|
648
|
+
(len(vote_data.nays) / vote_data.threshold * 100)
|
649
|
+
if vote_data.threshold > 0
|
650
|
+
else 0
|
651
|
+
)
|
616
652
|
table.add_row(
|
617
|
-
hash_,
|
653
|
+
hash_ if verbose else f"{hash_[:4]}...{hash_[-4:]}",
|
618
654
|
str(vote_data.threshold),
|
619
|
-
|
620
|
-
|
655
|
+
f"{len(vote_data.ayes)} ({ayes_threshold:.2f}%)",
|
656
|
+
f"{len(vote_data.nays)} ({nays_threshold:.2f}%)",
|
621
657
|
display_votes(vote_data, registered_delegate_info),
|
622
|
-
|
658
|
+
vote_end_cell,
|
623
659
|
format_call_data(call_data),
|
624
660
|
)
|
625
|
-
|
661
|
+
console.print(table)
|
662
|
+
console.print(
|
663
|
+
"\n[dim]* Both Ayes and Nays percentages are calculated relative to the proposal's threshold.[/dim]"
|
664
|
+
)
|
626
665
|
|
627
666
|
|
628
667
|
async def senate_vote(
|
@@ -653,10 +692,7 @@ async def senate_vote(
|
|
653
692
|
return False
|
654
693
|
|
655
694
|
# Unlock the wallet.
|
656
|
-
|
657
|
-
wallet.unlock_hotkey()
|
658
|
-
wallet.unlock_coldkey()
|
659
|
-
except KeyFileError:
|
695
|
+
if not unlock_key(wallet, "hot").success and unlock_key(wallet, "cold").success:
|
660
696
|
return False
|
661
697
|
|
662
698
|
console.print(f"Fetching proposals in [dark_orange]network: {subtensor.network}")
|
@@ -732,10 +768,7 @@ async def set_take(
|
|
732
768
|
f"Setting take on [{COLOR_PALETTE['GENERAL']['LINKS']}]network: {subtensor.network}"
|
733
769
|
)
|
734
770
|
|
735
|
-
|
736
|
-
wallet.unlock_hotkey()
|
737
|
-
wallet.unlock_coldkey()
|
738
|
-
except KeyFileError:
|
771
|
+
if not unlock_key(wallet, "hot").success and unlock_key(wallet, "cold").success:
|
739
772
|
return False
|
740
773
|
|
741
774
|
result_ = await _do_set_take()
|