bittensor-cli 9.1.4__py3-none-any.whl → 9.3.0__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/cli.py +525 -131
- bittensor_cli/src/__init__.py +444 -465
- bittensor_cli/src/bittensor/chain_data.py +6 -2
- bittensor_cli/src/bittensor/extrinsics/registration.py +47 -23
- bittensor_cli/src/bittensor/extrinsics/root.py +10 -11
- bittensor_cli/src/bittensor/extrinsics/transfer.py +5 -3
- bittensor_cli/src/bittensor/subtensor_interface.py +125 -5
- bittensor_cli/src/bittensor/utils.py +4 -1
- bittensor_cli/src/commands/stake/add.py +169 -108
- bittensor_cli/src/commands/stake/children_hotkeys.py +120 -79
- bittensor_cli/src/commands/stake/list.py +54 -20
- bittensor_cli/src/commands/stake/move.py +58 -18
- bittensor_cli/src/commands/stake/remove.py +174 -92
- bittensor_cli/src/commands/subnets/price.py +11 -9
- bittensor_cli/src/commands/subnets/subnets.py +223 -80
- bittensor_cli/src/commands/sudo.py +76 -22
- bittensor_cli/src/commands/wallets.py +656 -40
- bittensor_cli/src/commands/weights.py +21 -11
- bittensor_cli/version.py +2 -1
- {bittensor_cli-9.1.4.dist-info → bittensor_cli-9.3.0.dist-info}/METADATA +30 -11
- bittensor_cli-9.3.0.dist-info/RECORD +35 -0
- {bittensor_cli-9.1.4.dist-info → bittensor_cli-9.3.0.dist-info}/WHEEL +1 -1
- bittensor_cli-9.1.4.dist-info/RECORD +0 -35
- {bittensor_cli-9.1.4.dist-info → bittensor_cli-9.3.0.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-9.1.4.dist-info → bittensor_cli-9.3.0.dist-info}/top_level.txt +0 -0
@@ -34,6 +34,7 @@ from bittensor_cli.src.bittensor.utils import (
|
|
34
34
|
prompt_for_identity,
|
35
35
|
get_subnet_name,
|
36
36
|
unlock_key,
|
37
|
+
json_console,
|
37
38
|
)
|
38
39
|
|
39
40
|
if TYPE_CHECKING:
|
@@ -51,7 +52,7 @@ async def register_subnetwork_extrinsic(
|
|
51
52
|
wait_for_inclusion: bool = False,
|
52
53
|
wait_for_finalization: bool = True,
|
53
54
|
prompt: bool = False,
|
54
|
-
) -> bool:
|
55
|
+
) -> tuple[bool, Optional[int]]:
|
55
56
|
"""Registers a new subnetwork.
|
56
57
|
|
57
58
|
wallet (bittensor.wallet):
|
@@ -100,7 +101,7 @@ async def register_subnetwork_extrinsic(
|
|
100
101
|
f"[{COLOR_PALETTE['POOLS']['TAO']}]{sn_burn_cost}[{COLOR_PALETTE['POOLS']['TAO']}] "
|
101
102
|
f"to register a subnet."
|
102
103
|
)
|
103
|
-
return False
|
104
|
+
return False, None
|
104
105
|
|
105
106
|
if prompt:
|
106
107
|
console.print(
|
@@ -109,7 +110,7 @@ async def register_subnetwork_extrinsic(
|
|
109
110
|
if not Confirm.ask(
|
110
111
|
f"Do you want to burn [{COLOR_PALETTE['POOLS']['TAO']}]{sn_burn_cost} to register a subnet?"
|
111
112
|
):
|
112
|
-
return False
|
113
|
+
return False, None
|
113
114
|
|
114
115
|
call_params = {
|
115
116
|
"hotkey": wallet.hotkey.ss58_address,
|
@@ -151,10 +152,10 @@ async def register_subnetwork_extrinsic(
|
|
151
152
|
f"[red]Error:[/red] Identity field [white]{field}[/white] must be <= {max_size} bytes.\n"
|
152
153
|
f"Value '{value.decode()}' is {len(value)} bytes."
|
153
154
|
)
|
154
|
-
return False
|
155
|
+
return False, None
|
155
156
|
|
156
157
|
if not unlock_key(wallet).success:
|
157
|
-
return False
|
158
|
+
return False, None
|
158
159
|
|
159
160
|
with console.status(":satellite: Registering subnet...", spinner="earth"):
|
160
161
|
substrate = subtensor.substrate
|
@@ -175,15 +176,14 @@ async def register_subnetwork_extrinsic(
|
|
175
176
|
|
176
177
|
# We only wait here if we expect finalization.
|
177
178
|
if not wait_for_finalization and not wait_for_inclusion:
|
178
|
-
return True
|
179
|
+
return True, None
|
179
180
|
|
180
|
-
await response.process_events()
|
181
181
|
if not await response.is_success:
|
182
182
|
err_console.print(
|
183
183
|
f":cross_mark: [red]Failed[/red]: {format_error_message(await response.error_message)}"
|
184
184
|
)
|
185
185
|
await asyncio.sleep(0.5)
|
186
|
-
return False
|
186
|
+
return False, None
|
187
187
|
|
188
188
|
# Successful registration, final check for membership
|
189
189
|
else:
|
@@ -193,7 +193,7 @@ async def register_subnetwork_extrinsic(
|
|
193
193
|
console.print(
|
194
194
|
f":white_heavy_check_mark: [dark_sea_green3]Registered subnetwork with netuid: {attributes[0]}"
|
195
195
|
)
|
196
|
-
return True
|
196
|
+
return True, int(attributes[0])
|
197
197
|
|
198
198
|
|
199
199
|
# commands
|
@@ -206,40 +206,41 @@ async def subnets_list(
|
|
206
206
|
no_cache: bool,
|
207
207
|
verbose: bool,
|
208
208
|
live: bool,
|
209
|
+
json_output: bool,
|
209
210
|
):
|
210
211
|
"""List all subnet netuids in the network."""
|
211
212
|
|
212
213
|
async def fetch_subnet_data():
|
213
|
-
|
214
|
-
|
214
|
+
block_number_ = await subtensor.substrate.get_block_number(None)
|
215
|
+
subnets_ = await subtensor.all_subnets()
|
215
216
|
|
216
217
|
# Sort subnets by market cap, keeping the root subnet in the first position
|
217
|
-
root_subnet = next(s for s in
|
218
|
+
root_subnet = next(s for s in subnets_ if s.netuid == 0)
|
218
219
|
other_subnets = sorted(
|
219
|
-
[s for s in
|
220
|
+
[s for s in subnets_ if s.netuid != 0],
|
220
221
|
key=lambda x: (x.alpha_in.tao + x.alpha_out.tao) * x.price.tao,
|
221
222
|
reverse=True,
|
222
223
|
)
|
223
224
|
sorted_subnets = [root_subnet] + other_subnets
|
224
|
-
return sorted_subnets,
|
225
|
+
return sorted_subnets, block_number_
|
225
226
|
|
226
227
|
def calculate_emission_stats(
|
227
|
-
|
228
|
+
subnets_: list, block_number_: int
|
228
229
|
) -> tuple[Balance, str]:
|
229
230
|
# We do not include the root subnet in the emission calculation
|
230
231
|
total_tao_emitted = sum(
|
231
|
-
subnet.tao_in.tao for subnet in
|
232
|
+
subnet.tao_in.tao for subnet in subnets_ if subnet.netuid != 0
|
232
233
|
)
|
233
|
-
emission_percentage = (total_tao_emitted /
|
234
|
+
emission_percentage = (total_tao_emitted / block_number_) * 100
|
234
235
|
percentage_color = "dark_sea_green" if emission_percentage < 100 else "red"
|
235
236
|
formatted_percentage = (
|
236
237
|
f"[{percentage_color}]{emission_percentage:.2f}%[/{percentage_color}]"
|
237
238
|
)
|
238
239
|
if not verbose:
|
239
|
-
percentage_string = f"τ {millify_tao(total_tao_emitted)}/{millify_tao(
|
240
|
+
percentage_string = f"τ {millify_tao(total_tao_emitted)}/{millify_tao(block_number_)} ({formatted_percentage})"
|
240
241
|
else:
|
241
242
|
percentage_string = (
|
242
|
-
f"τ {total_tao_emitted:.1f}/{
|
243
|
+
f"τ {total_tao_emitted:.1f}/{block_number_} ({formatted_percentage})"
|
243
244
|
)
|
244
245
|
return total_tao_emitted, percentage_string
|
245
246
|
|
@@ -249,7 +250,7 @@ async def subnets_list(
|
|
249
250
|
total_netuids: int,
|
250
251
|
tao_emission_percentage: str,
|
251
252
|
):
|
252
|
-
|
253
|
+
defined_table = Table(
|
253
254
|
title=f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]Subnets"
|
254
255
|
f"\nNetwork: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]{subtensor.network}\n\n",
|
255
256
|
show_footer=True,
|
@@ -262,61 +263,61 @@ async def subnets_list(
|
|
262
263
|
pad_edge=True,
|
263
264
|
)
|
264
265
|
|
265
|
-
|
266
|
+
defined_table.add_column(
|
266
267
|
"[bold white]Netuid",
|
267
268
|
style="grey89",
|
268
269
|
justify="center",
|
269
270
|
footer=str(total_netuids),
|
270
271
|
)
|
271
|
-
|
272
|
-
|
272
|
+
defined_table.add_column("[bold white]Name", style="cyan", justify="left")
|
273
|
+
defined_table.add_column(
|
273
274
|
f"[bold white]Price \n({Balance.get_unit(0)}_in/{Balance.get_unit(1)}_in)",
|
274
275
|
style="dark_sea_green2",
|
275
276
|
justify="left",
|
276
277
|
footer=f"τ {total_rate}",
|
277
278
|
)
|
278
|
-
|
279
|
+
defined_table.add_column(
|
279
280
|
f"[bold white]Market Cap \n({Balance.get_unit(1)} * Price)",
|
280
281
|
style="steel_blue3",
|
281
282
|
justify="left",
|
282
283
|
)
|
283
|
-
|
284
|
+
defined_table.add_column(
|
284
285
|
f"[bold white]Emission ({Balance.get_unit(0)})",
|
285
286
|
style=COLOR_PALETTE["POOLS"]["EMISSION"],
|
286
287
|
justify="left",
|
287
288
|
footer=f"τ {total_emissions}",
|
288
289
|
)
|
289
|
-
|
290
|
+
defined_table.add_column(
|
290
291
|
f"[bold white]P ({Balance.get_unit(0)}_in, {Balance.get_unit(1)}_in)",
|
291
292
|
style=COLOR_PALETTE["STAKE"]["TAO"],
|
292
293
|
justify="left",
|
293
294
|
footer=f"{tao_emission_percentage}",
|
294
295
|
)
|
295
|
-
|
296
|
+
defined_table.add_column(
|
296
297
|
f"[bold white]Stake ({Balance.get_unit(1)}_out)",
|
297
298
|
style=COLOR_PALETTE["STAKE"]["STAKE_ALPHA"],
|
298
299
|
justify="left",
|
299
300
|
)
|
300
|
-
|
301
|
+
defined_table.add_column(
|
301
302
|
f"[bold white]Supply ({Balance.get_unit(1)})",
|
302
303
|
style=COLOR_PALETTE["POOLS"]["ALPHA_IN"],
|
303
304
|
justify="left",
|
304
305
|
)
|
305
306
|
|
306
|
-
|
307
|
+
defined_table.add_column(
|
307
308
|
"[bold white]Tempo (k/n)",
|
308
309
|
style=COLOR_PALETTE["GENERAL"]["TEMPO"],
|
309
310
|
justify="left",
|
310
311
|
overflow="fold",
|
311
312
|
)
|
312
|
-
return
|
313
|
+
return defined_table
|
313
314
|
|
314
315
|
# Non-live mode
|
315
|
-
def
|
316
|
+
def _create_table(subnets_, block_number_):
|
316
317
|
rows = []
|
317
|
-
_, percentage_string = calculate_emission_stats(
|
318
|
+
_, percentage_string = calculate_emission_stats(subnets_, block_number_)
|
318
319
|
|
319
|
-
for subnet in
|
320
|
+
for subnet in subnets_:
|
320
321
|
netuid = subnet.netuid
|
321
322
|
symbol = f"{subnet.symbol}\u200e"
|
322
323
|
|
@@ -363,7 +364,7 @@ async def subnets_list(
|
|
363
364
|
# Prepare cells
|
364
365
|
netuid_cell = str(netuid)
|
365
366
|
subnet_name_cell = (
|
366
|
-
f"[{COLOR_PALETTE
|
367
|
+
f"[{COLOR_PALETTE.G.SYM}]{subnet.symbol if netuid != 0 else 'τ'}[/{COLOR_PALETTE.G.SYM}]"
|
367
368
|
f" {get_subnet_name(subnet)}"
|
368
369
|
)
|
369
370
|
emission_cell = f"τ {emission_tao:,.4f}"
|
@@ -396,23 +397,76 @@ async def subnets_list(
|
|
396
397
|
)
|
397
398
|
|
398
399
|
total_emissions = round(
|
399
|
-
sum(
|
400
|
+
sum(
|
401
|
+
subnet.tao_in_emission.tao for subnet in subnets_ if subnet.netuid != 0
|
402
|
+
),
|
400
403
|
4,
|
401
404
|
)
|
402
405
|
total_rate = round(
|
403
|
-
sum(float(subnet.price.tao) for subnet in
|
406
|
+
sum(float(subnet.price.tao) for subnet in subnets_ if subnet.netuid != 0), 4
|
404
407
|
)
|
405
|
-
total_netuids = len(
|
406
|
-
|
408
|
+
total_netuids = len(subnets_)
|
409
|
+
defined_table = define_table(
|
407
410
|
total_emissions, total_rate, total_netuids, percentage_string
|
408
411
|
)
|
409
412
|
|
410
413
|
for row in rows:
|
411
|
-
|
412
|
-
return
|
414
|
+
defined_table.add_row(*row)
|
415
|
+
return defined_table
|
416
|
+
|
417
|
+
def dict_table(subnets_, block_number_) -> dict:
|
418
|
+
subnet_rows = {}
|
419
|
+
total_tao_emitted, _ = calculate_emission_stats(subnets_, block_number_)
|
420
|
+
total_emissions = 0.0
|
421
|
+
total_rate = 0.0
|
422
|
+
total_netuids = len(subnets_)
|
423
|
+
emission_percentage = (total_tao_emitted / block_number_) * 100
|
424
|
+
for subnet in subnets_:
|
425
|
+
total_emissions += subnet.tao_in_emission.tao
|
426
|
+
total_rate += subnet.price.tao
|
427
|
+
netuid = subnet.netuid
|
428
|
+
if netuid == 0:
|
429
|
+
emission_tao = 0.0
|
430
|
+
else:
|
431
|
+
emission_tao = subnet.tao_in_emission.tao
|
432
|
+
alpha_in_value = subnet.alpha_in.tao
|
433
|
+
alpha_out_value = subnet.alpha_out.tao
|
434
|
+
price_value = subnet.price.tao
|
435
|
+
market_cap = (subnet.alpha_in.tao + subnet.alpha_out.tao) * subnet.price.tao
|
436
|
+
tao_in = subnet.tao_in.tao if netuid != 0 else None
|
437
|
+
alpha_in = alpha_in_value if netuid != 0 else None
|
438
|
+
alpha_out = alpha_out_value if netuid != 0 else None
|
439
|
+
supply = subnet.alpha_in.tao + subnet.alpha_out.tao
|
440
|
+
subnet_name = get_subnet_name(subnet)
|
441
|
+
tempo = {
|
442
|
+
"blocks_since_last_step": (
|
443
|
+
subnet.blocks_since_last_step if netuid != 0 else None
|
444
|
+
),
|
445
|
+
"sn_tempo": (subnet.tempo if netuid != 0 else None),
|
446
|
+
}
|
447
|
+
subnet_rows[netuid] = {
|
448
|
+
"netuid": netuid,
|
449
|
+
"subnet_name": subnet_name,
|
450
|
+
"price": price_value,
|
451
|
+
"market_cap": market_cap,
|
452
|
+
"emission": emission_tao,
|
453
|
+
"liquidity": {"tao_in": tao_in, "alpha_in": alpha_in},
|
454
|
+
"alpha_out": alpha_out,
|
455
|
+
"supply": supply,
|
456
|
+
"tempo": tempo,
|
457
|
+
}
|
458
|
+
output = {
|
459
|
+
"total_tao_emitted": total_tao_emitted,
|
460
|
+
"total_emissions": total_emissions,
|
461
|
+
"total_rate": total_rate,
|
462
|
+
"total_netuids": total_netuids,
|
463
|
+
"emission_percentage": emission_percentage,
|
464
|
+
"subnets": subnet_rows,
|
465
|
+
}
|
466
|
+
return output
|
413
467
|
|
414
468
|
# Live mode
|
415
|
-
def create_table_live(
|
469
|
+
def create_table_live(subnets_, previous_data_, block_number_):
|
416
470
|
def format_cell(
|
417
471
|
value, previous_value, unit="", unit_first=False, precision=4, millify=False
|
418
472
|
):
|
@@ -516,9 +570,9 @@ async def subnets_list(
|
|
516
570
|
|
517
571
|
rows = []
|
518
572
|
current_data = {} # To store current values for comparison in the next update
|
519
|
-
_, percentage_string = calculate_emission_stats(
|
573
|
+
_, percentage_string = calculate_emission_stats(subnets_, block_number_)
|
520
574
|
|
521
|
-
for subnet in
|
575
|
+
for subnet in subnets_:
|
522
576
|
netuid = subnet.netuid
|
523
577
|
symbol = f"{subnet.symbol}\u200e"
|
524
578
|
|
@@ -541,7 +595,7 @@ async def subnets_list(
|
|
541
595
|
"supply": supply,
|
542
596
|
"blocks_since_last_step": subnet.blocks_since_last_step,
|
543
597
|
}
|
544
|
-
prev =
|
598
|
+
prev = previous_data_.get(netuid, {}) if previous_data_ else {}
|
545
599
|
|
546
600
|
# Prepare cells
|
547
601
|
if netuid == 0:
|
@@ -652,9 +706,9 @@ async def subnets_list(
|
|
652
706
|
)
|
653
707
|
|
654
708
|
# Calculate totals
|
655
|
-
total_netuids = len(
|
709
|
+
total_netuids = len(subnets_)
|
656
710
|
_total_emissions = sum(
|
657
|
-
subnet.tao_in_emission.tao for subnet in
|
711
|
+
subnet.tao_in_emission.tao for subnet in subnets_ if subnet.netuid != 0
|
658
712
|
)
|
659
713
|
total_emissions = (
|
660
714
|
f"{millify_tao(_total_emissions)}"
|
@@ -662,7 +716,7 @@ async def subnets_list(
|
|
662
716
|
else f"{_total_emissions:,.2f}"
|
663
717
|
)
|
664
718
|
|
665
|
-
total_rate = sum(subnet.price.tao for subnet in
|
719
|
+
total_rate = sum(subnet.price.tao for subnet in subnets_ if subnet.netuid != 0)
|
666
720
|
total_rate = (
|
667
721
|
f"{millify_tao(total_rate)}" if not verbose else f"{total_rate:,.2f}"
|
668
722
|
)
|
@@ -733,8 +787,11 @@ async def subnets_list(
|
|
733
787
|
else:
|
734
788
|
# Non-live mode
|
735
789
|
subnets, block_number = await fetch_subnet_data()
|
736
|
-
|
737
|
-
|
790
|
+
if json_output:
|
791
|
+
json_console.print(json.dumps(dict_table(subnets, block_number)))
|
792
|
+
else:
|
793
|
+
table = _create_table(subnets, block_number)
|
794
|
+
console.print(table)
|
738
795
|
|
739
796
|
return
|
740
797
|
# TODO: Temporarily returning till we update docs
|
@@ -804,20 +861,22 @@ async def show(
|
|
804
861
|
delegate_selection: bool = False,
|
805
862
|
verbose: bool = False,
|
806
863
|
prompt: bool = True,
|
864
|
+
json_output: bool = False,
|
807
865
|
) -> Optional[str]:
|
808
866
|
async def show_root():
|
867
|
+
# TODO json_output for this, don't forget
|
809
868
|
block_hash = await subtensor.substrate.get_chain_head()
|
810
|
-
all_subnets = await subtensor.all_subnets(block_hash=block_hash)
|
811
|
-
root_info = next((s for s in all_subnets if s.netuid == 0), None)
|
812
|
-
if root_info is None:
|
813
|
-
print_error("The root subnet does not exist")
|
814
|
-
return False
|
815
869
|
|
816
|
-
root_state, identities, old_identities = await asyncio.gather(
|
870
|
+
all_subnets, root_state, identities, old_identities = await asyncio.gather(
|
871
|
+
subtensor.all_subnets(block_hash=block_hash),
|
817
872
|
subtensor.get_subnet_state(netuid=0, block_hash=block_hash),
|
818
873
|
subtensor.query_all_identities(block_hash=block_hash),
|
819
874
|
subtensor.get_delegate_identities(block_hash=block_hash),
|
820
875
|
)
|
876
|
+
root_info = next((s for s in all_subnets if s.netuid == 0), None)
|
877
|
+
if root_info is None:
|
878
|
+
print_error("The root subnet does not exist")
|
879
|
+
return False
|
821
880
|
|
822
881
|
if root_state is None:
|
823
882
|
err_console.print("The root subnet does not exist")
|
@@ -829,12 +888,11 @@ async def show(
|
|
829
888
|
)
|
830
889
|
return
|
831
890
|
|
832
|
-
tao_sum = sum(
|
833
|
-
[root_state.tao_stake[idx].tao for idx in range(len(root_state.tao_stake))]
|
834
|
-
)
|
891
|
+
tao_sum = sum(root_state.tao_stake).tao
|
835
892
|
|
836
893
|
table = Table(
|
837
|
-
title=f"[{COLOR_PALETTE
|
894
|
+
title=f"[{COLOR_PALETTE.G.HEADER}]Root Network\n[{COLOR_PALETTE.G.SUBHEAD}]"
|
895
|
+
f"Network: {subtensor.network}[/{COLOR_PALETTE.G.SUBHEAD}]\n",
|
838
896
|
show_footer=True,
|
839
897
|
show_edge=False,
|
840
898
|
header_style="bold white",
|
@@ -1119,6 +1177,7 @@ async def show(
|
|
1119
1177
|
)
|
1120
1178
|
|
1121
1179
|
rows = []
|
1180
|
+
json_out_rows = []
|
1122
1181
|
for idx in sorted_indices:
|
1123
1182
|
# Get identity for this uid
|
1124
1183
|
coldkey_identity = identities.get(subnet_state.coldkeys[idx], {}).get(
|
@@ -1170,6 +1229,22 @@ async def show(
|
|
1170
1229
|
uid_identity, # Identity
|
1171
1230
|
)
|
1172
1231
|
)
|
1232
|
+
json_out_rows.append(
|
1233
|
+
{
|
1234
|
+
"uid": idx,
|
1235
|
+
"stake": subnet_state.total_stake[idx].tao,
|
1236
|
+
"alpha_stake": subnet_state.alpha_stake[idx].tao,
|
1237
|
+
"tao_stake": tao_stake.tao,
|
1238
|
+
"dividends": subnet_state.dividends[idx],
|
1239
|
+
"incentive": subnet_state.incentives[idx],
|
1240
|
+
"emissions": Balance.from_tao(subnet_state.emission[idx].tao)
|
1241
|
+
.set_unit(netuid_)
|
1242
|
+
.tao,
|
1243
|
+
"hotkey": subnet_state.hotkeys[idx],
|
1244
|
+
"coldkey": subnet_state.coldkeys[idx],
|
1245
|
+
"identity": uid_identity,
|
1246
|
+
}
|
1247
|
+
)
|
1173
1248
|
|
1174
1249
|
# Add columns to the table
|
1175
1250
|
table.add_column("UID", style="grey89", no_wrap=True, justify="center")
|
@@ -1262,6 +1337,24 @@ async def show(
|
|
1262
1337
|
if current_burn_cost
|
1263
1338
|
else Balance(0)
|
1264
1339
|
)
|
1340
|
+
output_dict = {
|
1341
|
+
"netuid": netuid_,
|
1342
|
+
"name": subnet_name_display,
|
1343
|
+
"owner": subnet_info.owner_coldkey,
|
1344
|
+
"owner_identity": owner_identity,
|
1345
|
+
"rate": subnet_info.price.tao,
|
1346
|
+
"emission": subnet_info.emission.tao,
|
1347
|
+
"tao_pool": subnet_info.tao_in.tao,
|
1348
|
+
"alpha_pool": subnet_info.alpha_in.tao,
|
1349
|
+
"tempo": {
|
1350
|
+
"block_since_last_step": subnet_info.blocks_since_last_step,
|
1351
|
+
"tempo": subnet_info.tempo,
|
1352
|
+
},
|
1353
|
+
"registration_cost": current_registration_burn.tao,
|
1354
|
+
"uids": json_out_rows,
|
1355
|
+
}
|
1356
|
+
if json_output:
|
1357
|
+
json_console.print(json.dumps(output_dict))
|
1265
1358
|
|
1266
1359
|
console.print(
|
1267
1360
|
f"[{COLOR_PALETTE['GENERAL']['SUBHEADING']}]Subnet {netuid_}{subnet_name_display}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}]"
|
@@ -1334,7 +1427,9 @@ async def show(
|
|
1334
1427
|
return result
|
1335
1428
|
|
1336
1429
|
|
1337
|
-
async def burn_cost(
|
1430
|
+
async def burn_cost(
|
1431
|
+
subtensor: "SubtensorInterface", json_output: bool = False
|
1432
|
+
) -> Optional[Balance]:
|
1338
1433
|
"""View locking cost of creating a new subnetwork"""
|
1339
1434
|
with console.status(
|
1340
1435
|
f":satellite:Retrieving lock cost from {subtensor.network}...",
|
@@ -1342,26 +1437,47 @@ async def burn_cost(subtensor: "SubtensorInterface") -> Optional[Balance]:
|
|
1342
1437
|
):
|
1343
1438
|
current_burn_cost = await subtensor.burn_cost()
|
1344
1439
|
if current_burn_cost:
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1440
|
+
if json_output:
|
1441
|
+
json_console.print(
|
1442
|
+
json.dumps({"burn_cost": current_burn_cost.to_dict(), "error": ""})
|
1443
|
+
)
|
1444
|
+
else:
|
1445
|
+
console.print(
|
1446
|
+
f"Subnet burn cost: [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{current_burn_cost}"
|
1447
|
+
)
|
1348
1448
|
return current_burn_cost
|
1349
1449
|
else:
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1450
|
+
if json_output:
|
1451
|
+
json_console.print(
|
1452
|
+
json.dumps(
|
1453
|
+
{"burn_cost": None, "error": "Failed to get subnet burn cost"}
|
1454
|
+
)
|
1455
|
+
)
|
1456
|
+
else:
|
1457
|
+
err_console.print(
|
1458
|
+
"Subnet burn cost: [red]Failed to get subnet burn cost[/red]"
|
1459
|
+
)
|
1353
1460
|
return None
|
1354
1461
|
|
1355
1462
|
|
1356
1463
|
async def create(
|
1357
|
-
wallet: Wallet,
|
1464
|
+
wallet: Wallet,
|
1465
|
+
subtensor: "SubtensorInterface",
|
1466
|
+
subnet_identity: dict,
|
1467
|
+
json_output: bool,
|
1468
|
+
prompt: bool,
|
1358
1469
|
):
|
1359
1470
|
"""Register a subnetwork"""
|
1360
1471
|
|
1361
1472
|
# Call register command.
|
1362
|
-
success = await register_subnetwork_extrinsic(
|
1473
|
+
success, netuid = await register_subnetwork_extrinsic(
|
1363
1474
|
subtensor, wallet, subnet_identity, prompt=prompt
|
1364
1475
|
)
|
1476
|
+
if json_output:
|
1477
|
+
# technically, netuid can be `None`, but only if not wait for finalization/inclusion. However, as of present
|
1478
|
+
# (2025/04/03), we always use the default `wait_for_finalization=True`, so it will always have a netuid.
|
1479
|
+
json_console.print(json.dumps({"success": success, "netuid": netuid}))
|
1480
|
+
return success
|
1365
1481
|
if success and prompt:
|
1366
1482
|
# Prompt for user to set identity.
|
1367
1483
|
do_set_identity = Confirm.ask(
|
@@ -1436,7 +1552,12 @@ async def pow_register(
|
|
1436
1552
|
|
1437
1553
|
|
1438
1554
|
async def register(
|
1439
|
-
wallet: Wallet,
|
1555
|
+
wallet: Wallet,
|
1556
|
+
subtensor: "SubtensorInterface",
|
1557
|
+
netuid: int,
|
1558
|
+
era: Optional[int],
|
1559
|
+
json_output: bool,
|
1560
|
+
prompt: bool,
|
1440
1561
|
):
|
1441
1562
|
"""Register neuron by recycling some TAO."""
|
1442
1563
|
|
@@ -1445,6 +1566,12 @@ async def register(
|
|
1445
1566
|
block_hash = await subtensor.substrate.get_chain_head()
|
1446
1567
|
if not await subtensor.subnet_exists(netuid=netuid, block_hash=block_hash):
|
1447
1568
|
err_console.print(f"[red]Subnet {netuid} does not exist[/red]")
|
1569
|
+
if json_output:
|
1570
|
+
json_console.print(
|
1571
|
+
json.dumps(
|
1572
|
+
{"success": False, "error": f"Subnet {netuid} does not exist"}
|
1573
|
+
)
|
1574
|
+
)
|
1448
1575
|
return
|
1449
1576
|
|
1450
1577
|
# Check current recycle amount
|
@@ -1466,7 +1593,7 @@ async def register(
|
|
1466
1593
|
)
|
1467
1594
|
return
|
1468
1595
|
|
1469
|
-
if prompt:
|
1596
|
+
if prompt and not json_output:
|
1470
1597
|
# TODO make this a reusable function, also used in subnets list
|
1471
1598
|
# Show creation table.
|
1472
1599
|
table = Table(
|
@@ -1518,23 +1645,28 @@ async def register(
|
|
1518
1645
|
console.print(table)
|
1519
1646
|
if not (
|
1520
1647
|
Confirm.ask(
|
1521
|
-
f"Your balance is: [{COLOR_PALETTE
|
1522
|
-
f"
|
1648
|
+
f"Your balance is: [{COLOR_PALETTE.G.BAL}]{balance}[/{COLOR_PALETTE.G.BAL}]\n"
|
1649
|
+
f"The cost to register by recycle is "
|
1650
|
+
f"[{COLOR_PALETTE.G.COST}]{current_recycle}[/{COLOR_PALETTE.G.COST}]\n"
|
1651
|
+
f"Do you want to continue?",
|
1523
1652
|
default=False,
|
1524
1653
|
)
|
1525
1654
|
):
|
1526
1655
|
return
|
1527
1656
|
|
1528
1657
|
if netuid == 0:
|
1529
|
-
await root_register_extrinsic(subtensor, wallet=wallet)
|
1658
|
+
success, msg = await root_register_extrinsic(subtensor, wallet=wallet)
|
1530
1659
|
else:
|
1531
|
-
await burned_register_extrinsic(
|
1660
|
+
success, msg = await burned_register_extrinsic(
|
1532
1661
|
subtensor,
|
1533
1662
|
wallet=wallet,
|
1534
1663
|
netuid=netuid,
|
1535
1664
|
prompt=False,
|
1536
1665
|
old_balance=balance,
|
1666
|
+
era=era,
|
1537
1667
|
)
|
1668
|
+
if json_output:
|
1669
|
+
json_console.print(json.dumps({"success": success, "msg": msg}))
|
1538
1670
|
|
1539
1671
|
|
1540
1672
|
# TODO: Confirm emissions, incentive, Dividends are to be fetched from subnet_state or keep NeuronInfo
|
@@ -2126,10 +2258,15 @@ async def set_identity(
|
|
2126
2258
|
return True
|
2127
2259
|
|
2128
2260
|
|
2129
|
-
async def get_identity(
|
2261
|
+
async def get_identity(
|
2262
|
+
subtensor: "SubtensorInterface",
|
2263
|
+
netuid: int,
|
2264
|
+
title: str = None,
|
2265
|
+
json_output: bool = False,
|
2266
|
+
) -> Optional[dict]:
|
2130
2267
|
"""Fetch and display existing subnet identity information."""
|
2131
2268
|
if not title:
|
2132
|
-
title = "Subnet Identity"
|
2269
|
+
title = f"Current Subnet {netuid} Identity"
|
2133
2270
|
|
2134
2271
|
if not await subtensor.subnet_exists(netuid):
|
2135
2272
|
print_error(f"Subnet {netuid} does not exist.")
|
@@ -2147,10 +2284,12 @@ async def get_identity(subtensor: "SubtensorInterface", netuid: int, title: str
|
|
2147
2284
|
f" for subnet [blue]{netuid}[/blue]"
|
2148
2285
|
f" on {subtensor}"
|
2149
2286
|
)
|
2287
|
+
if json_output:
|
2288
|
+
json_console.print("{}")
|
2150
2289
|
return {}
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2290
|
+
else:
|
2291
|
+
table = create_identity_table(title=title)
|
2292
|
+
dict_out = {}
|
2154
2293
|
table.add_row("Netuid", str(netuid))
|
2155
2294
|
for key in [
|
2156
2295
|
"subnet_name",
|
@@ -2163,5 +2302,9 @@ async def get_identity(subtensor: "SubtensorInterface", netuid: int, title: str
|
|
2163
2302
|
]:
|
2164
2303
|
value = getattr(identity, key, None)
|
2165
2304
|
table.add_row(key, str(value) if value else "~")
|
2166
|
-
|
2305
|
+
dict_out[key] = value
|
2306
|
+
if json_output:
|
2307
|
+
json_console.print(json.dumps(dict_out))
|
2308
|
+
else:
|
2309
|
+
console.print(table)
|
2167
2310
|
return identity
|