bittensor-cli 8.4.3__py3-none-any.whl → 9.0.0rc2__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 +1508 -1385
- bittensor_cli/src/__init__.py +627 -197
- bittensor_cli/src/bittensor/balances.py +41 -8
- bittensor_cli/src/bittensor/chain_data.py +557 -428
- bittensor_cli/src/bittensor/extrinsics/registration.py +161 -47
- bittensor_cli/src/bittensor/extrinsics/root.py +14 -8
- bittensor_cli/src/bittensor/extrinsics/transfer.py +14 -21
- bittensor_cli/src/bittensor/minigraph.py +46 -8
- bittensor_cli/src/bittensor/subtensor_interface.py +572 -253
- bittensor_cli/src/bittensor/utils.py +326 -75
- bittensor_cli/src/commands/stake/__init__.py +154 -0
- bittensor_cli/src/commands/stake/children_hotkeys.py +121 -87
- bittensor_cli/src/commands/stake/move.py +1000 -0
- bittensor_cli/src/commands/stake/stake.py +1637 -1264
- bittensor_cli/src/commands/subnets/__init__.py +0 -0
- bittensor_cli/src/commands/subnets/price.py +867 -0
- bittensor_cli/src/commands/subnets/subnets.py +2055 -0
- bittensor_cli/src/commands/sudo.py +529 -26
- bittensor_cli/src/commands/wallets.py +234 -544
- bittensor_cli/src/commands/weights.py +15 -11
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/METADATA +7 -4
- bittensor_cli-9.0.0rc2.dist-info/RECORD +32 -0
- bittensor_cli/src/bittensor/async_substrate_interface.py +0 -2748
- bittensor_cli/src/commands/root.py +0 -1752
- bittensor_cli/src/commands/subnets.py +0 -897
- bittensor_cli-8.4.3.dist-info/RECORD +0 -31
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/WHEEL +0 -0
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/top_level.txt +0 -0
@@ -2,10 +2,11 @@ import asyncio
|
|
2
2
|
from typing import Optional
|
3
3
|
|
4
4
|
from bittensor_wallet import Wallet
|
5
|
+
from bittensor_wallet.errors import KeyFileError
|
5
6
|
from rich.prompt import Confirm, Prompt, IntPrompt
|
6
7
|
from rich.table import Table
|
7
8
|
from rich.text import Text
|
8
|
-
from
|
9
|
+
from async_substrate_interface.errors import SubstrateRequestException
|
9
10
|
|
10
11
|
from bittensor_cli.src.bittensor.balances import Balance
|
11
12
|
from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface
|
@@ -18,10 +19,36 @@ from bittensor_cli.src.bittensor.utils import (
|
|
18
19
|
u64_to_float,
|
19
20
|
is_valid_ss58_address,
|
20
21
|
format_error_message,
|
21
|
-
unlock_key,
|
22
22
|
)
|
23
23
|
|
24
24
|
|
25
|
+
async def get_childkey_completion_block(
|
26
|
+
subtensor: SubtensorInterface, netuid: int
|
27
|
+
) -> tuple[int, int]:
|
28
|
+
"""
|
29
|
+
Calculates the block at which the childkey set request will complete
|
30
|
+
"""
|
31
|
+
blocks_since_last_step_query = subtensor.query(
|
32
|
+
"SubtensorModule",
|
33
|
+
"BlocksSinceLastStep",
|
34
|
+
params=[netuid],
|
35
|
+
)
|
36
|
+
tempo_query = subtensor.get_hyperparameter(
|
37
|
+
param_name="Tempo",
|
38
|
+
netuid=netuid,
|
39
|
+
)
|
40
|
+
block_number, blocks_since_last_step, tempo = await asyncio.gather(
|
41
|
+
subtensor.substrate.get_block_number(),
|
42
|
+
blocks_since_last_step_query,
|
43
|
+
tempo_query,
|
44
|
+
)
|
45
|
+
cooldown = block_number + 1
|
46
|
+
blocks_left_in_tempo = tempo - blocks_since_last_step
|
47
|
+
next_tempo = block_number + blocks_left_in_tempo
|
48
|
+
next_epoch_after_cooldown = (cooldown - next_tempo) % tempo + cooldown
|
49
|
+
return block_number, next_epoch_after_cooldown
|
50
|
+
|
51
|
+
|
25
52
|
async def set_children_extrinsic(
|
26
53
|
subtensor: "SubtensorInterface",
|
27
54
|
wallet: Wallet,
|
@@ -72,8 +99,10 @@ async def set_children_extrinsic(
|
|
72
99
|
return False, "Operation Cancelled"
|
73
100
|
|
74
101
|
# Decrypt coldkey.
|
75
|
-
|
76
|
-
|
102
|
+
try:
|
103
|
+
wallet.unlock_coldkey()
|
104
|
+
except KeyFileError:
|
105
|
+
return False, "There was an error unlocking your coldkey."
|
77
106
|
|
78
107
|
with console.status(
|
79
108
|
f":satellite: {operation} on [white]{subtensor.network}[/white] ..."
|
@@ -156,8 +185,10 @@ async def set_childkey_take_extrinsic(
|
|
156
185
|
return False, "Operation Cancelled"
|
157
186
|
|
158
187
|
# Decrypt coldkey.
|
159
|
-
|
160
|
-
|
188
|
+
try:
|
189
|
+
wallet.unlock_coldkey()
|
190
|
+
except KeyFileError:
|
191
|
+
return False, "There was an error unlocking your coldkey."
|
161
192
|
|
162
193
|
with console.status(
|
163
194
|
f":satellite: Setting childkey take on [white]{subtensor.network}[/white] ..."
|
@@ -208,7 +239,7 @@ async def set_childkey_take_extrinsic(
|
|
208
239
|
except SubstrateRequestException as e:
|
209
240
|
return (
|
210
241
|
False,
|
211
|
-
f"Exception occurred while setting childkey take: {format_error_message(e)}",
|
242
|
+
f"Exception occurred while setting childkey take: {format_error_message(e, subtensor.substrate)}",
|
212
243
|
)
|
213
244
|
|
214
245
|
|
@@ -223,16 +254,18 @@ async def get_childkey_take(subtensor, hotkey: str, netuid: int) -> Optional[int
|
|
223
254
|
- Optional[float]: The value of the "ChildkeyTake" if found, or None if any error occurs.
|
224
255
|
"""
|
225
256
|
try:
|
226
|
-
childkey_take_ = await subtensor.
|
257
|
+
childkey_take_ = await subtensor.query(
|
227
258
|
module="SubtensorModule",
|
228
259
|
storage_function="ChildkeyTake",
|
229
260
|
params=[hotkey, netuid],
|
230
261
|
)
|
231
262
|
if childkey_take_:
|
232
|
-
return int(childkey_take_)
|
263
|
+
return int(childkey_take_.value)
|
233
264
|
|
234
265
|
except SubstrateRequestException as e:
|
235
|
-
err_console.print(
|
266
|
+
err_console.print(
|
267
|
+
f"Error querying ChildKeys: {format_error_message(e, subtensor.substrate)}"
|
268
|
+
)
|
236
269
|
return None
|
237
270
|
|
238
271
|
|
@@ -264,6 +297,7 @@ def prepare_child_proportions(children_with_proportions):
|
|
264
297
|
async def get_children(
|
265
298
|
wallet: Wallet, subtensor: "SubtensorInterface", netuid: Optional[int] = None
|
266
299
|
):
|
300
|
+
# TODO rao asks separately for the hotkey from the user, should we do this, or the way we do it now?
|
267
301
|
"""
|
268
302
|
Retrieves the child hotkeys for the specified wallet.
|
269
303
|
|
@@ -281,35 +315,7 @@ async def get_children(
|
|
281
315
|
- If netuid is not specified, generates and prints a summary table of all child hotkeys across all subnets.
|
282
316
|
"""
|
283
317
|
|
284
|
-
async def
|
285
|
-
"""
|
286
|
-
Fetches and displays the total stake for a specified hotkey from the Subtensor blockchain network.
|
287
|
-
If `parent` is True, it prints the hotkey and its corresponding stake.
|
288
|
-
|
289
|
-
Parameters:
|
290
|
-
- hotkey (str): The hotkey for which the stake needs to be fetched.
|
291
|
-
- parent (bool, optional): A flag to indicate whether the hotkey is the parent key. Defaults to False.
|
292
|
-
|
293
|
-
Returns:
|
294
|
-
- Balance: The total stake associated with the specified hotkey.
|
295
|
-
"""
|
296
|
-
_result = await subtensor.substrate.query(
|
297
|
-
module="SubtensorModule",
|
298
|
-
storage_function="TotalHotkeyStake",
|
299
|
-
params=[hotkey],
|
300
|
-
reuse_block_hash=True,
|
301
|
-
)
|
302
|
-
stake = Balance.from_rao(_result) if _result is not None else Balance(0)
|
303
|
-
if parent:
|
304
|
-
console.print(
|
305
|
-
f"\nYour Hotkey: [bright_magenta]{hotkey}[/bright_magenta] | Total Stake: [dark_orange]{stake}t[/dark_orange]\n",
|
306
|
-
end="",
|
307
|
-
no_wrap=True,
|
308
|
-
)
|
309
|
-
|
310
|
-
return stake
|
311
|
-
|
312
|
-
async def get_take(child: tuple) -> float:
|
318
|
+
async def get_take(child: tuple, netuid__: int) -> float:
|
313
319
|
"""
|
314
320
|
Get the take value for a given subtensor, hotkey, and netuid.
|
315
321
|
|
@@ -320,7 +326,7 @@ async def get_children(
|
|
320
326
|
"""
|
321
327
|
child_hotkey = child[1]
|
322
328
|
take_u16 = await get_childkey_take(
|
323
|
-
subtensor=subtensor, hotkey=child_hotkey, netuid=
|
329
|
+
subtensor=subtensor, hotkey=child_hotkey, netuid=netuid__
|
324
330
|
)
|
325
331
|
if take_u16:
|
326
332
|
return u16_to_float(take_u16)
|
@@ -329,7 +335,7 @@ async def get_children(
|
|
329
335
|
|
330
336
|
async def _render_table(
|
331
337
|
parent_hotkey: str,
|
332
|
-
|
338
|
+
netuid_children_: list[tuple[int, list[tuple[int, str]]]],
|
333
339
|
):
|
334
340
|
"""
|
335
341
|
Retrieves and renders children hotkeys and their details for a given parent hotkey.
|
@@ -352,10 +358,11 @@ async def get_children(
|
|
352
358
|
"Current Stake Weight", style="bold red", no_wrap=True, justify="right"
|
353
359
|
)
|
354
360
|
|
355
|
-
if not
|
361
|
+
if not netuid_children_:
|
356
362
|
console.print(table)
|
357
363
|
console.print(
|
358
|
-
f"[bold red]There are currently no child hotkeys with parent hotkey:
|
364
|
+
f"[bold red]There are currently no child hotkeys with parent hotkey: "
|
365
|
+
f"{wallet.name} | {wallet.hotkey_str} ({parent_hotkey}).[/bold red]"
|
359
366
|
)
|
360
367
|
return
|
361
368
|
|
@@ -363,48 +370,64 @@ async def get_children(
|
|
363
370
|
total_proportion = 0
|
364
371
|
total_stake_weight = 0
|
365
372
|
|
366
|
-
|
367
|
-
|
368
|
-
|
373
|
+
netuid_children_.sort(key=lambda x: x[0]) # Sort by netuid in ascending order
|
374
|
+
unique_keys = set(
|
375
|
+
[parent_hotkey]
|
376
|
+
+ [s for _, child_list in netuid_children_ for _, s in child_list]
|
377
|
+
)
|
378
|
+
hotkey_stake_dict = await subtensor.get_total_stake_for_hotkey(
|
379
|
+
*unique_keys,
|
380
|
+
netuids=[n[0] for n in netuid_children_],
|
381
|
+
)
|
382
|
+
parent_total = sum(hotkey_stake_dict[parent_hotkey].values())
|
383
|
+
insert_text = (
|
384
|
+
" "
|
385
|
+
if netuid is None
|
386
|
+
else f" on netuids: {', '.join(str(n[0]) for n in netuid_children_)} "
|
387
|
+
)
|
388
|
+
console.print(
|
389
|
+
f"The total stake of parent hotkey '{parent_hotkey}'{insert_text}is {parent_total}."
|
390
|
+
)
|
369
391
|
|
370
|
-
for index, (
|
392
|
+
for index, (netuid_, children_) in enumerate(netuid_children_):
|
371
393
|
# calculate totals
|
372
394
|
total_proportion_per_netuid = 0
|
373
395
|
total_stake_weight_per_netuid = 0
|
374
|
-
avg_take_per_netuid = 0
|
396
|
+
avg_take_per_netuid = 0.0
|
375
397
|
|
376
|
-
|
377
|
-
parent_hotkey
|
378
|
-
)
|
379
|
-
hotkey_stake = hotkey_stake_dict.get(parent_hotkey, Balance(0))
|
398
|
+
hotkey_stake: dict[int, Balance] = hotkey_stake_dict[parent_hotkey]
|
380
399
|
|
381
400
|
children_info = []
|
382
|
-
|
383
|
-
*[
|
401
|
+
child_takes = await asyncio.gather(
|
402
|
+
*[get_take(c, netuid_) for c in children_]
|
384
403
|
)
|
385
|
-
|
386
|
-
for child, child_stake, child_take in zip(
|
387
|
-
children_, child_stakes, child_takes
|
388
|
-
):
|
404
|
+
for child, child_take in zip(children_, child_takes):
|
389
405
|
proportion = child[0]
|
390
406
|
child_hotkey = child[1]
|
391
407
|
|
392
408
|
# add to totals
|
393
409
|
avg_take_per_netuid += child_take
|
394
410
|
|
395
|
-
|
411
|
+
converted_proportion = u64_to_float(proportion)
|
396
412
|
|
397
413
|
children_info.append(
|
398
|
-
(
|
414
|
+
(
|
415
|
+
converted_proportion,
|
416
|
+
child_hotkey,
|
417
|
+
hotkey_stake_dict[child_hotkey][netuid_],
|
418
|
+
child_take,
|
419
|
+
)
|
399
420
|
)
|
400
421
|
|
401
422
|
children_info.sort(
|
402
423
|
key=lambda x: x[0], reverse=True
|
403
424
|
) # sorting by proportion (highest first)
|
404
425
|
|
405
|
-
for
|
406
|
-
proportion_percent =
|
407
|
-
proportion_tao =
|
426
|
+
for proportion_, hotkey, stake, child_take in children_info:
|
427
|
+
proportion_percent = proportion_ * 100 # Proportion in percent
|
428
|
+
proportion_tao = (
|
429
|
+
hotkey_stake[netuid_].tao * proportion_
|
430
|
+
) # Proportion in TAO
|
408
431
|
|
409
432
|
total_proportion_per_netuid += proportion_percent
|
410
433
|
|
@@ -414,9 +437,9 @@ async def get_children(
|
|
414
437
|
total_stake_weight_per_netuid += stake_weight
|
415
438
|
take_str = f"{child_take * 100:.3f}%"
|
416
439
|
|
417
|
-
hotkey = Text(hotkey, style="italic red" if
|
440
|
+
hotkey = Text(hotkey, style="italic red" if proportion_ == 0 else "")
|
418
441
|
table.add_row(
|
419
|
-
str(
|
442
|
+
str(netuid_),
|
420
443
|
hotkey,
|
421
444
|
proportion_str,
|
422
445
|
take_str,
|
@@ -440,7 +463,7 @@ async def get_children(
|
|
440
463
|
total_stake_weight += total_stake_weight_per_netuid
|
441
464
|
|
442
465
|
# Add a dividing line if there are more than one netuid
|
443
|
-
if len(
|
466
|
+
if len(netuid_children_) > 1:
|
444
467
|
table.add_section()
|
445
468
|
|
446
469
|
console.print(table)
|
@@ -449,17 +472,16 @@ async def get_children(
|
|
449
472
|
if netuid is None:
|
450
473
|
# get all netuids
|
451
474
|
netuids = await subtensor.get_all_subnet_netuids()
|
452
|
-
await get_total_stake_for_hk(wallet.hotkey.ss58_address, True)
|
453
475
|
netuid_children_tuples = []
|
454
|
-
for
|
476
|
+
for netuid_ in netuids:
|
455
477
|
success, children, err_mg = await subtensor.get_children(
|
456
|
-
wallet.hotkey.ss58_address,
|
478
|
+
wallet.hotkey.ss58_address, netuid_
|
457
479
|
)
|
458
480
|
if children:
|
459
|
-
netuid_children_tuples.append((
|
481
|
+
netuid_children_tuples.append((netuid_, children))
|
460
482
|
if not success:
|
461
483
|
err_console.print(
|
462
|
-
f"Failed to get children from subtensor {
|
484
|
+
f"Failed to get children from subtensor {netuid_}: {err_mg}"
|
463
485
|
)
|
464
486
|
await _render_table(wallet.hotkey.ss58_address, netuid_children_tuples)
|
465
487
|
else:
|
@@ -468,7 +490,6 @@ async def get_children(
|
|
468
490
|
)
|
469
491
|
if not success:
|
470
492
|
err_console.print(f"Failed to get children from subtensor: {err_mg}")
|
471
|
-
await get_total_stake_for_hk(wallet.hotkey.ss58_address, True)
|
472
493
|
if children:
|
473
494
|
netuid_children_tuples = [(netuid, children)]
|
474
495
|
await _render_table(wallet.hotkey.ss58_address, netuid_children_tuples)
|
@@ -481,13 +502,15 @@ async def set_children(
|
|
481
502
|
subtensor: "SubtensorInterface",
|
482
503
|
children: list[str],
|
483
504
|
proportions: list[float],
|
484
|
-
netuid: Optional[int]
|
505
|
+
netuid: Optional[int],
|
485
506
|
wait_for_inclusion: bool = True,
|
486
507
|
wait_for_finalization: bool = True,
|
487
508
|
prompt: bool = True,
|
488
509
|
):
|
489
510
|
"""Set children hotkeys."""
|
490
511
|
# Validate children SS58 addresses
|
512
|
+
# TODO check to see if this should be allowed to be specified by user instead of pulling from wallet
|
513
|
+
hotkey = wallet.hotkey.ss58_address
|
491
514
|
for child in children:
|
492
515
|
if not is_valid_ss58_address(child):
|
493
516
|
err_console.print(f":cross_mark:[red] Invalid SS58 address: {child}[/red]")
|
@@ -502,14 +525,13 @@ async def set_children(
|
|
502
525
|
f"Invalid proportion: The sum of all proportions cannot be greater than 1. "
|
503
526
|
f"Proposed sum of proportions is {total_proposed}."
|
504
527
|
)
|
505
|
-
|
506
528
|
children_with_proportions = list(zip(proportions, children))
|
507
|
-
if netuid:
|
529
|
+
if netuid is not None:
|
508
530
|
success, message = await set_children_extrinsic(
|
509
531
|
subtensor=subtensor,
|
510
532
|
wallet=wallet,
|
511
533
|
netuid=netuid,
|
512
|
-
hotkey=
|
534
|
+
hotkey=hotkey,
|
513
535
|
children_with_proportions=children_with_proportions,
|
514
536
|
prompt=prompt,
|
515
537
|
wait_for_inclusion=wait_for_inclusion,
|
@@ -518,8 +540,13 @@ async def set_children(
|
|
518
540
|
# Result
|
519
541
|
if success:
|
520
542
|
if wait_for_inclusion and wait_for_finalization:
|
521
|
-
|
522
|
-
|
543
|
+
current_block, completion_block = await get_childkey_completion_block(
|
544
|
+
subtensor, netuid
|
545
|
+
)
|
546
|
+
console.print(
|
547
|
+
f"Your childkey request has been submitted. It will be completed around block {completion_block}. "
|
548
|
+
f"The current block is {current_block}"
|
549
|
+
)
|
523
550
|
console.print(
|
524
551
|
":white_heavy_check_mark: [green]Set children hotkeys.[/green]"
|
525
552
|
)
|
@@ -530,20 +557,27 @@ async def set_children(
|
|
530
557
|
else:
|
531
558
|
# set children on all subnets that parent is registered on
|
532
559
|
netuids = await subtensor.get_all_subnet_netuids()
|
533
|
-
for
|
534
|
-
if
|
560
|
+
for netuid_ in netuids:
|
561
|
+
if netuid_ == 0: # dont include root network
|
535
562
|
continue
|
536
|
-
console.print(f"Setting children on netuid {
|
563
|
+
console.print(f"Setting children on netuid {netuid_}.")
|
537
564
|
await set_children_extrinsic(
|
538
565
|
subtensor=subtensor,
|
539
566
|
wallet=wallet,
|
540
|
-
netuid=
|
541
|
-
hotkey=
|
567
|
+
netuid=netuid_,
|
568
|
+
hotkey=hotkey,
|
542
569
|
children_with_proportions=children_with_proportions,
|
543
570
|
prompt=prompt,
|
544
571
|
wait_for_inclusion=True,
|
545
572
|
wait_for_finalization=False,
|
546
573
|
)
|
574
|
+
current_block, completion_block = await get_childkey_completion_block(
|
575
|
+
subtensor, netuid_
|
576
|
+
)
|
577
|
+
console.print(
|
578
|
+
f"Your childkey request for netuid {netuid_} has been submitted. It will be completed around "
|
579
|
+
f"block {completion_block}. The current block is {current_block}."
|
580
|
+
)
|
547
581
|
console.print(
|
548
582
|
":white_heavy_check_mark: [green]Sent set children request for all subnets.[/green]"
|
549
583
|
)
|
@@ -555,8 +589,8 @@ async def revoke_children(
|
|
555
589
|
netuid: Optional[int] = None,
|
556
590
|
wait_for_inclusion: bool = True,
|
557
591
|
wait_for_finalization: bool = True,
|
558
|
-
prompt: bool = True,
|
559
592
|
):
|
593
|
+
# TODO seek clarification on use of asking hotkey vs how we do it now
|
560
594
|
"""
|
561
595
|
Revokes the children hotkeys associated with a given network identifier (netuid).
|
562
596
|
"""
|
@@ -567,7 +601,7 @@ async def revoke_children(
|
|
567
601
|
netuid=netuid,
|
568
602
|
hotkey=wallet.hotkey.ss58_address,
|
569
603
|
children_with_proportions=[],
|
570
|
-
prompt=
|
604
|
+
prompt=True,
|
571
605
|
wait_for_inclusion=wait_for_inclusion,
|
572
606
|
wait_for_finalization=wait_for_finalization,
|
573
607
|
)
|
@@ -596,7 +630,7 @@ async def revoke_children(
|
|
596
630
|
netuid=netuid,
|
597
631
|
hotkey=wallet.hotkey.ss58_address,
|
598
632
|
children_with_proportions=[],
|
599
|
-
prompt=
|
633
|
+
prompt=False,
|
600
634
|
wait_for_inclusion=True,
|
601
635
|
wait_for_finalization=False,
|
602
636
|
)
|
@@ -756,7 +790,7 @@ async def childkey_take(
|
|
756
790
|
netuid=netuid,
|
757
791
|
hotkey=wallet.hotkey.ss58_address,
|
758
792
|
take=take,
|
759
|
-
prompt=
|
793
|
+
prompt=False,
|
760
794
|
wait_for_inclusion=True,
|
761
795
|
wait_for_finalization=False,
|
762
796
|
)
|