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.
Files changed (30) hide show
  1. bittensor_cli/__init__.py +2 -2
  2. bittensor_cli/cli.py +1508 -1385
  3. bittensor_cli/src/__init__.py +627 -197
  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 +161 -47
  7. bittensor_cli/src/bittensor/extrinsics/root.py +14 -8
  8. bittensor_cli/src/bittensor/extrinsics/transfer.py +14 -21
  9. bittensor_cli/src/bittensor/minigraph.py +46 -8
  10. bittensor_cli/src/bittensor/subtensor_interface.py +572 -253
  11. bittensor_cli/src/bittensor/utils.py +326 -75
  12. bittensor_cli/src/commands/stake/__init__.py +154 -0
  13. bittensor_cli/src/commands/stake/children_hotkeys.py +121 -87
  14. bittensor_cli/src/commands/stake/move.py +1000 -0
  15. bittensor_cli/src/commands/stake/stake.py +1637 -1264
  16. bittensor_cli/src/commands/subnets/__init__.py +0 -0
  17. bittensor_cli/src/commands/subnets/price.py +867 -0
  18. bittensor_cli/src/commands/subnets/subnets.py +2055 -0
  19. bittensor_cli/src/commands/sudo.py +529 -26
  20. bittensor_cli/src/commands/wallets.py +234 -544
  21. bittensor_cli/src/commands/weights.py +15 -11
  22. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/METADATA +7 -4
  23. bittensor_cli-9.0.0rc2.dist-info/RECORD +32 -0
  24. bittensor_cli/src/bittensor/async_substrate_interface.py +0 -2748
  25. bittensor_cli/src/commands/root.py +0 -1752
  26. bittensor_cli/src/commands/subnets.py +0 -897
  27. bittensor_cli-8.4.3.dist-info/RECORD +0 -31
  28. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/WHEEL +0 -0
  29. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/entry_points.txt +0 -0
  30. {bittensor_cli-8.4.3.dist-info → bittensor_cli-9.0.0rc2.dist-info}/top_level.txt +0 -0
@@ -1,897 +0,0 @@
1
- import asyncio
2
- import json
3
- import sqlite3
4
- from textwrap import dedent
5
- from typing import TYPE_CHECKING, Optional, cast
6
-
7
- from bittensor_wallet import Wallet
8
- from rich.prompt import Confirm
9
- from rich.table import Column, Table
10
-
11
- from bittensor_cli.src import DelegatesDetails
12
- from bittensor_cli.src.bittensor.balances import Balance
13
- from bittensor_cli.src.bittensor.chain_data import SubnetInfo
14
- from bittensor_cli.src.bittensor.extrinsics.registration import register_extrinsic
15
- from bittensor_cli.src.bittensor.minigraph import MiniGraph
16
- from bittensor_cli.src.commands.root import burned_register_extrinsic
17
- from bittensor_cli.src.commands.wallets import set_id, set_id_prompts
18
- from bittensor_cli.src.bittensor.utils import (
19
- RAO_PER_TAO,
20
- console,
21
- create_table,
22
- err_console,
23
- print_verbose,
24
- print_error,
25
- format_error_message,
26
- get_metadata_table,
27
- millify,
28
- render_table,
29
- update_metadata_table,
30
- unlock_key,
31
- hex_to_bytes,
32
- )
33
-
34
- if TYPE_CHECKING:
35
- from bittensor_cli.src.bittensor.subtensor_interface import SubtensorInterface
36
-
37
-
38
- # helpers and extrinsics
39
-
40
-
41
- async def register_subnetwork_extrinsic(
42
- subtensor: "SubtensorInterface",
43
- wallet: Wallet,
44
- wait_for_inclusion: bool = False,
45
- wait_for_finalization: bool = True,
46
- prompt: bool = False,
47
- ) -> bool:
48
- """Registers a new subnetwork.
49
-
50
- wallet (bittensor.wallet):
51
- bittensor wallet object.
52
- wait_for_inclusion (bool):
53
- If set, waits for the extrinsic to enter a block before returning ``true``, or returns ``false`` if the extrinsic fails to enter the block within the timeout.
54
- wait_for_finalization (bool):
55
- If set, waits for the extrinsic to be finalized on the chain before returning ``true``, or returns ``false`` if the extrinsic fails to be finalized within the timeout.
56
- prompt (bool):
57
- If true, the call waits for confirmation from the user before proceeding.
58
- Returns:
59
- success (bool):
60
- Flag is ``true`` if extrinsic was finalized or included in the block.
61
- If we did not wait for finalization / inclusion, the response is ``true``.
62
- """
63
-
64
- async def _find_event_attributes_in_extrinsic_receipt(
65
- response_, event_name: str
66
- ) -> list:
67
- """
68
- Searches for the attributes of a specified event within an extrinsic receipt.
69
-
70
- :param response_: (substrateinterface.base.ExtrinsicReceipt): The receipt of the extrinsic to be searched.
71
- :param event_name: The name of the event to search for.
72
-
73
- :return: A list of attributes for the specified event. Returns [-1] if the event is not found.
74
- """
75
- for event in await response_.triggered_events:
76
- # Access the event details
77
- event_details = event["event"]
78
- # Check if the event_id is 'NetworkAdded'
79
- if event_details["event_id"] == event_name:
80
- # Once found, you can access the attributes of the event_name
81
- return event_details["attributes"]
82
- return [-1]
83
-
84
- print_verbose("Fetching balance")
85
- your_balance_ = await subtensor.get_balance(wallet.coldkeypub.ss58_address)
86
- your_balance = your_balance_[wallet.coldkeypub.ss58_address]
87
-
88
- print_verbose("Fetching lock_cost")
89
- burn_cost = await lock_cost(subtensor)
90
- if burn_cost > your_balance:
91
- err_console.print(
92
- f"Your balance of: [green]{your_balance}[/green] is not enough to pay the subnet lock cost of: "
93
- f"[green]{burn_cost}[/green]"
94
- )
95
- return False
96
-
97
- if prompt:
98
- console.print(f"Your balance is: [green]{your_balance}[/green]")
99
- if not Confirm.ask(
100
- f"Do you want to register a subnet for [green]{burn_cost}[/green]?"
101
- ):
102
- return False
103
-
104
- if not unlock_key(wallet).success:
105
- return False
106
-
107
- with console.status(":satellite: Registering subnet...", spinner="earth"):
108
- substrate = subtensor.substrate
109
- # create extrinsic call
110
- call = await substrate.compose_call(
111
- call_module="SubtensorModule",
112
- call_function="register_network",
113
- call_params={"immunity_period": 0, "reg_allowed": True},
114
- )
115
- extrinsic = await substrate.create_signed_extrinsic(
116
- call=call, keypair=wallet.coldkey
117
- )
118
- response = await substrate.submit_extrinsic(
119
- extrinsic,
120
- wait_for_inclusion=wait_for_inclusion,
121
- wait_for_finalization=wait_for_finalization,
122
- )
123
-
124
- # We only wait here if we expect finalization.
125
- if not wait_for_finalization and not wait_for_inclusion:
126
- return True
127
-
128
- await response.process_events()
129
- if not await response.is_success:
130
- err_console.print(
131
- f":cross_mark: [red]Failed[/red]: {format_error_message(await response.error_message)}"
132
- )
133
- await asyncio.sleep(0.5)
134
- return False
135
-
136
- # Successful registration, final check for membership
137
- else:
138
- attributes = await _find_event_attributes_in_extrinsic_receipt(
139
- response, "NetworkAdded"
140
- )
141
- console.print(
142
- f":white_heavy_check_mark: [green]Registered subnetwork with netuid: {attributes[0]}[/green]"
143
- )
144
- return True
145
-
146
-
147
- # commands
148
-
149
-
150
- async def subnets_list(
151
- subtensor: "SubtensorInterface", reuse_last: bool, html_output: bool, no_cache: bool
152
- ):
153
- """List all subnet netuids in the network."""
154
-
155
- async def _get_all_subnets_info():
156
- hex_bytes_result = await subtensor.query_runtime_api(
157
- runtime_api="SubnetInfoRuntimeApi", method="get_subnets_info", params=[]
158
- )
159
-
160
- return SubnetInfo.list_from_vec_u8(hex_to_bytes(hex_bytes_result))
161
-
162
- if not reuse_last:
163
- subnets: list[SubnetInfo]
164
- delegate_info: dict[str, DelegatesDetails]
165
-
166
- print_verbose("Fetching subnet and delegate information")
167
- subnets, delegate_info = await asyncio.gather(
168
- _get_all_subnets_info(),
169
- subtensor.get_delegate_identities(),
170
- )
171
-
172
- if not subnets:
173
- err_console.print("[red]No subnets found[/red]")
174
- return
175
-
176
- rows = []
177
- db_rows = []
178
- total_neurons = 0
179
- max_neurons = 0
180
-
181
- for subnet in subnets:
182
- total_neurons += subnet.subnetwork_n
183
- max_neurons += subnet.max_n
184
- rows.append(
185
- (
186
- str(subnet.netuid),
187
- str(subnet.subnetwork_n),
188
- str(millify(subnet.max_n)),
189
- f"{subnet.emission_value / RAO_PER_TAO * 100:0.2f}%",
190
- str(subnet.tempo),
191
- f"{subnet.burn!s:8.8}",
192
- str(millify(subnet.difficulty)),
193
- str(
194
- delegate_info[subnet.owner_ss58].display
195
- if subnet.owner_ss58 in delegate_info
196
- else subnet.owner_ss58
197
- ),
198
- )
199
- )
200
- db_rows.append(
201
- [
202
- int(subnet.netuid),
203
- int(subnet.subnetwork_n),
204
- int(subnet.max_n), # millified in HTML table
205
- float(
206
- subnet.emission_value / RAO_PER_TAO * 100
207
- ), # shown as percentage in HTML table
208
- int(subnet.tempo),
209
- float(subnet.burn),
210
- int(subnet.difficulty), # millified in HTML table
211
- str(
212
- delegate_info[subnet.owner_ss58].display
213
- if subnet.owner_ss58 in delegate_info
214
- else subnet.owner_ss58
215
- ),
216
- ]
217
- )
218
- metadata = {
219
- "network": subtensor.network,
220
- "netuid_count": len(subnets),
221
- "N": total_neurons,
222
- "MAX_N": max_neurons,
223
- "rows": json.dumps(rows),
224
- }
225
- if not no_cache:
226
- create_table(
227
- "subnetslist",
228
- [
229
- ("NETUID", "INTEGER"),
230
- ("N", "INTEGER"),
231
- ("MAX_N", "BLOB"),
232
- ("EMISSION", "REAL"),
233
- ("TEMPO", "INTEGER"),
234
- ("RECYCLE", "REAL"),
235
- ("DIFFICULTY", "BLOB"),
236
- ("SUDO", "TEXT"),
237
- ],
238
- db_rows,
239
- )
240
- update_metadata_table("subnetslist", values=metadata)
241
- else:
242
- try:
243
- metadata = get_metadata_table("subnetslist")
244
- rows = json.loads(metadata["rows"])
245
- except sqlite3.OperationalError:
246
- err_console.print(
247
- "[red]Error[/red] Unable to retrieve table data. This is usually caused by attempting to use "
248
- "`--reuse-last` before running the command a first time. In rare cases, this could also be due to "
249
- "a corrupted database. Re-run the command (do not use `--reuse-last`) and see if that resolves your "
250
- "issue."
251
- )
252
- return
253
- if not html_output:
254
- table = Table(
255
- title=f"[underline dark_orange]Subnets[/underline dark_orange]\n[dark_orange]Network: {metadata['network']}[/dark_orange]\n",
256
- show_footer=True,
257
- show_edge=False,
258
- header_style="bold white",
259
- border_style="bright_black",
260
- style="bold",
261
- title_justify="center",
262
- show_lines=False,
263
- pad_edge=True,
264
- )
265
-
266
- table.add_column(
267
- "[bold white]NETUID",
268
- footer=f"[white]{metadata['netuid_count']}[/white]",
269
- style="white",
270
- justify="center",
271
- )
272
- table.add_column(
273
- "[bold white]N",
274
- footer=f"[white]{metadata['N']}[/white]",
275
- style="bright_cyan",
276
- justify="right",
277
- )
278
- table.add_column(
279
- "[bold white]MAX_N",
280
- footer=f"[white]{metadata['MAX_N']}[/white]",
281
- style="bright_cyan",
282
- justify="right",
283
- )
284
- table.add_column(
285
- "[bold white]EMISSION", style="light_goldenrod2", justify="right"
286
- )
287
- table.add_column("[bold white]TEMPO", style="rgb(42,161,152)", justify="right")
288
- table.add_column("[bold white]RECYCLE", style="light_salmon3", justify="right")
289
- table.add_column("[bold white]POW", style="medium_purple", justify="right")
290
- table.add_column(
291
- "[bold white]SUDO", style="bright_magenta", justify="right", overflow="fold"
292
- )
293
-
294
- for row in rows:
295
- table.add_row(*row)
296
-
297
- console.print(table)
298
- console.print(
299
- dedent(
300
- """
301
- Description:
302
- The table displays the list of subnets registered in the Bittensor network.
303
- - NETUID: The network identifier of the subnet.
304
- - N: The current UIDs registered to the network.
305
- - MAX_N: The total UIDs allowed on the network.
306
- - EMISSION: The emission accrued by this subnet in the network.
307
- - TEMPO: A duration of a number of blocks. Several subnet events occur at the end of every tempo period.
308
- - RECYCLE: Cost to register to the subnet.
309
- - POW: Proof of work metric of the subnet.
310
- - SUDO: Owner's identity.
311
- """
312
- )
313
- )
314
- else:
315
- render_table(
316
- "subnetslist",
317
- f"Subnets List | Network: {metadata['network']} - "
318
- f"Netuids: {metadata['netuid_count']} - N: {metadata['N']}",
319
- columns=[
320
- {"title": "NetUID", "field": "NETUID"},
321
- {"title": "N", "field": "N"},
322
- {"title": "MAX_N", "field": "MAX_N", "customFormatter": "millify"},
323
- {
324
- "title": "EMISSION",
325
- "field": "EMISSION",
326
- "formatter": "money",
327
- "formatterParams": {
328
- "symbolAfter": "p",
329
- "symbol": "%",
330
- "precision": 2,
331
- },
332
- },
333
- {"title": "Tempo", "field": "TEMPO"},
334
- {
335
- "title": "Recycle",
336
- "field": "RECYCLE",
337
- "formatter": "money",
338
- "formatterParams": {"symbol": "τ", "precision": 5},
339
- },
340
- {
341
- "title": "Difficulty",
342
- "field": "DIFFICULTY",
343
- "customFormatter": "millify",
344
- },
345
- {"title": "sudo", "field": "SUDO"},
346
- ],
347
- )
348
-
349
-
350
- async def lock_cost(subtensor: "SubtensorInterface") -> Optional[Balance]:
351
- """View locking cost of creating a new subnetwork"""
352
- with console.status(
353
- f":satellite:Retrieving lock cost from {subtensor.network}...",
354
- spinner="aesthetic",
355
- ):
356
- lc = await subtensor.query_runtime_api(
357
- runtime_api="SubnetRegistrationRuntimeApi",
358
- method="get_network_registration_cost",
359
- params=[],
360
- )
361
- if lc:
362
- lock_cost_ = Balance(lc)
363
- console.print(f"Subnet lock cost: [green]{lock_cost_}[/green]")
364
- return lock_cost_
365
- else:
366
- err_console.print("Subnet lock cost: [red]Failed to get subnet lock cost[/red]")
367
- return None
368
-
369
-
370
- async def create(wallet: Wallet, subtensor: "SubtensorInterface", prompt: bool):
371
- """Register a subnetwork"""
372
-
373
- # Call register command.
374
- success = await register_subnetwork_extrinsic(subtensor, wallet, prompt=prompt)
375
- if success and prompt:
376
- # Prompt for user to set identity.
377
- do_set_identity = Confirm.ask(
378
- "Subnetwork registered successfully. Would you like to set your identity?"
379
- )
380
-
381
- if do_set_identity:
382
- id_prompts = set_id_prompts(validator=False)
383
- await set_id(wallet, subtensor, *id_prompts, prompt=prompt)
384
-
385
-
386
- async def pow_register(
387
- wallet: Wallet,
388
- subtensor: "SubtensorInterface",
389
- netuid,
390
- processors,
391
- update_interval,
392
- output_in_place,
393
- verbose,
394
- use_cuda,
395
- dev_id,
396
- threads_per_block,
397
- prompt: bool,
398
- ):
399
- """Register neuron."""
400
-
401
- await register_extrinsic(
402
- subtensor,
403
- wallet=wallet,
404
- netuid=netuid,
405
- prompt=prompt,
406
- tpb=threads_per_block,
407
- update_interval=update_interval,
408
- num_processes=processors,
409
- cuda=use_cuda,
410
- dev_id=dev_id,
411
- output_in_place=output_in_place,
412
- log_verbose=verbose,
413
- )
414
-
415
-
416
- async def register(
417
- wallet: Wallet, subtensor: "SubtensorInterface", netuid: int, prompt: bool
418
- ):
419
- """Register neuron by recycling some TAO."""
420
-
421
- # Verify subnet exists
422
- print_verbose("Checking subnet status")
423
- block_hash = await subtensor.substrate.get_chain_head()
424
- if not await subtensor.subnet_exists(netuid=netuid, block_hash=block_hash):
425
- err_console.print(f"[red]Subnet {netuid} does not exist[/red]")
426
- return
427
-
428
- # Check current recycle amount
429
- print_verbose("Fetching recycle amount")
430
- current_recycle_, balance_ = await asyncio.gather(
431
- subtensor.get_hyperparameter(
432
- param_name="Burn", netuid=netuid, block_hash=block_hash
433
- ),
434
- subtensor.get_balance(wallet.coldkeypub.ss58_address, block_hash=block_hash),
435
- )
436
- current_recycle = (
437
- Balance.from_rao(int(current_recycle_)) if current_recycle_ else Balance(0)
438
- )
439
- balance = balance_[wallet.coldkeypub.ss58_address]
440
-
441
- # Check balance is sufficient
442
- if balance < current_recycle:
443
- err_console.print(
444
- f"[red]Insufficient balance {balance} to register neuron. Current recycle is {current_recycle} TAO[/red]"
445
- )
446
- return
447
-
448
- if prompt:
449
- if not (
450
- Confirm.ask(
451
- f"Your balance is: [bold green]{balance}[/bold green]\nThe cost to register by recycle is "
452
- f"[bold red]{current_recycle}[/bold red]\nDo you want to continue?",
453
- default=False,
454
- )
455
- ):
456
- return
457
-
458
- await burned_register_extrinsic(
459
- subtensor,
460
- wallet=wallet,
461
- netuid=netuid,
462
- prompt=False,
463
- recycle_amount=current_recycle,
464
- old_balance=balance,
465
- )
466
-
467
-
468
- async def metagraph_cmd(
469
- subtensor: Optional["SubtensorInterface"],
470
- netuid: Optional[int],
471
- reuse_last: bool,
472
- html_output: bool,
473
- no_cache: bool,
474
- display_cols: dict,
475
- ):
476
- """Prints an entire metagraph."""
477
- # TODO allow config to set certain columns
478
- if not reuse_last:
479
- cast("SubtensorInterface", subtensor)
480
- cast(int, netuid)
481
- with console.status(
482
- f":satellite: Syncing with chain: [white]{subtensor.network}[/white] ...",
483
- spinner="aesthetic",
484
- ) as status:
485
- block_hash = await subtensor.substrate.get_chain_head()
486
-
487
- if not await subtensor.subnet_exists(netuid, block_hash):
488
- print_error(f"Subnet with netuid: {netuid} does not exist", status)
489
- return False
490
-
491
- neurons, difficulty_, total_issuance_, block = await asyncio.gather(
492
- subtensor.neurons(netuid, block_hash=block_hash),
493
- subtensor.get_hyperparameter(
494
- param_name="Difficulty", netuid=netuid, block_hash=block_hash
495
- ),
496
- subtensor.substrate.query(
497
- module="SubtensorModule",
498
- storage_function="TotalIssuance",
499
- params=[],
500
- block_hash=block_hash,
501
- ),
502
- subtensor.substrate.get_block_number(block_hash=block_hash),
503
- )
504
-
505
- difficulty = int(difficulty_)
506
- total_issuance = Balance.from_rao(total_issuance_)
507
- metagraph = MiniGraph(
508
- netuid=netuid, neurons=neurons, subtensor=subtensor, block=block
509
- )
510
- table_data = []
511
- db_table = []
512
- total_stake = 0.0
513
- total_rank = 0.0
514
- total_validator_trust = 0.0
515
- total_trust = 0.0
516
- total_consensus = 0.0
517
- total_incentive = 0.0
518
- total_dividends = 0.0
519
- total_emission = 0
520
- for uid in metagraph.uids:
521
- neuron = metagraph.neurons[uid]
522
- ep = metagraph.axons[uid]
523
- row = [
524
- str(neuron.uid),
525
- "{:.5f}".format(metagraph.total_stake[uid]),
526
- "{:.5f}".format(metagraph.ranks[uid]),
527
- "{:.5f}".format(metagraph.trust[uid]),
528
- "{:.5f}".format(metagraph.consensus[uid]),
529
- "{:.5f}".format(metagraph.incentive[uid]),
530
- "{:.5f}".format(metagraph.dividends[uid]),
531
- "{}".format(int(metagraph.emission[uid] * 1000000000)),
532
- "{:.5f}".format(metagraph.validator_trust[uid]),
533
- "*" if metagraph.validator_permit[uid] else "",
534
- str(metagraph.block.item() - metagraph.last_update[uid].item()),
535
- str(metagraph.active[uid].item()),
536
- (
537
- ep.ip + ":" + str(ep.port)
538
- if ep.is_serving
539
- else "[light_goldenrod2]none[/light_goldenrod2]"
540
- ),
541
- ep.hotkey[:10],
542
- ep.coldkey[:10],
543
- ]
544
- db_row = [
545
- neuron.uid,
546
- float(metagraph.total_stake[uid]),
547
- float(metagraph.ranks[uid]),
548
- float(metagraph.trust[uid]),
549
- float(metagraph.consensus[uid]),
550
- float(metagraph.incentive[uid]),
551
- float(metagraph.dividends[uid]),
552
- int(metagraph.emission[uid] * 1000000000),
553
- float(metagraph.validator_trust[uid]),
554
- bool(metagraph.validator_permit[uid]),
555
- metagraph.block.item() - metagraph.last_update[uid].item(),
556
- metagraph.active[uid].item(),
557
- (ep.ip + ":" + str(ep.port) if ep.is_serving else "ERROR"),
558
- ep.hotkey[:10],
559
- ep.coldkey[:10],
560
- ]
561
- db_table.append(db_row)
562
- total_stake += metagraph.total_stake[uid]
563
- total_rank += metagraph.ranks[uid]
564
- total_validator_trust += metagraph.validator_trust[uid]
565
- total_trust += metagraph.trust[uid]
566
- total_consensus += metagraph.consensus[uid]
567
- total_incentive += metagraph.incentive[uid]
568
- total_dividends += metagraph.dividends[uid]
569
- total_emission += int(metagraph.emission[uid] * 1000000000)
570
- table_data.append(row)
571
- metadata_info = {
572
- "stake": str(Balance.from_tao(total_stake)),
573
- "total_stake": "\u03c4{:.5f}".format(total_stake),
574
- "rank": "{:.5f}".format(total_rank),
575
- "validator_trust": "{:.5f}".format(total_validator_trust),
576
- "trust": "{:.5f}".format(total_trust),
577
- "consensus": "{:.5f}".format(total_consensus),
578
- "incentive": "{:.5f}".format(total_incentive),
579
- "dividends": "{:.5f}".format(total_dividends),
580
- "emission": "\u03c1{}".format(int(total_emission)),
581
- "net": f"{subtensor.network}:{metagraph.netuid}",
582
- "block": str(metagraph.block.item()),
583
- "N": f"{sum(metagraph.active.tolist())}/{metagraph.n.item()}",
584
- "N0": str(sum(metagraph.active.tolist())),
585
- "N1": str(metagraph.n.item()),
586
- "issuance": str(total_issuance),
587
- "difficulty": str(difficulty),
588
- "total_neurons": str(len(metagraph.uids)),
589
- "table_data": json.dumps(table_data),
590
- }
591
- if not no_cache:
592
- update_metadata_table("metagraph", metadata_info)
593
- create_table(
594
- "metagraph",
595
- columns=[
596
- ("UID", "INTEGER"),
597
- ("STAKE", "REAL"),
598
- ("RANK", "REAL"),
599
- ("TRUST", "REAL"),
600
- ("CONSENSUS", "REAL"),
601
- ("INCENTIVE", "REAL"),
602
- ("DIVIDENDS", "REAL"),
603
- ("EMISSION", "INTEGER"),
604
- ("VTRUST", "REAL"),
605
- ("VAL", "INTEGER"),
606
- ("UPDATED", "INTEGER"),
607
- ("ACTIVE", "INTEGER"),
608
- ("AXON", "TEXT"),
609
- ("HOTKEY", "TEXT"),
610
- ("COLDKEY", "TEXT"),
611
- ],
612
- rows=db_table,
613
- )
614
- else:
615
- try:
616
- metadata_info = get_metadata_table("metagraph")
617
- table_data = json.loads(metadata_info["table_data"])
618
- except sqlite3.OperationalError:
619
- err_console.print(
620
- "[red]Error[/red] Unable to retrieve table data. This is usually caused by attempting to use "
621
- "`--reuse-last` before running the command a first time. In rare cases, this could also be due to "
622
- "a corrupted database. Re-run the command (do not use `--reuse-last`) and see if that resolves your "
623
- "issue."
624
- )
625
- return
626
-
627
- if html_output:
628
- try:
629
- render_table(
630
- table_name="metagraph",
631
- table_info=f"Metagraph | "
632
- f"net: {metadata_info['net']}, "
633
- f"block: {metadata_info['block']}, "
634
- f"N: {metadata_info['N']}, "
635
- f"stake: {metadata_info['stake']}, "
636
- f"issuance: {metadata_info['issuance']}, "
637
- f"difficulty: {metadata_info['difficulty']}",
638
- columns=[
639
- {"title": "UID", "field": "UID"},
640
- {
641
- "title": "Stake",
642
- "field": "STAKE",
643
- "formatter": "money",
644
- "formatterParams": {"symbol": "τ", "precision": 5},
645
- },
646
- {
647
- "title": "Rank",
648
- "field": "RANK",
649
- "formatter": "money",
650
- "formatterParams": {"precision": 5},
651
- },
652
- {
653
- "title": "Trust",
654
- "field": "TRUST",
655
- "formatter": "money",
656
- "formatterParams": {"precision": 5},
657
- },
658
- {
659
- "title": "Consensus",
660
- "field": "CONSENSUS",
661
- "formatter": "money",
662
- "formatterParams": {"precision": 5},
663
- },
664
- {
665
- "title": "Incentive",
666
- "field": "INCENTIVE",
667
- "formatter": "money",
668
- "formatterParams": {"precision": 5},
669
- },
670
- {
671
- "title": "Dividends",
672
- "field": "DIVIDENDS",
673
- "formatter": "money",
674
- "formatterParams": {"precision": 5},
675
- },
676
- {"title": "Emission", "field": "EMISSION"},
677
- {
678
- "title": "VTrust",
679
- "field": "VTRUST",
680
- "formatter": "money",
681
- "formatterParams": {"precision": 5},
682
- },
683
- {"title": "Validated", "field": "VAL"},
684
- {"title": "Updated", "field": "UPDATED"},
685
- {"title": "Active", "field": "ACTIVE"},
686
- {"title": "Axon", "field": "AXON"},
687
- {"title": "Hotkey", "field": "HOTKEY"},
688
- {"title": "Coldkey", "field": "COLDKEY"},
689
- ],
690
- )
691
- except sqlite3.OperationalError:
692
- err_console.print(
693
- "[red]Error[/red] Unable to retrieve table data. This may indicate that your database is corrupted, "
694
- "or was not able to load with the most recent data."
695
- )
696
- return
697
- else:
698
- cols: dict[str, tuple[int, Column]] = {
699
- "UID": (
700
- 0,
701
- Column(
702
- "[bold white]UID",
703
- footer=f"[white]{metadata_info['total_neurons']}[/white]",
704
- style="white",
705
- justify="right",
706
- ratio=0.75,
707
- ),
708
- ),
709
- "STAKE": (
710
- 1,
711
- Column(
712
- "[bold white]STAKE(\u03c4)",
713
- footer=metadata_info["total_stake"],
714
- style="bright_cyan",
715
- justify="right",
716
- no_wrap=True,
717
- ratio=1.5,
718
- ),
719
- ),
720
- "RANK": (
721
- 2,
722
- Column(
723
- "[bold white]RANK",
724
- footer=metadata_info["rank"],
725
- style="medium_purple",
726
- justify="right",
727
- no_wrap=True,
728
- ratio=1,
729
- ),
730
- ),
731
- "TRUST": (
732
- 3,
733
- Column(
734
- "[bold white]TRUST",
735
- footer=metadata_info["trust"],
736
- style="dark_sea_green",
737
- justify="right",
738
- no_wrap=True,
739
- ratio=1,
740
- ),
741
- ),
742
- "CONSENSUS": (
743
- 4,
744
- Column(
745
- "[bold white]CONSENSUS",
746
- footer=metadata_info["consensus"],
747
- style="rgb(42,161,152)",
748
- justify="right",
749
- no_wrap=True,
750
- ratio=1,
751
- ),
752
- ),
753
- "INCENTIVE": (
754
- 5,
755
- Column(
756
- "[bold white]INCENTIVE",
757
- footer=metadata_info["incentive"],
758
- style="#5fd7ff",
759
- justify="right",
760
- no_wrap=True,
761
- ratio=1,
762
- ),
763
- ),
764
- "DIVIDENDS": (
765
- 6,
766
- Column(
767
- "[bold white]DIVIDENDS",
768
- footer=metadata_info["dividends"],
769
- style="#8787d7",
770
- justify="right",
771
- no_wrap=True,
772
- ratio=1,
773
- ),
774
- ),
775
- "EMISSION": (
776
- 7,
777
- Column(
778
- "[bold white]EMISSION(\u03c1)",
779
- footer=metadata_info["emission"],
780
- style="#d7d7ff",
781
- justify="right",
782
- no_wrap=True,
783
- ratio=1.5,
784
- ),
785
- ),
786
- "VTRUST": (
787
- 8,
788
- Column(
789
- "[bold white]VTRUST",
790
- footer=metadata_info["validator_trust"],
791
- style="magenta",
792
- justify="right",
793
- no_wrap=True,
794
- ratio=1,
795
- ),
796
- ),
797
- "VAL": (
798
- 9,
799
- Column(
800
- "[bold white]VAL",
801
- justify="center",
802
- style="bright_white",
803
- no_wrap=True,
804
- ratio=0.4,
805
- ),
806
- ),
807
- "UPDATED": (
808
- 10,
809
- Column("[bold white]UPDATED", justify="right", no_wrap=True, ratio=1),
810
- ),
811
- "ACTIVE": (
812
- 11,
813
- Column(
814
- "[bold white]ACTIVE",
815
- justify="center",
816
- style="#8787ff",
817
- no_wrap=True,
818
- ratio=1,
819
- ),
820
- ),
821
- "AXON": (
822
- 12,
823
- Column(
824
- "[bold white]AXON",
825
- justify="left",
826
- style="dark_orange",
827
- overflow="fold",
828
- ratio=2,
829
- ),
830
- ),
831
- "HOTKEY": (
832
- 13,
833
- Column(
834
- "[bold white]HOTKEY",
835
- justify="center",
836
- style="bright_magenta",
837
- overflow="fold",
838
- ratio=1.5,
839
- ),
840
- ),
841
- "COLDKEY": (
842
- 14,
843
- Column(
844
- "[bold white]COLDKEY",
845
- justify="center",
846
- style="bright_magenta",
847
- overflow="fold",
848
- ratio=1.5,
849
- ),
850
- ),
851
- }
852
- table_cols: list[Column] = []
853
- table_cols_indices: list[int] = []
854
- for k, (idx, v) in cols.items():
855
- if display_cols[k] is True:
856
- table_cols_indices.append(idx)
857
- table_cols.append(v)
858
-
859
- table = Table(
860
- *table_cols,
861
- show_footer=True,
862
- show_edge=False,
863
- header_style="bold white",
864
- border_style="bright_black",
865
- style="bold",
866
- title_style="bold white",
867
- title_justify="center",
868
- show_lines=False,
869
- expand=True,
870
- title=(
871
- f"[underline dark_orange]Metagraph[/underline dark_orange]\n\n"
872
- f"Net: [bright_cyan]{metadata_info['net']}[/bright_cyan], "
873
- f"Block: [bright_cyan]{metadata_info['block']}[/bright_cyan], "
874
- f"N: [bright_green]{metadata_info['N0']}[/bright_green]/[bright_red]{metadata_info['N1']}[/bright_red], "
875
- f"Stake: [dark_orange]{metadata_info['stake']}[/dark_orange], "
876
- f"Issuance: [bright_blue]{metadata_info['issuance']}[/bright_blue], "
877
- f"Difficulty: [bright_cyan]{metadata_info['difficulty']}[/bright_cyan]\n"
878
- ),
879
- pad_edge=True,
880
- )
881
-
882
- if all(x is False for x in display_cols.values()):
883
- console.print("You have selected no columns to display in your config.")
884
- table.add_row(" " * 256) # allows title to be printed
885
- elif any(x is False for x in display_cols.values()):
886
- console.print(
887
- "Limiting column display output based on your config settings. Hiding columns "
888
- f"{', '.join([k for (k, v) in display_cols.items() if v is False])}"
889
- )
890
- for row in table_data:
891
- new_row = [row[idx] for idx in table_cols_indices]
892
- table.add_row(*new_row)
893
- else:
894
- for row in table_data:
895
- table.add_row(*row)
896
-
897
- console.print(table)