bittensor-cli 8.4.2__py3-none-any.whl → 9.0.0rc1__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 +1503 -1372
- bittensor_cli/src/__init__.py +625 -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 +123 -91
- 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 +2043 -0
- bittensor_cli/src/commands/sudo.py +529 -26
- bittensor_cli/src/commands/wallets.py +231 -535
- bittensor_cli/src/commands/weights.py +15 -11
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.dist-info}/METADATA +7 -4
- bittensor_cli-9.0.0rc1.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.2.dist-info/RECORD +0 -31
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.dist-info}/WHEEL +0 -0
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-8.4.2.dist-info → bittensor_cli-9.0.0rc1.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,39 +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 = (
|
303
|
-
Balance.from_rao(_result)
|
304
|
-
if _result is not None
|
305
|
-
else Balance(0)
|
306
|
-
)
|
307
|
-
if parent:
|
308
|
-
console.print(
|
309
|
-
f"\nYour Hotkey: [bright_magenta]{hotkey}[/bright_magenta] | Total Stake: [dark_orange]{stake}t[/dark_orange]\n",
|
310
|
-
end="",
|
311
|
-
no_wrap=True,
|
312
|
-
)
|
313
|
-
|
314
|
-
return stake
|
315
|
-
|
316
|
-
async def get_take(child: tuple) -> float:
|
318
|
+
async def get_take(child: tuple, netuid__: int) -> float:
|
317
319
|
"""
|
318
320
|
Get the take value for a given subtensor, hotkey, and netuid.
|
319
321
|
|
@@ -324,7 +326,7 @@ async def get_children(
|
|
324
326
|
"""
|
325
327
|
child_hotkey = child[1]
|
326
328
|
take_u16 = await get_childkey_take(
|
327
|
-
subtensor=subtensor, hotkey=child_hotkey, netuid=
|
329
|
+
subtensor=subtensor, hotkey=child_hotkey, netuid=netuid__
|
328
330
|
)
|
329
331
|
if take_u16:
|
330
332
|
return u16_to_float(take_u16)
|
@@ -333,7 +335,7 @@ async def get_children(
|
|
333
335
|
|
334
336
|
async def _render_table(
|
335
337
|
parent_hotkey: str,
|
336
|
-
|
338
|
+
netuid_children_: list[tuple[int, list[tuple[int, str]]]],
|
337
339
|
):
|
338
340
|
"""
|
339
341
|
Retrieves and renders children hotkeys and their details for a given parent hotkey.
|
@@ -356,10 +358,11 @@ async def get_children(
|
|
356
358
|
"Current Stake Weight", style="bold red", no_wrap=True, justify="right"
|
357
359
|
)
|
358
360
|
|
359
|
-
if not
|
361
|
+
if not netuid_children_:
|
360
362
|
console.print(table)
|
361
363
|
console.print(
|
362
|
-
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]"
|
363
366
|
)
|
364
367
|
return
|
365
368
|
|
@@ -367,48 +370,64 @@ async def get_children(
|
|
367
370
|
total_proportion = 0
|
368
371
|
total_stake_weight = 0
|
369
372
|
|
370
|
-
|
371
|
-
|
372
|
-
|
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
|
+
)
|
373
391
|
|
374
|
-
for index, (
|
392
|
+
for index, (netuid_, children_) in enumerate(netuid_children_):
|
375
393
|
# calculate totals
|
376
394
|
total_proportion_per_netuid = 0
|
377
395
|
total_stake_weight_per_netuid = 0
|
378
|
-
avg_take_per_netuid = 0
|
396
|
+
avg_take_per_netuid = 0.0
|
379
397
|
|
380
|
-
|
381
|
-
parent_hotkey
|
382
|
-
)
|
383
|
-
hotkey_stake = hotkey_stake_dict.get(parent_hotkey, Balance(0))
|
398
|
+
hotkey_stake: dict[int, Balance] = hotkey_stake_dict[parent_hotkey]
|
384
399
|
|
385
400
|
children_info = []
|
386
|
-
|
387
|
-
*[
|
401
|
+
child_takes = await asyncio.gather(
|
402
|
+
*[get_take(c, netuid_) for c in children_]
|
388
403
|
)
|
389
|
-
|
390
|
-
for child, child_stake, child_take in zip(
|
391
|
-
children_, child_stakes, child_takes
|
392
|
-
):
|
404
|
+
for child, child_take in zip(children_, child_takes):
|
393
405
|
proportion = child[0]
|
394
406
|
child_hotkey = child[1]
|
395
407
|
|
396
408
|
# add to totals
|
397
409
|
avg_take_per_netuid += child_take
|
398
410
|
|
399
|
-
|
411
|
+
converted_proportion = u64_to_float(proportion)
|
400
412
|
|
401
413
|
children_info.append(
|
402
|
-
(
|
414
|
+
(
|
415
|
+
converted_proportion,
|
416
|
+
child_hotkey,
|
417
|
+
hotkey_stake_dict[child_hotkey][netuid_],
|
418
|
+
child_take,
|
419
|
+
)
|
403
420
|
)
|
404
421
|
|
405
422
|
children_info.sort(
|
406
423
|
key=lambda x: x[0], reverse=True
|
407
424
|
) # sorting by proportion (highest first)
|
408
425
|
|
409
|
-
for
|
410
|
-
proportion_percent =
|
411
|
-
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
|
412
431
|
|
413
432
|
total_proportion_per_netuid += proportion_percent
|
414
433
|
|
@@ -418,9 +437,9 @@ async def get_children(
|
|
418
437
|
total_stake_weight_per_netuid += stake_weight
|
419
438
|
take_str = f"{child_take * 100:.3f}%"
|
420
439
|
|
421
|
-
hotkey = Text(hotkey, style="italic red" if
|
440
|
+
hotkey = Text(hotkey, style="italic red" if proportion_ == 0 else "")
|
422
441
|
table.add_row(
|
423
|
-
str(
|
442
|
+
str(netuid_),
|
424
443
|
hotkey,
|
425
444
|
proportion_str,
|
426
445
|
take_str,
|
@@ -444,7 +463,7 @@ async def get_children(
|
|
444
463
|
total_stake_weight += total_stake_weight_per_netuid
|
445
464
|
|
446
465
|
# Add a dividing line if there are more than one netuid
|
447
|
-
if len(
|
466
|
+
if len(netuid_children_) > 1:
|
448
467
|
table.add_section()
|
449
468
|
|
450
469
|
console.print(table)
|
@@ -453,17 +472,16 @@ async def get_children(
|
|
453
472
|
if netuid is None:
|
454
473
|
# get all netuids
|
455
474
|
netuids = await subtensor.get_all_subnet_netuids()
|
456
|
-
await get_total_stake_for_hk(wallet.hotkey.ss58_address, True)
|
457
475
|
netuid_children_tuples = []
|
458
|
-
for
|
476
|
+
for netuid_ in netuids:
|
459
477
|
success, children, err_mg = await subtensor.get_children(
|
460
|
-
wallet.hotkey.ss58_address,
|
478
|
+
wallet.hotkey.ss58_address, netuid_
|
461
479
|
)
|
462
480
|
if children:
|
463
|
-
netuid_children_tuples.append((
|
481
|
+
netuid_children_tuples.append((netuid_, children))
|
464
482
|
if not success:
|
465
483
|
err_console.print(
|
466
|
-
f"Failed to get children from subtensor {
|
484
|
+
f"Failed to get children from subtensor {netuid_}: {err_mg}"
|
467
485
|
)
|
468
486
|
await _render_table(wallet.hotkey.ss58_address, netuid_children_tuples)
|
469
487
|
else:
|
@@ -472,7 +490,6 @@ async def get_children(
|
|
472
490
|
)
|
473
491
|
if not success:
|
474
492
|
err_console.print(f"Failed to get children from subtensor: {err_mg}")
|
475
|
-
await get_total_stake_for_hk(wallet.hotkey.ss58_address, True)
|
476
493
|
if children:
|
477
494
|
netuid_children_tuples = [(netuid, children)]
|
478
495
|
await _render_table(wallet.hotkey.ss58_address, netuid_children_tuples)
|
@@ -485,13 +502,15 @@ async def set_children(
|
|
485
502
|
subtensor: "SubtensorInterface",
|
486
503
|
children: list[str],
|
487
504
|
proportions: list[float],
|
488
|
-
netuid: Optional[int]
|
505
|
+
netuid: Optional[int],
|
489
506
|
wait_for_inclusion: bool = True,
|
490
507
|
wait_for_finalization: bool = True,
|
491
508
|
prompt: bool = True,
|
492
509
|
):
|
493
510
|
"""Set children hotkeys."""
|
494
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
|
495
514
|
for child in children:
|
496
515
|
if not is_valid_ss58_address(child):
|
497
516
|
err_console.print(f":cross_mark:[red] Invalid SS58 address: {child}[/red]")
|
@@ -506,14 +525,13 @@ async def set_children(
|
|
506
525
|
f"Invalid proportion: The sum of all proportions cannot be greater than 1. "
|
507
526
|
f"Proposed sum of proportions is {total_proposed}."
|
508
527
|
)
|
509
|
-
|
510
528
|
children_with_proportions = list(zip(proportions, children))
|
511
|
-
if netuid:
|
529
|
+
if netuid is not None:
|
512
530
|
success, message = await set_children_extrinsic(
|
513
531
|
subtensor=subtensor,
|
514
532
|
wallet=wallet,
|
515
533
|
netuid=netuid,
|
516
|
-
hotkey=
|
534
|
+
hotkey=hotkey,
|
517
535
|
children_with_proportions=children_with_proportions,
|
518
536
|
prompt=prompt,
|
519
537
|
wait_for_inclusion=wait_for_inclusion,
|
@@ -522,8 +540,14 @@ async def set_children(
|
|
522
540
|
# Result
|
523
541
|
if success:
|
524
542
|
if wait_for_inclusion and wait_for_finalization:
|
525
|
-
|
526
|
-
|
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"assuming you have the required key swap cost (default: 0.1 Tao) in your coldkey at that time. "
|
549
|
+
f"The current block is {current_block}"
|
550
|
+
)
|
527
551
|
console.print(
|
528
552
|
":white_heavy_check_mark: [green]Set children hotkeys.[/green]"
|
529
553
|
)
|
@@ -534,20 +558,28 @@ async def set_children(
|
|
534
558
|
else:
|
535
559
|
# set children on all subnets that parent is registered on
|
536
560
|
netuids = await subtensor.get_all_subnet_netuids()
|
537
|
-
for
|
538
|
-
if
|
561
|
+
for netuid_ in netuids:
|
562
|
+
if netuid_ == 0: # dont include root network
|
539
563
|
continue
|
540
|
-
console.print(f"Setting children on netuid {
|
564
|
+
console.print(f"Setting children on netuid {netuid_}.")
|
541
565
|
await set_children_extrinsic(
|
542
566
|
subtensor=subtensor,
|
543
567
|
wallet=wallet,
|
544
|
-
netuid=
|
545
|
-
hotkey=
|
568
|
+
netuid=netuid_,
|
569
|
+
hotkey=hotkey,
|
546
570
|
children_with_proportions=children_with_proportions,
|
547
571
|
prompt=prompt,
|
548
572
|
wait_for_inclusion=True,
|
549
573
|
wait_for_finalization=False,
|
550
574
|
)
|
575
|
+
current_block, completion_block = await get_childkey_completion_block(
|
576
|
+
subtensor, netuid_
|
577
|
+
)
|
578
|
+
console.print(
|
579
|
+
f"Your childkey request for netuid {netuid_} has been submitted. It will be completed around "
|
580
|
+
f"block {completion_block}, assuming you have the required key swap cost (default: 0.1 Tao) in your "
|
581
|
+
f"coldkey at that time. The current block is {current_block}."
|
582
|
+
)
|
551
583
|
console.print(
|
552
584
|
":white_heavy_check_mark: [green]Sent set children request for all subnets.[/green]"
|
553
585
|
)
|
@@ -559,8 +591,8 @@ async def revoke_children(
|
|
559
591
|
netuid: Optional[int] = None,
|
560
592
|
wait_for_inclusion: bool = True,
|
561
593
|
wait_for_finalization: bool = True,
|
562
|
-
prompt: bool = True,
|
563
594
|
):
|
595
|
+
# TODO seek clarification on use of asking hotkey vs how we do it now
|
564
596
|
"""
|
565
597
|
Revokes the children hotkeys associated with a given network identifier (netuid).
|
566
598
|
"""
|
@@ -571,7 +603,7 @@ async def revoke_children(
|
|
571
603
|
netuid=netuid,
|
572
604
|
hotkey=wallet.hotkey.ss58_address,
|
573
605
|
children_with_proportions=[],
|
574
|
-
prompt=
|
606
|
+
prompt=True,
|
575
607
|
wait_for_inclusion=wait_for_inclusion,
|
576
608
|
wait_for_finalization=wait_for_finalization,
|
577
609
|
)
|
@@ -600,7 +632,7 @@ async def revoke_children(
|
|
600
632
|
netuid=netuid,
|
601
633
|
hotkey=wallet.hotkey.ss58_address,
|
602
634
|
children_with_proportions=[],
|
603
|
-
prompt=
|
635
|
+
prompt=False,
|
604
636
|
wait_for_inclusion=True,
|
605
637
|
wait_for_finalization=False,
|
606
638
|
)
|
@@ -760,7 +792,7 @@ async def childkey_take(
|
|
760
792
|
netuid=netuid,
|
761
793
|
hotkey=wallet.hotkey.ss58_address,
|
762
794
|
take=take,
|
763
|
-
prompt=
|
795
|
+
prompt=False,
|
764
796
|
wait_for_inclusion=True,
|
765
797
|
wait_for_finalization=False,
|
766
798
|
)
|