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.
- meshtensor_cli/__init__.py +22 -0
- meshtensor_cli/cli.py +10742 -0
- meshtensor_cli/doc_generation_helper.py +4 -0
- meshtensor_cli/src/__init__.py +1085 -0
- meshtensor_cli/src/commands/__init__.py +0 -0
- meshtensor_cli/src/commands/axon/__init__.py +0 -0
- meshtensor_cli/src/commands/axon/axon.py +132 -0
- meshtensor_cli/src/commands/crowd/__init__.py +0 -0
- meshtensor_cli/src/commands/crowd/contribute.py +621 -0
- meshtensor_cli/src/commands/crowd/contributors.py +200 -0
- meshtensor_cli/src/commands/crowd/create.py +783 -0
- meshtensor_cli/src/commands/crowd/dissolve.py +219 -0
- meshtensor_cli/src/commands/crowd/refund.py +233 -0
- meshtensor_cli/src/commands/crowd/update.py +418 -0
- meshtensor_cli/src/commands/crowd/utils.py +124 -0
- meshtensor_cli/src/commands/crowd/view.py +991 -0
- meshtensor_cli/src/commands/governance/__init__.py +0 -0
- meshtensor_cli/src/commands/governance/governance.py +794 -0
- meshtensor_cli/src/commands/liquidity/__init__.py +0 -0
- meshtensor_cli/src/commands/liquidity/liquidity.py +699 -0
- meshtensor_cli/src/commands/liquidity/utils.py +202 -0
- meshtensor_cli/src/commands/proxy.py +700 -0
- meshtensor_cli/src/commands/stake/__init__.py +0 -0
- meshtensor_cli/src/commands/stake/add.py +799 -0
- meshtensor_cli/src/commands/stake/auto_staking.py +306 -0
- meshtensor_cli/src/commands/stake/children_hotkeys.py +865 -0
- meshtensor_cli/src/commands/stake/claim.py +770 -0
- meshtensor_cli/src/commands/stake/list.py +738 -0
- meshtensor_cli/src/commands/stake/move.py +1211 -0
- meshtensor_cli/src/commands/stake/remove.py +1466 -0
- meshtensor_cli/src/commands/stake/wizard.py +323 -0
- meshtensor_cli/src/commands/subnets/__init__.py +0 -0
- meshtensor_cli/src/commands/subnets/mechanisms.py +515 -0
- meshtensor_cli/src/commands/subnets/price.py +733 -0
- meshtensor_cli/src/commands/subnets/subnets.py +2908 -0
- meshtensor_cli/src/commands/sudo.py +1294 -0
- meshtensor_cli/src/commands/tc/__init__.py +0 -0
- meshtensor_cli/src/commands/tc/tc.py +190 -0
- meshtensor_cli/src/commands/treasury/__init__.py +0 -0
- meshtensor_cli/src/commands/treasury/treasury.py +194 -0
- meshtensor_cli/src/commands/view.py +354 -0
- meshtensor_cli/src/commands/wallets.py +2311 -0
- meshtensor_cli/src/commands/weights.py +467 -0
- meshtensor_cli/src/meshtensor/__init__.py +0 -0
- meshtensor_cli/src/meshtensor/balances.py +313 -0
- meshtensor_cli/src/meshtensor/chain_data.py +1263 -0
- meshtensor_cli/src/meshtensor/extrinsics/__init__.py +0 -0
- meshtensor_cli/src/meshtensor/extrinsics/mev_shield.py +174 -0
- meshtensor_cli/src/meshtensor/extrinsics/registration.py +1861 -0
- meshtensor_cli/src/meshtensor/extrinsics/root.py +550 -0
- meshtensor_cli/src/meshtensor/extrinsics/serving.py +255 -0
- meshtensor_cli/src/meshtensor/extrinsics/transfer.py +239 -0
- meshtensor_cli/src/meshtensor/meshtensor_interface.py +2598 -0
- meshtensor_cli/src/meshtensor/minigraph.py +254 -0
- meshtensor_cli/src/meshtensor/networking.py +12 -0
- meshtensor_cli/src/meshtensor/templates/main-filters.j2 +24 -0
- meshtensor_cli/src/meshtensor/templates/main-header.j2 +36 -0
- meshtensor_cli/src/meshtensor/templates/neuron-details.j2 +111 -0
- meshtensor_cli/src/meshtensor/templates/price-multi.j2 +113 -0
- meshtensor_cli/src/meshtensor/templates/price-single.j2 +99 -0
- meshtensor_cli/src/meshtensor/templates/subnet-details-header.j2 +49 -0
- meshtensor_cli/src/meshtensor/templates/subnet-details.j2 +32 -0
- meshtensor_cli/src/meshtensor/templates/subnet-metrics.j2 +57 -0
- meshtensor_cli/src/meshtensor/templates/subnets-table.j2 +28 -0
- meshtensor_cli/src/meshtensor/templates/table.j2 +267 -0
- meshtensor_cli/src/meshtensor/templates/view.css +1058 -0
- meshtensor_cli/src/meshtensor/templates/view.j2 +43 -0
- meshtensor_cli/src/meshtensor/templates/view.js +1053 -0
- meshtensor_cli/src/meshtensor/utils.py +2007 -0
- meshtensor_cli/version.py +23 -0
- meshtensor_cli-9.18.1.dist-info/METADATA +261 -0
- meshtensor_cli-9.18.1.dist-info/RECORD +74 -0
- meshtensor_cli-9.18.1.dist-info/WHEEL +4 -0
- meshtensor_cli-9.18.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Wizard command for guiding users through stake movement operations.
|
|
3
|
+
|
|
4
|
+
This module provides an interactive wizard that helps users understand and select
|
|
5
|
+
the appropriate stake movement command (move, transfer, or swap) based on their needs.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
from typing import TYPE_CHECKING, Optional
|
|
10
|
+
|
|
11
|
+
from meshtensor_wallet import Wallet
|
|
12
|
+
from rich.prompt import Prompt
|
|
13
|
+
from rich.table import Table
|
|
14
|
+
from rich.panel import Panel
|
|
15
|
+
|
|
16
|
+
from meshtensor_cli.src import COLOR_PALETTE
|
|
17
|
+
from meshtensor_cli.src.meshtensor.utils import (
|
|
18
|
+
console,
|
|
19
|
+
print_error,
|
|
20
|
+
is_valid_ss58_address,
|
|
21
|
+
get_hotkey_pub_ss58,
|
|
22
|
+
group_subnets,
|
|
23
|
+
get_hotkey_wallets_for_wallet,
|
|
24
|
+
)
|
|
25
|
+
from meshtensor_cli.src.commands.stake.move import (
|
|
26
|
+
stake_move_transfer_selection,
|
|
27
|
+
stake_swap_selection,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from meshtensor_cli.src.meshtensor.meshtensor_interface import MeshtensorInterface
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def stake_movement_wizard(
|
|
35
|
+
meshtensor: "MeshtensorInterface",
|
|
36
|
+
wallet: Wallet,
|
|
37
|
+
) -> Optional[dict]:
|
|
38
|
+
"""
|
|
39
|
+
Interactive wizard that guides users through stake movement operations.
|
|
40
|
+
|
|
41
|
+
This wizard helps users understand the differences between:
|
|
42
|
+
- move: Move stake between hotkeys (same coldkey)
|
|
43
|
+
- transfer: Transfer stake between coldkeys (same hotkey)
|
|
44
|
+
- swap: Swap stake between subnets (same coldkey-hotkey pair)
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
meshtensor: MeshtensorInterface object
|
|
48
|
+
wallet: Wallet object
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
dict: Contains the operation type and parameters needed to execute the operation
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
# Display welcome message and explanation
|
|
55
|
+
console.print("\n")
|
|
56
|
+
console.print(
|
|
57
|
+
Panel(
|
|
58
|
+
"[bold cyan]Stake Movement Wizard[/bold cyan]\n\n"
|
|
59
|
+
"This wizard will help you choose the right stake movement operation.\n"
|
|
60
|
+
"There are three types of stake movements:\n\n"
|
|
61
|
+
"[bold]1. Move[/bold] - Move stake between [blue]hotkeys[/blue] while keeping the same [blue]coldkey[/blue]\n"
|
|
62
|
+
" Example: Moving stake from hotkey A to hotkey B (both owned by your coldkey)\n\n"
|
|
63
|
+
"[bold]2. Transfer[/bold] - Transfer stake between [blue]coldkeys[/blue] while keeping the same [blue]hotkey[/blue]\n"
|
|
64
|
+
" Example: Transferring stake ownership from your coldkey to another coldkey (same hotkey)\n\n"
|
|
65
|
+
"[bold]3. Swap[/bold] - Swap stake between [blue]subnets[/blue] while keeping the same [blue]coldkey-hotkey pair[/blue]\n"
|
|
66
|
+
" Example: Moving stake from subnet 1 to subnet 2 (same wallet and hotkey)\n",
|
|
67
|
+
title="Welcome",
|
|
68
|
+
border_style="cyan",
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Ask user what they want to do
|
|
73
|
+
operation_choice = Prompt.ask(
|
|
74
|
+
"\n[bold]What would you like to do?[/bold]",
|
|
75
|
+
choices=["1", "2", "3", "move", "transfer", "swap", "q"],
|
|
76
|
+
default="q",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
if operation_choice.lower() == "q":
|
|
80
|
+
console.print("[yellow]Wizard cancelled.[/yellow]")
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
# Normalize choice
|
|
84
|
+
if operation_choice in ["1", "move"]:
|
|
85
|
+
operation = "move"
|
|
86
|
+
operation_name = "Move"
|
|
87
|
+
description = "Move stake between hotkeys (same coldkey)"
|
|
88
|
+
elif operation_choice in ["2", "transfer"]:
|
|
89
|
+
operation = "transfer"
|
|
90
|
+
operation_name = "Transfer"
|
|
91
|
+
description = "Transfer stake between coldkeys (same hotkey)"
|
|
92
|
+
elif operation_choice in ["3", "swap"]:
|
|
93
|
+
operation = "swap"
|
|
94
|
+
operation_name = "Swap"
|
|
95
|
+
description = "Swap stake between subnets (same coldkey-hotkey pair)"
|
|
96
|
+
else:
|
|
97
|
+
print_error("Invalid choice")
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
console.print(f"\n[bold green]Selected: {operation_name}[/bold green]")
|
|
101
|
+
console.print(f"[dim]{description}[/dim]\n")
|
|
102
|
+
|
|
103
|
+
# Get stakes for the wallet
|
|
104
|
+
with console.status("Retrieving stake information..."):
|
|
105
|
+
stakes, ck_hk_identities, old_identities = await asyncio.gather(
|
|
106
|
+
meshtensor.get_stake_for_coldkey(
|
|
107
|
+
coldkey_ss58=wallet.coldkeypub.ss58_address
|
|
108
|
+
),
|
|
109
|
+
meshtensor.fetch_coldkey_hotkey_identities(),
|
|
110
|
+
meshtensor.get_delegate_identities(),
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Filter stakes with actual amounts
|
|
114
|
+
available_stakes = [s for s in stakes if s.stake.tao > 0]
|
|
115
|
+
|
|
116
|
+
if not available_stakes:
|
|
117
|
+
print_error("You have no stakes available to move.")
|
|
118
|
+
return None
|
|
119
|
+
|
|
120
|
+
# Display available stakes
|
|
121
|
+
_display_available_stakes(available_stakes, ck_hk_identities, old_identities)
|
|
122
|
+
|
|
123
|
+
# Guide user through the specific operation
|
|
124
|
+
if operation == "move":
|
|
125
|
+
return await _guide_move_operation(
|
|
126
|
+
meshtensor, wallet, available_stakes, ck_hk_identities, old_identities
|
|
127
|
+
)
|
|
128
|
+
elif operation == "transfer":
|
|
129
|
+
return await _guide_transfer_operation(
|
|
130
|
+
meshtensor, wallet, available_stakes, ck_hk_identities, old_identities
|
|
131
|
+
)
|
|
132
|
+
elif operation == "swap":
|
|
133
|
+
return await _guide_swap_operation(meshtensor, wallet, available_stakes)
|
|
134
|
+
else:
|
|
135
|
+
raise ValueError(f"Unknown operation: {operation}")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _display_available_stakes(
|
|
139
|
+
stakes: list,
|
|
140
|
+
ck_hk_identities: dict,
|
|
141
|
+
old_identities: dict,
|
|
142
|
+
):
|
|
143
|
+
"""Display a table of available stakes."""
|
|
144
|
+
# Group stakes by hotkey
|
|
145
|
+
hotkey_stakes = {}
|
|
146
|
+
for stake in stakes:
|
|
147
|
+
hotkey = stake.hotkey_ss58
|
|
148
|
+
if hotkey not in hotkey_stakes:
|
|
149
|
+
hotkey_stakes[hotkey] = {}
|
|
150
|
+
hotkey_stakes[hotkey][stake.netuid] = stake.stake
|
|
151
|
+
|
|
152
|
+
# Get identities
|
|
153
|
+
def get_identity(hotkey_ss58_: str) -> str:
|
|
154
|
+
if hk_identity := ck_hk_identities["hotkeys"].get(hotkey_ss58_):
|
|
155
|
+
return hk_identity.get("identity", {}).get("name", "") or hk_identity.get(
|
|
156
|
+
"display", "~"
|
|
157
|
+
)
|
|
158
|
+
elif old_identity := old_identities.get(hotkey_ss58_):
|
|
159
|
+
return old_identity.display
|
|
160
|
+
return "~"
|
|
161
|
+
|
|
162
|
+
table = Table(
|
|
163
|
+
title=f"\n[{COLOR_PALETTE['GENERAL']['HEADER']}]Your Available Stakes[/{COLOR_PALETTE['GENERAL']['HEADER']}]\n",
|
|
164
|
+
show_edge=False,
|
|
165
|
+
header_style="bold white",
|
|
166
|
+
border_style="bright_black",
|
|
167
|
+
title_justify="center",
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
table.add_column("Hotkey Identity", style=COLOR_PALETTE["GENERAL"]["SUBHEADING"])
|
|
171
|
+
table.add_column("Hotkey Address", style=COLOR_PALETTE["GENERAL"]["HOTKEY"])
|
|
172
|
+
table.add_column("Netuids", style=COLOR_PALETTE["GENERAL"]["NETUID"])
|
|
173
|
+
table.add_column("Total Stake", style=COLOR_PALETTE["STAKE"]["STAKE_AMOUNT"])
|
|
174
|
+
|
|
175
|
+
for hotkey_ss58, netuid_stakes in hotkey_stakes.items():
|
|
176
|
+
identity = get_identity(hotkey_ss58)
|
|
177
|
+
netuids = sorted(netuid_stakes.keys())
|
|
178
|
+
total_stake = sum(
|
|
179
|
+
netuid_stakes.values(), start=stakes[0].stake.__class__.from_tao(0)
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
table.add_row(
|
|
183
|
+
identity,
|
|
184
|
+
f"{hotkey_ss58[:8]}...{hotkey_ss58[-8:]}",
|
|
185
|
+
group_subnets(netuids),
|
|
186
|
+
str(total_stake),
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
console.print(table)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
async def _guide_move_operation(
|
|
193
|
+
meshtensor: "MeshtensorInterface",
|
|
194
|
+
wallet: Wallet,
|
|
195
|
+
available_stakes: list,
|
|
196
|
+
ck_hk_identities: dict,
|
|
197
|
+
old_identities: dict,
|
|
198
|
+
) -> dict:
|
|
199
|
+
"""Guide user through move operation."""
|
|
200
|
+
console.print(
|
|
201
|
+
"\n[bold cyan]Move Operation[/bold cyan]\n"
|
|
202
|
+
"You will move stake from one hotkey to another hotkey.\n"
|
|
203
|
+
"Both hotkeys must be owned by the same coldkey (your wallet).\n"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
try:
|
|
207
|
+
selection = await stake_move_transfer_selection(meshtensor, wallet)
|
|
208
|
+
|
|
209
|
+
# Get available hotkeys for destination
|
|
210
|
+
all_hotkeys = get_hotkey_wallets_for_wallet(wallet=wallet)
|
|
211
|
+
available_hotkeys = [
|
|
212
|
+
(hk.hotkey_str, get_hotkey_pub_ss58(hk)) for hk in all_hotkeys
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
# Ask for destination hotkey
|
|
216
|
+
console.print("\n[bold]Destination Hotkey[/bold]")
|
|
217
|
+
if available_hotkeys:
|
|
218
|
+
console.print("\nAvailable hotkeys in your wallet:")
|
|
219
|
+
for idx, (name, ss58) in enumerate(available_hotkeys):
|
|
220
|
+
console.print(f" {idx}: {name} ({ss58[:8]}...{ss58[-8:]})")
|
|
221
|
+
|
|
222
|
+
dest_choice = Prompt.ask(
|
|
223
|
+
"\nEnter the [blue]index[/blue] of the destination hotkey, or [blue]SS58 address[/blue]",
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
try:
|
|
227
|
+
dest_idx = int(dest_choice)
|
|
228
|
+
if 0 <= dest_idx < len(available_hotkeys):
|
|
229
|
+
dest_hotkey = available_hotkeys[dest_idx][1]
|
|
230
|
+
else:
|
|
231
|
+
raise ValueError("Invalid index")
|
|
232
|
+
except ValueError:
|
|
233
|
+
# Assume it's an SS58 address
|
|
234
|
+
if is_valid_ss58_address(dest_choice):
|
|
235
|
+
dest_hotkey = dest_choice
|
|
236
|
+
else:
|
|
237
|
+
print_error(
|
|
238
|
+
"Invalid hotkey selection. Please provide a valid index or SS58 address."
|
|
239
|
+
)
|
|
240
|
+
raise ValueError("Invalid destination hotkey")
|
|
241
|
+
else:
|
|
242
|
+
dest_hotkey = Prompt.ask(
|
|
243
|
+
"Enter the [blue]destination hotkey[/blue] SS58 address"
|
|
244
|
+
)
|
|
245
|
+
if not is_valid_ss58_address(dest_hotkey):
|
|
246
|
+
print_error("Invalid SS58 address")
|
|
247
|
+
raise ValueError("Invalid destination hotkey")
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
"operation": "move",
|
|
251
|
+
"origin_hotkey": selection["origin_hotkey"],
|
|
252
|
+
"origin_netuid": selection["origin_netuid"],
|
|
253
|
+
"destination_netuid": selection["destination_netuid"],
|
|
254
|
+
"destination_hotkey": dest_hotkey,
|
|
255
|
+
"amount": selection["amount"],
|
|
256
|
+
"stake_all": selection["stake_all"],
|
|
257
|
+
}
|
|
258
|
+
except ValueError:
|
|
259
|
+
raise
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
async def _guide_transfer_operation(
|
|
263
|
+
meshtensor: "MeshtensorInterface",
|
|
264
|
+
wallet: Wallet,
|
|
265
|
+
available_stakes: list,
|
|
266
|
+
ck_hk_identities: dict,
|
|
267
|
+
old_identities: dict,
|
|
268
|
+
) -> dict:
|
|
269
|
+
"""Guide user through transfer operation."""
|
|
270
|
+
console.print(
|
|
271
|
+
"\n[bold cyan]Transfer Operation[/bold cyan]\n"
|
|
272
|
+
"You will transfer stake ownership from one coldkey to another coldkey.\n"
|
|
273
|
+
"The hotkey remains the same, but ownership changes.\n"
|
|
274
|
+
"[yellow]Warning:[/yellow] Make sure the destination coldkey is not a validator hotkey.\n"
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
try:
|
|
278
|
+
selection = await stake_move_transfer_selection(meshtensor, wallet)
|
|
279
|
+
|
|
280
|
+
# Ask for destination coldkey
|
|
281
|
+
console.print("\n[bold]Destination Coldkey[/bold]")
|
|
282
|
+
dest_coldkey = Prompt.ask(
|
|
283
|
+
"Enter the [blue]destination coldkey[/blue] SS58 address or wallet name"
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# Note: The CLI will handle wallet name resolution if it's not an SS58 address
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
"operation": "transfer",
|
|
290
|
+
"origin_hotkey": selection["origin_hotkey"],
|
|
291
|
+
"origin_netuid": selection["origin_netuid"],
|
|
292
|
+
"destination_netuid": selection["destination_netuid"],
|
|
293
|
+
"destination_coldkey": dest_coldkey,
|
|
294
|
+
"amount": selection["amount"],
|
|
295
|
+
"stake_all": selection["stake_all"],
|
|
296
|
+
}
|
|
297
|
+
except ValueError:
|
|
298
|
+
raise
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
async def _guide_swap_operation(
|
|
302
|
+
meshtensor: "MeshtensorInterface",
|
|
303
|
+
wallet: Wallet,
|
|
304
|
+
available_stakes: list,
|
|
305
|
+
) -> dict:
|
|
306
|
+
"""Guide user through swap operation."""
|
|
307
|
+
console.print(
|
|
308
|
+
"\n[bold cyan]Swap Operation[/bold cyan]\n"
|
|
309
|
+
"You will swap stake between subnets.\n"
|
|
310
|
+
"The same coldkey-hotkey pair is used, but stake moves between subnets.\n"
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
try:
|
|
314
|
+
selection = await stake_swap_selection(meshtensor, wallet)
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
"operation": "swap",
|
|
318
|
+
"origin_netuid": selection["origin_netuid"],
|
|
319
|
+
"destination_netuid": selection["destination_netuid"],
|
|
320
|
+
"amount": selection["amount"],
|
|
321
|
+
}
|
|
322
|
+
except ValueError:
|
|
323
|
+
raise
|
|
File without changes
|