meshtensor-cli 9.18.1__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 (74) hide show
  1. meshtensor_cli/__init__.py +22 -0
  2. meshtensor_cli/cli.py +10742 -0
  3. meshtensor_cli/doc_generation_helper.py +4 -0
  4. meshtensor_cli/src/__init__.py +1085 -0
  5. meshtensor_cli/src/commands/__init__.py +0 -0
  6. meshtensor_cli/src/commands/axon/__init__.py +0 -0
  7. meshtensor_cli/src/commands/axon/axon.py +132 -0
  8. meshtensor_cli/src/commands/crowd/__init__.py +0 -0
  9. meshtensor_cli/src/commands/crowd/contribute.py +621 -0
  10. meshtensor_cli/src/commands/crowd/contributors.py +200 -0
  11. meshtensor_cli/src/commands/crowd/create.py +783 -0
  12. meshtensor_cli/src/commands/crowd/dissolve.py +219 -0
  13. meshtensor_cli/src/commands/crowd/refund.py +233 -0
  14. meshtensor_cli/src/commands/crowd/update.py +418 -0
  15. meshtensor_cli/src/commands/crowd/utils.py +124 -0
  16. meshtensor_cli/src/commands/crowd/view.py +991 -0
  17. meshtensor_cli/src/commands/governance/__init__.py +0 -0
  18. meshtensor_cli/src/commands/governance/governance.py +794 -0
  19. meshtensor_cli/src/commands/liquidity/__init__.py +0 -0
  20. meshtensor_cli/src/commands/liquidity/liquidity.py +699 -0
  21. meshtensor_cli/src/commands/liquidity/utils.py +202 -0
  22. meshtensor_cli/src/commands/proxy.py +700 -0
  23. meshtensor_cli/src/commands/stake/__init__.py +0 -0
  24. meshtensor_cli/src/commands/stake/add.py +799 -0
  25. meshtensor_cli/src/commands/stake/auto_staking.py +306 -0
  26. meshtensor_cli/src/commands/stake/children_hotkeys.py +865 -0
  27. meshtensor_cli/src/commands/stake/claim.py +770 -0
  28. meshtensor_cli/src/commands/stake/list.py +738 -0
  29. meshtensor_cli/src/commands/stake/move.py +1211 -0
  30. meshtensor_cli/src/commands/stake/remove.py +1466 -0
  31. meshtensor_cli/src/commands/stake/wizard.py +323 -0
  32. meshtensor_cli/src/commands/subnets/__init__.py +0 -0
  33. meshtensor_cli/src/commands/subnets/mechanisms.py +515 -0
  34. meshtensor_cli/src/commands/subnets/price.py +733 -0
  35. meshtensor_cli/src/commands/subnets/subnets.py +2908 -0
  36. meshtensor_cli/src/commands/sudo.py +1294 -0
  37. meshtensor_cli/src/commands/tc/__init__.py +0 -0
  38. meshtensor_cli/src/commands/tc/tc.py +190 -0
  39. meshtensor_cli/src/commands/treasury/__init__.py +0 -0
  40. meshtensor_cli/src/commands/treasury/treasury.py +194 -0
  41. meshtensor_cli/src/commands/view.py +354 -0
  42. meshtensor_cli/src/commands/wallets.py +2311 -0
  43. meshtensor_cli/src/commands/weights.py +467 -0
  44. meshtensor_cli/src/meshtensor/__init__.py +0 -0
  45. meshtensor_cli/src/meshtensor/balances.py +313 -0
  46. meshtensor_cli/src/meshtensor/chain_data.py +1263 -0
  47. meshtensor_cli/src/meshtensor/extrinsics/__init__.py +0 -0
  48. meshtensor_cli/src/meshtensor/extrinsics/mev_shield.py +174 -0
  49. meshtensor_cli/src/meshtensor/extrinsics/registration.py +1861 -0
  50. meshtensor_cli/src/meshtensor/extrinsics/root.py +550 -0
  51. meshtensor_cli/src/meshtensor/extrinsics/serving.py +255 -0
  52. meshtensor_cli/src/meshtensor/extrinsics/transfer.py +239 -0
  53. meshtensor_cli/src/meshtensor/meshtensor_interface.py +2598 -0
  54. meshtensor_cli/src/meshtensor/minigraph.py +254 -0
  55. meshtensor_cli/src/meshtensor/networking.py +12 -0
  56. meshtensor_cli/src/meshtensor/templates/main-filters.j2 +24 -0
  57. meshtensor_cli/src/meshtensor/templates/main-header.j2 +36 -0
  58. meshtensor_cli/src/meshtensor/templates/neuron-details.j2 +111 -0
  59. meshtensor_cli/src/meshtensor/templates/price-multi.j2 +113 -0
  60. meshtensor_cli/src/meshtensor/templates/price-single.j2 +99 -0
  61. meshtensor_cli/src/meshtensor/templates/subnet-details-header.j2 +49 -0
  62. meshtensor_cli/src/meshtensor/templates/subnet-details.j2 +32 -0
  63. meshtensor_cli/src/meshtensor/templates/subnet-metrics.j2 +57 -0
  64. meshtensor_cli/src/meshtensor/templates/subnets-table.j2 +28 -0
  65. meshtensor_cli/src/meshtensor/templates/table.j2 +267 -0
  66. meshtensor_cli/src/meshtensor/templates/view.css +1058 -0
  67. meshtensor_cli/src/meshtensor/templates/view.j2 +43 -0
  68. meshtensor_cli/src/meshtensor/templates/view.js +1053 -0
  69. meshtensor_cli/src/meshtensor/utils.py +2007 -0
  70. meshtensor_cli/version.py +23 -0
  71. meshtensor_cli-9.18.1.dist-info/METADATA +261 -0
  72. meshtensor_cli-9.18.1.dist-info/RECORD +74 -0
  73. meshtensor_cli-9.18.1.dist-info/WHEEL +4 -0
  74. meshtensor_cli-9.18.1.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,306 @@
1
+ import asyncio
2
+ import json
3
+ from typing import Optional, TYPE_CHECKING
4
+
5
+ from meshtensor_wallet import Wallet
6
+ from rich import box
7
+ from rich.table import Table
8
+
9
+ from meshtensor_cli.src import COLOR_PALETTE
10
+ from meshtensor_cli.src.meshtensor.utils import (
11
+ confirm_action,
12
+ console,
13
+ json_console,
14
+ print_success,
15
+ get_subnet_name,
16
+ is_valid_ss58_address,
17
+ print_error,
18
+ unlock_key,
19
+ print_extrinsic_id,
20
+ )
21
+
22
+ if TYPE_CHECKING:
23
+ from meshtensor_cli.src.meshtensor.meshtensor_interface import MeshtensorInterface
24
+
25
+
26
+ async def show_auto_stake_destinations(
27
+ wallet: Optional[Wallet],
28
+ meshtensor: "MeshtensorInterface",
29
+ coldkey_ss58: Optional[str] = None,
30
+ json_output: bool = False,
31
+ ) -> Optional[dict[int, dict[str, Optional[str]]]]:
32
+ """Display auto-stake destinations for the supplied wallet."""
33
+
34
+ wallet_name: Optional[str] = wallet.name if wallet else None
35
+ coldkey_ss58 = coldkey_ss58 or (wallet.coldkeypub.ss58_address if wallet else None)
36
+ if not coldkey_ss58:
37
+ raise ValueError("A wallet or coldkey SS58 address must be provided")
38
+
39
+ with console.status(
40
+ f"Retrieving auto-stake configuration from {meshtensor.network}...",
41
+ spinner="earth",
42
+ ):
43
+ chain_head = await meshtensor.substrate.get_chain_head()
44
+ (
45
+ subnet_info,
46
+ auto_destinations,
47
+ identities,
48
+ delegate_identities,
49
+ ) = await asyncio.gather(
50
+ meshtensor.all_subnets(block_hash=chain_head),
51
+ meshtensor.get_auto_stake_destinations(
52
+ coldkey_ss58=coldkey_ss58,
53
+ block_hash=chain_head,
54
+ reuse_block=True,
55
+ ),
56
+ meshtensor.fetch_coldkey_hotkey_identities(block_hash=chain_head),
57
+ meshtensor.get_delegate_identities(block_hash=chain_head),
58
+ )
59
+
60
+ subnet_map = {info.netuid: info for info in subnet_info}
61
+ auto_destinations = auto_destinations or {}
62
+ identities = identities or {}
63
+ delegate_identities = delegate_identities or {}
64
+ hotkey_identities = identities.get("hotkeys", {})
65
+
66
+ def resolve_identity(hotkey: str) -> Optional[str]:
67
+ if not hotkey:
68
+ return None
69
+
70
+ identity_entry = hotkey_identities.get(hotkey, {}).get("identity")
71
+ if identity_entry:
72
+ display_name = identity_entry.get("name") or identity_entry.get("display")
73
+ if display_name:
74
+ return display_name
75
+
76
+ delegate_info = delegate_identities.get(hotkey)
77
+ if delegate_info and getattr(delegate_info, "display", ""):
78
+ return delegate_info.display
79
+
80
+ return None
81
+
82
+ coldkey_display = wallet_name
83
+ if not coldkey_display:
84
+ coldkey_identity = identities.get("coldkeys", {}).get(coldkey_ss58, {})
85
+ if identity_data := coldkey_identity.get("identity"):
86
+ coldkey_display = identity_data.get("name") or identity_data.get("display")
87
+ if not coldkey_display:
88
+ coldkey_display = f"{coldkey_ss58[:6]}...{coldkey_ss58[-6:]}"
89
+
90
+ rows = []
91
+ data_output: dict[int, dict[str, Optional[str]]] = {}
92
+
93
+ for netuid in sorted(subnet_map):
94
+ subnet = subnet_map[netuid]
95
+ subnet_name = get_subnet_name(subnet)
96
+ hotkey_ss58 = auto_destinations.get(netuid)
97
+ identity_str = resolve_identity(hotkey_ss58) if hotkey_ss58 else None
98
+ is_custom = hotkey_ss58 is not None
99
+
100
+ data_output[netuid] = {
101
+ "subnet_name": subnet_name,
102
+ "status": "custom" if is_custom else "default",
103
+ "destination": hotkey_ss58,
104
+ "identity": identity_str,
105
+ }
106
+
107
+ if json_output:
108
+ continue
109
+
110
+ status_text = (
111
+ f"[{COLOR_PALETTE['STAKE']['STAKE_ALPHA']}]Custom[/{COLOR_PALETTE['STAKE']['STAKE_ALPHA']}]"
112
+ if is_custom
113
+ else f"[{COLOR_PALETTE['GENERAL']['HINT']}]Default[/{COLOR_PALETTE['GENERAL']['HINT']}]"
114
+ )
115
+
116
+ rows.append(
117
+ (
118
+ str(netuid),
119
+ subnet_name,
120
+ status_text,
121
+ hotkey_ss58,
122
+ identity_str or "",
123
+ )
124
+ )
125
+
126
+ if json_output:
127
+ json_console.print(json.dumps(data_output))
128
+ return data_output
129
+
130
+ table = Table(
131
+ title=(
132
+ f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]Auto Stake Destinations"
133
+ f" for [bold]{coldkey_display}[/bold]\n"
134
+ f"Network: {meshtensor.network}\n"
135
+ f"Coldkey: {coldkey_ss58}\n"
136
+ f"[/{COLOR_PALETTE['GENERAL']['HEADER']}]"
137
+ ),
138
+ show_edge=False,
139
+ header_style="bold white",
140
+ border_style="bright_black",
141
+ style="bold",
142
+ title_justify="center",
143
+ show_lines=False,
144
+ pad_edge=True,
145
+ box=box.SIMPLE_HEAD,
146
+ )
147
+
148
+ table.add_column(
149
+ "Netuid", style=COLOR_PALETTE["GENERAL"]["SYMBOL"], justify="center"
150
+ )
151
+ table.add_column("Subnet", style="cyan", justify="left")
152
+ table.add_column("Status", style="white", justify="center")
153
+ table.add_column(
154
+ "Destination Hotkey", style=COLOR_PALETTE["GENERAL"]["HOTKEY"], justify="center"
155
+ )
156
+ table.add_column(
157
+ "Identity", style=COLOR_PALETTE["GENERAL"]["SUBHEADING"], justify="left"
158
+ )
159
+
160
+ for row in rows:
161
+ table.add_row(*row)
162
+
163
+ console.print(table)
164
+ console.print(
165
+ f"\n[{COLOR_PALETTE['GENERAL']['SUBHEADING']}]Total subnets:[/] {len(subnet_map)} "
166
+ f"[{COLOR_PALETTE['GENERAL']['SUBHEADING']}]Custom destinations:[/] {len(auto_destinations)}"
167
+ )
168
+
169
+ return None
170
+
171
+
172
+ async def set_auto_stake_destination(
173
+ wallet: Wallet,
174
+ meshtensor: "MeshtensorInterface",
175
+ netuid: int,
176
+ hotkey_ss58: str,
177
+ proxy: Optional[str] = None,
178
+ wait_for_inclusion: bool = True,
179
+ wait_for_finalization: bool = False,
180
+ prompt_user: bool = True,
181
+ decline: bool = False,
182
+ quiet: bool = False,
183
+ json_output: bool = False,
184
+ ) -> bool:
185
+ """Set the auto-stake destination hotkey for a coldkey on a subnet."""
186
+
187
+ if not is_valid_ss58_address(hotkey_ss58):
188
+ print_error("You entered an invalid hotkey ss58 address")
189
+ return False
190
+
191
+ try:
192
+ chain_head = await meshtensor.substrate.get_chain_head()
193
+ subnet_info, identities, delegate_identities = await asyncio.gather(
194
+ meshtensor.subnet(netuid, block_hash=chain_head),
195
+ meshtensor.fetch_coldkey_hotkey_identities(block_hash=chain_head),
196
+ meshtensor.get_delegate_identities(block_hash=chain_head),
197
+ )
198
+ except ValueError:
199
+ print_error(f"Subnet with netuid {netuid} does not exist")
200
+ return False
201
+
202
+ hotkey_identity = ""
203
+ identities = identities or {}
204
+ delegate_identities = delegate_identities or {}
205
+
206
+ hotkey_identity_entry = identities.get("hotkeys", {}).get(hotkey_ss58, {})
207
+ if identity_data := hotkey_identity_entry.get("identity"):
208
+ hotkey_identity = (
209
+ identity_data.get("name") or identity_data.get("display") or ""
210
+ )
211
+ if not hotkey_identity:
212
+ delegate_info = delegate_identities.get(hotkey_ss58)
213
+ if delegate_info and getattr(delegate_info, "display", ""):
214
+ hotkey_identity = delegate_info.display
215
+
216
+ if prompt_user and not json_output:
217
+ table = Table(
218
+ title=(
219
+ f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]Confirm Auto-Stake Destination"
220
+ f"[/{COLOR_PALETTE['GENERAL']['HEADER']}]"
221
+ ),
222
+ show_edge=False,
223
+ header_style="bold white",
224
+ border_style="bright_black",
225
+ style="bold",
226
+ title_justify="center",
227
+ show_lines=False,
228
+ pad_edge=True,
229
+ box=box.SIMPLE_HEAD,
230
+ )
231
+ table.add_column(
232
+ "Netuid", justify="center", style=COLOR_PALETTE["GENERAL"]["SYMBOL"]
233
+ )
234
+ table.add_column("Subnet", style="cyan", justify="left")
235
+ table.add_column(
236
+ "Destination Hotkey",
237
+ style=COLOR_PALETTE["GENERAL"]["HOTKEY"],
238
+ justify="center",
239
+ )
240
+ table.add_column(
241
+ "Identity", style=COLOR_PALETTE["GENERAL"]["SUBHEADING"], justify="left"
242
+ )
243
+ table.add_row(
244
+ str(netuid),
245
+ get_subnet_name(subnet_info),
246
+ hotkey_ss58,
247
+ hotkey_identity or "",
248
+ )
249
+ console.print(table)
250
+
251
+ if not confirm_action(
252
+ "\nSet this auto-stake destination?",
253
+ default=True,
254
+ decline=decline,
255
+ quiet=quiet,
256
+ ):
257
+ return False
258
+
259
+ if not unlock_key(wallet).success:
260
+ return False
261
+
262
+ call = await meshtensor.substrate.compose_call(
263
+ call_module="MeshtensorModule",
264
+ call_function="set_coldkey_auto_stake_hotkey",
265
+ call_params={
266
+ "netuid": netuid,
267
+ "hotkey": hotkey_ss58,
268
+ },
269
+ )
270
+
271
+ with console.status(
272
+ f":satellite: Setting auto-stake destination on [white]{meshtensor.network}[/white]...",
273
+ spinner="earth",
274
+ ):
275
+ success, error_message, ext_receipt = await meshtensor.sign_and_send_extrinsic(
276
+ call,
277
+ wallet,
278
+ wait_for_inclusion=wait_for_inclusion,
279
+ wait_for_finalization=wait_for_finalization,
280
+ proxy=proxy,
281
+ )
282
+
283
+ ext_id = await ext_receipt.get_extrinsic_identifier() if success else None
284
+
285
+ if json_output:
286
+ json_console.print(
287
+ json.dumps(
288
+ {
289
+ "success": success,
290
+ "error": error_message,
291
+ "netuid": netuid,
292
+ "hotkey": hotkey_ss58,
293
+ "extrinsic_identifier": ext_id,
294
+ }
295
+ )
296
+ )
297
+
298
+ if success:
299
+ await print_extrinsic_id(ext_receipt)
300
+ print_success(
301
+ f"[dark_sea_green3]Auto-stake destination set for netuid {netuid}[/dark_sea_green3]"
302
+ )
303
+ return True
304
+
305
+ print_error(f"Failed: {error_message}")
306
+ return False