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.
@@ -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.018
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, substrate)}"
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.emission.tao
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(float(subnet.emission.tao) for subnet in subnets if subnet.netuid != 0),
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.emission.tao
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
- float(subnet.emission.tao) for subnet in subnets if subnet.netuid != 0
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
- relative_emissions_sum = 0
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
- # Sort by owner status first
1122
- not (
1123
- subnet_state.coldkeys[i] == subnet_info.owner_coldkey
1124
- or subnet_state.hotkeys[i] in owner_hotkeys
1125
- ),
1126
- # Then sort by stake amount (higher stakes first)
1127
- -subnet_state.total_stake[i].tao,
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
- # str(subnet_state.dividends[idx]),
1179
- f"{Balance.from_tao(hotkey_block_emission).set_unit(netuid_).tao:.5f}", # Dividends
1180
- f"{subnet_state.incentives[idx]:.4f}", # Incentive
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"{relative_emissions_sum:.3f}",
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
- f"[red]Invalid UID. Please enter a valid UID from the table above[/red]"
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
- try:
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
- call = await substrate.compose_call(
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
- # Extract the argument, handling tuple values
270
- formatted_args = ", ".join(
271
- str(arg[0]) if isinstance(arg, tuple) else str(arg)
272
- for arg in call_args.values()
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
- return f"{call_function}({formatted_args})"
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
- "network_registration_allowed",
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. Value is {normalized_value} but must be {value}"
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=f"\n[dark_orange]Proposals\t\t\nActive Proposals: {len(all_proposals)}\t\tSenate Size: {len(senate_members)}\nNetwork: {subtensor.network}",
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
- str(len(vote_data.ayes)),
620
- str(len(vote_data.nays)),
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
- str(vote_data.end),
658
+ vote_end_cell,
623
659
  format_call_data(call_data),
624
660
  )
625
- return console.print(table)
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
- try:
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
- try:
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()