bittensor-cli 8.4.3__py3-none-any.whl → 9.0.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.
Files changed (33) hide show
  1. bittensor_cli/__init__.py +1 -1
  2. bittensor_cli/cli.py +1827 -1392
  3. bittensor_cli/src/__init__.py +623 -168
  4. bittensor_cli/src/bittensor/balances.py +41 -8
  5. bittensor_cli/src/bittensor/chain_data.py +557 -428
  6. bittensor_cli/src/bittensor/extrinsics/registration.py +129 -23
  7. bittensor_cli/src/bittensor/extrinsics/root.py +3 -3
  8. bittensor_cli/src/bittensor/extrinsics/transfer.py +6 -11
  9. bittensor_cli/src/bittensor/minigraph.py +46 -8
  10. bittensor_cli/src/bittensor/subtensor_interface.py +567 -250
  11. bittensor_cli/src/bittensor/utils.py +399 -25
  12. bittensor_cli/src/commands/stake/__init__.py +154 -0
  13. bittensor_cli/src/commands/stake/add.py +625 -0
  14. bittensor_cli/src/commands/stake/children_hotkeys.py +103 -75
  15. bittensor_cli/src/commands/stake/list.py +687 -0
  16. bittensor_cli/src/commands/stake/move.py +1000 -0
  17. bittensor_cli/src/commands/stake/remove.py +1146 -0
  18. bittensor_cli/src/commands/subnets/__init__.py +0 -0
  19. bittensor_cli/src/commands/subnets/price.py +867 -0
  20. bittensor_cli/src/commands/subnets/subnets.py +2028 -0
  21. bittensor_cli/src/commands/sudo.py +554 -12
  22. bittensor_cli/src/commands/wallets.py +225 -531
  23. bittensor_cli/src/commands/weights.py +2 -2
  24. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0.dist-info}/METADATA +7 -4
  25. bittensor_cli-9.0.0.dist-info/RECORD +34 -0
  26. bittensor_cli/src/bittensor/async_substrate_interface.py +0 -2748
  27. bittensor_cli/src/commands/root.py +0 -1752
  28. bittensor_cli/src/commands/stake/stake.py +0 -1448
  29. bittensor_cli/src/commands/subnets.py +0 -897
  30. bittensor_cli-8.4.3.dist-info/RECORD +0 -31
  31. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0.dist-info}/WHEEL +0 -0
  32. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0.dist-info}/entry_points.txt +0 -0
  33. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,7 @@ from bittensor_wallet import Wallet
5
5
  from rich.prompt import Confirm, Prompt, IntPrompt
6
6
  from rich.table import Table
7
7
  from rich.text import Text
8
- from substrateinterface.exceptions import SubstrateRequestException
8
+ from async_substrate_interface.errors import SubstrateRequestException
9
9
 
10
10
  from bittensor_cli.src.bittensor.balances import Balance
11
11
  from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface
@@ -22,6 +22,33 @@ from bittensor_cli.src.bittensor.utils import (
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,
@@ -223,13 +250,13 @@ async def get_childkey_take(subtensor, hotkey: str, netuid: int) -> Optional[int
223
250
  - Optional[float]: The value of the "ChildkeyTake" if found, or None if any error occurs.
224
251
  """
225
252
  try:
226
- childkey_take_ = await subtensor.substrate.query(
253
+ childkey_take_ = await subtensor.query(
227
254
  module="SubtensorModule",
228
255
  storage_function="ChildkeyTake",
229
256
  params=[hotkey, netuid],
230
257
  )
231
258
  if childkey_take_:
232
- return int(childkey_take_)
259
+ return int(childkey_take_.value)
233
260
 
234
261
  except SubstrateRequestException as e:
235
262
  err_console.print(f"Error querying ChildKeys: {format_error_message(e)}")
@@ -264,6 +291,7 @@ def prepare_child_proportions(children_with_proportions):
264
291
  async def get_children(
265
292
  wallet: Wallet, subtensor: "SubtensorInterface", netuid: Optional[int] = None
266
293
  ):
294
+ # TODO rao asks separately for the hotkey from the user, should we do this, or the way we do it now?
267
295
  """
268
296
  Retrieves the child hotkeys for the specified wallet.
269
297
 
@@ -281,35 +309,7 @@ async def get_children(
281
309
  - If netuid is not specified, generates and prints a summary table of all child hotkeys across all subnets.
282
310
  """
283
311
 
284
- async def get_total_stake_for_hk(hotkey: str, parent: bool = False):
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:
312
+ async def get_take(child: tuple, netuid__: int) -> float:
313
313
  """
314
314
  Get the take value for a given subtensor, hotkey, and netuid.
315
315
 
@@ -320,7 +320,7 @@ async def get_children(
320
320
  """
321
321
  child_hotkey = child[1]
322
322
  take_u16 = await get_childkey_take(
323
- subtensor=subtensor, hotkey=child_hotkey, netuid=netuid
323
+ subtensor=subtensor, hotkey=child_hotkey, netuid=netuid__
324
324
  )
325
325
  if take_u16:
326
326
  return u16_to_float(take_u16)
@@ -329,7 +329,7 @@ async def get_children(
329
329
 
330
330
  async def _render_table(
331
331
  parent_hotkey: str,
332
- netuid_children_tuples: list[tuple[int, list[tuple[int, str]]]],
332
+ netuid_children_: list[tuple[int, list[tuple[int, str]]]],
333
333
  ):
334
334
  """
335
335
  Retrieves and renders children hotkeys and their details for a given parent hotkey.
@@ -352,10 +352,11 @@ async def get_children(
352
352
  "Current Stake Weight", style="bold red", no_wrap=True, justify="right"
353
353
  )
354
354
 
355
- if not netuid_children_tuples:
355
+ if not netuid_children_:
356
356
  console.print(table)
357
357
  console.print(
358
- f"[bold red]There are currently no child hotkeys with parent hotkey: {wallet.name} ({parent_hotkey}).[/bold red]"
358
+ f"[bold red]There are currently no child hotkeys with parent hotkey: "
359
+ f"{wallet.name} | {wallet.hotkey_str} ({parent_hotkey}).[/bold red]"
359
360
  )
360
361
  return
361
362
 
@@ -363,48 +364,64 @@ async def get_children(
363
364
  total_proportion = 0
364
365
  total_stake_weight = 0
365
366
 
366
- netuid_children_tuples.sort(
367
- key=lambda x: x[0]
368
- ) # Sort by netuid in ascending order
367
+ netuid_children_.sort(key=lambda x: x[0]) # Sort by netuid in ascending order
368
+ unique_keys = set(
369
+ [parent_hotkey]
370
+ + [s for _, child_list in netuid_children_ for _, s in child_list]
371
+ )
372
+ hotkey_stake_dict = await subtensor.get_total_stake_for_hotkey(
373
+ *unique_keys,
374
+ netuids=[n[0] for n in netuid_children_],
375
+ )
376
+ parent_total = sum(hotkey_stake_dict[parent_hotkey].values())
377
+ insert_text = (
378
+ " "
379
+ if netuid is None
380
+ else f" on netuids: {', '.join(str(n[0]) for n in netuid_children_)} "
381
+ )
382
+ console.print(
383
+ f"The total stake of parent hotkey '{parent_hotkey}'{insert_text}is {parent_total}."
384
+ )
369
385
 
370
- for index, (netuid, children_) in enumerate(netuid_children_tuples):
386
+ for index, (netuid_, children_) in enumerate(netuid_children_):
371
387
  # calculate totals
372
388
  total_proportion_per_netuid = 0
373
389
  total_stake_weight_per_netuid = 0
374
- avg_take_per_netuid = 0
390
+ avg_take_per_netuid = 0.0
375
391
 
376
- hotkey_stake_dict = await subtensor.get_total_stake_for_hotkey(
377
- parent_hotkey
378
- )
379
- hotkey_stake = hotkey_stake_dict.get(parent_hotkey, Balance(0))
392
+ hotkey_stake: dict[int, Balance] = hotkey_stake_dict[parent_hotkey]
380
393
 
381
394
  children_info = []
382
- child_stakes = await asyncio.gather(
383
- *[get_total_stake_for_hk(c[1]) for c in children_]
395
+ child_takes = await asyncio.gather(
396
+ *[get_take(c, netuid_) for c in children_]
384
397
  )
385
- child_takes = await asyncio.gather(*[get_take(c) for c in children_])
386
- for child, child_stake, child_take in zip(
387
- children_, child_stakes, child_takes
388
- ):
398
+ for child, child_take in zip(children_, child_takes):
389
399
  proportion = child[0]
390
400
  child_hotkey = child[1]
391
401
 
392
402
  # add to totals
393
403
  avg_take_per_netuid += child_take
394
404
 
395
- proportion = u64_to_float(proportion)
405
+ converted_proportion = u64_to_float(proportion)
396
406
 
397
407
  children_info.append(
398
- (proportion, child_hotkey, child_stake, child_take)
408
+ (
409
+ converted_proportion,
410
+ child_hotkey,
411
+ hotkey_stake_dict[child_hotkey][netuid_],
412
+ child_take,
413
+ )
399
414
  )
400
415
 
401
416
  children_info.sort(
402
417
  key=lambda x: x[0], reverse=True
403
418
  ) # sorting by proportion (highest first)
404
419
 
405
- for proportion, hotkey, stake, child_take in children_info:
406
- proportion_percent = proportion * 100 # Proportion in percent
407
- proportion_tao = hotkey_stake.tao * proportion # Proportion in TAO
420
+ for proportion_, hotkey, stake, child_take in children_info:
421
+ proportion_percent = proportion_ * 100 # Proportion in percent
422
+ proportion_tao = (
423
+ hotkey_stake[netuid_].tao * proportion_
424
+ ) # Proportion in TAO
408
425
 
409
426
  total_proportion_per_netuid += proportion_percent
410
427
 
@@ -414,9 +431,9 @@ async def get_children(
414
431
  total_stake_weight_per_netuid += stake_weight
415
432
  take_str = f"{child_take * 100:.3f}%"
416
433
 
417
- hotkey = Text(hotkey, style="italic red" if proportion == 0 else "")
434
+ hotkey = Text(hotkey, style="italic red" if proportion_ == 0 else "")
418
435
  table.add_row(
419
- str(netuid),
436
+ str(netuid_),
420
437
  hotkey,
421
438
  proportion_str,
422
439
  take_str,
@@ -440,7 +457,7 @@ async def get_children(
440
457
  total_stake_weight += total_stake_weight_per_netuid
441
458
 
442
459
  # Add a dividing line if there are more than one netuid
443
- if len(netuid_children_tuples) > 1:
460
+ if len(netuid_children_) > 1:
444
461
  table.add_section()
445
462
 
446
463
  console.print(table)
@@ -449,17 +466,16 @@ async def get_children(
449
466
  if netuid is None:
450
467
  # get all netuids
451
468
  netuids = await subtensor.get_all_subnet_netuids()
452
- await get_total_stake_for_hk(wallet.hotkey.ss58_address, True)
453
469
  netuid_children_tuples = []
454
- for netuid in netuids:
470
+ for netuid_ in netuids:
455
471
  success, children, err_mg = await subtensor.get_children(
456
- wallet.hotkey.ss58_address, netuid
472
+ wallet.hotkey.ss58_address, netuid_
457
473
  )
458
474
  if children:
459
- netuid_children_tuples.append((netuid, children))
475
+ netuid_children_tuples.append((netuid_, children))
460
476
  if not success:
461
477
  err_console.print(
462
- f"Failed to get children from subtensor {netuid}: {err_mg}"
478
+ f"Failed to get children from subtensor {netuid_}: {err_mg}"
463
479
  )
464
480
  await _render_table(wallet.hotkey.ss58_address, netuid_children_tuples)
465
481
  else:
@@ -468,7 +484,6 @@ async def get_children(
468
484
  )
469
485
  if not success:
470
486
  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
487
  if children:
473
488
  netuid_children_tuples = [(netuid, children)]
474
489
  await _render_table(wallet.hotkey.ss58_address, netuid_children_tuples)
@@ -488,6 +503,8 @@ async def set_children(
488
503
  ):
489
504
  """Set children hotkeys."""
490
505
  # Validate children SS58 addresses
506
+ # TODO check to see if this should be allowed to be specified by user instead of pulling from wallet
507
+ hotkey = wallet.hotkey.ss58_address
491
508
  for child in children:
492
509
  if not is_valid_ss58_address(child):
493
510
  err_console.print(f":cross_mark:[red] Invalid SS58 address: {child}[/red]")
@@ -502,14 +519,13 @@ async def set_children(
502
519
  f"Invalid proportion: The sum of all proportions cannot be greater than 1. "
503
520
  f"Proposed sum of proportions is {total_proposed}."
504
521
  )
505
-
506
522
  children_with_proportions = list(zip(proportions, children))
507
- if netuid:
523
+ if netuid is not None:
508
524
  success, message = await set_children_extrinsic(
509
525
  subtensor=subtensor,
510
526
  wallet=wallet,
511
527
  netuid=netuid,
512
- hotkey=wallet.hotkey.ss58_address,
528
+ hotkey=hotkey,
513
529
  children_with_proportions=children_with_proportions,
514
530
  prompt=prompt,
515
531
  wait_for_inclusion=wait_for_inclusion,
@@ -518,8 +534,13 @@ async def set_children(
518
534
  # Result
519
535
  if success:
520
536
  if wait_for_inclusion and wait_for_finalization:
521
- console.print("New Status:")
522
- await get_children(wallet, subtensor, netuid)
537
+ current_block, completion_block = await get_childkey_completion_block(
538
+ subtensor, netuid
539
+ )
540
+ console.print(
541
+ f"Your childkey request has been submitted. It will be completed around block {completion_block}. "
542
+ f"The current block is {current_block}"
543
+ )
523
544
  console.print(
524
545
  ":white_heavy_check_mark: [green]Set children hotkeys.[/green]"
525
546
  )
@@ -530,20 +551,27 @@ async def set_children(
530
551
  else:
531
552
  # set children on all subnets that parent is registered on
532
553
  netuids = await subtensor.get_all_subnet_netuids()
533
- for netuid in netuids:
534
- if netuid == 0: # dont include root network
554
+ for netuid_ in netuids:
555
+ if netuid_ == 0: # dont include root network
535
556
  continue
536
- console.print(f"Setting children on netuid {netuid}.")
557
+ console.print(f"Setting children on netuid {netuid_}.")
537
558
  await set_children_extrinsic(
538
559
  subtensor=subtensor,
539
560
  wallet=wallet,
540
- netuid=netuid,
541
- hotkey=wallet.hotkey.ss58_address,
561
+ netuid=netuid_,
562
+ hotkey=hotkey,
542
563
  children_with_proportions=children_with_proportions,
543
564
  prompt=prompt,
544
565
  wait_for_inclusion=True,
545
566
  wait_for_finalization=False,
546
567
  )
568
+ current_block, completion_block = await get_childkey_completion_block(
569
+ subtensor, netuid_
570
+ )
571
+ console.print(
572
+ f"Your childkey request for netuid {netuid_} has been submitted. It will be completed around "
573
+ f"block {completion_block}. The current block is {current_block}."
574
+ )
547
575
  console.print(
548
576
  ":white_heavy_check_mark: [green]Sent set children request for all subnets.[/green]"
549
577
  )