cartha-cli 1.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.
@@ -0,0 +1,283 @@
1
+ """Miner password command - shows password with authentication."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ import bittensor as bt
8
+ import typer
9
+ from rich.json import JSON
10
+
11
+ from ..config import settings
12
+ from ..pair import (
13
+ build_pair_auth_payload,
14
+ get_uid_from_hotkey,
15
+ )
16
+ from ..utils import format_timestamp
17
+ from ..verifier import VerifierError, fetch_pair_status
18
+ from ..wallet import load_wallet
19
+ from .common import (
20
+ console,
21
+ handle_unexpected_exception,
22
+ handle_wallet_exception,
23
+ )
24
+ from .shared_options import (
25
+ wallet_name_option,
26
+ wallet_hotkey_option,
27
+ slot_option,
28
+ auto_fetch_uid_option,
29
+ network_option,
30
+ netuid_option,
31
+ json_output_option,
32
+ )
33
+
34
+
35
+ def miner_password(
36
+ wallet_name: str = wallet_name_option(required=True),
37
+ wallet_hotkey: str = wallet_hotkey_option(required=True),
38
+ slot: int | None = slot_option(),
39
+ auto_fetch_uid: bool = auto_fetch_uid_option(),
40
+ network: str = network_option(),
41
+ netuid: int = netuid_option(),
42
+ json_output: bool = json_output_option(),
43
+ ) -> None:
44
+ """DEPRECATED: View your existing miner password (requires authentication).
45
+
46
+ All arguments are optional - the CLI will prompt for wallet name and hotkey if not provided.
47
+ Multiple aliases available: use --wallet-name or --coldkey, --wallet-hotkey or --hotkey, -w, -wh, etc.
48
+
49
+ ⚠️ This command is deprecated. The new lock flow uses session tokens instead of passwords.
50
+ Passwords were only used in the old LockProof flow, which has been replaced.
51
+
52
+ This command allows you to VIEW existing passwords only. Password generation is no longer supported.
53
+ Use 'cartha vault lock' to create new lock positions with the new flow.
54
+ """
55
+ console.print(
56
+ "[bold yellow]⚠️ DEPRECATED:[/] The miner password command is deprecated. "
57
+ "The new lock flow uses session tokens instead of passwords."
58
+ )
59
+ console.print()
60
+ console.print(
61
+ "[dim]This command allows you to VIEW existing passwords only. "
62
+ "Password generation is no longer supported.[/]"
63
+ )
64
+ console.print()
65
+
66
+ try:
67
+ # Auto-map netuid and verifier URL based on network
68
+ if network == "test":
69
+ netuid = 78
70
+ elif network == "finney":
71
+ netuid = 35
72
+ # Warn that mainnet is not live yet
73
+ console.print()
74
+ console.print("[bold yellow]⚠️ MAINNET NOT AVAILABLE YET[/]")
75
+ console.print("[yellow]Cartha subnet is currently in testnet phase (subnet 78).[/]")
76
+ console.print("[yellow]Mainnet (subnet 35) has not been announced yet.[/]")
77
+ console.print("[dim]Use --network test to access testnet.[/]")
78
+ console.print()
79
+ # Note: netuid parameter is kept for backwards compatibility / explicit override
80
+
81
+ from ..config import get_verifier_url_for_network
82
+ expected_verifier_url = get_verifier_url_for_network(network)
83
+ if settings.verifier_url != expected_verifier_url:
84
+ settings.verifier_url = expected_verifier_url
85
+
86
+ console.print("[bold cyan]Loading wallet...[/]")
87
+ wallet = load_wallet(wallet_name, wallet_hotkey, None)
88
+ hotkey = wallet.hotkey.ss58_address
89
+
90
+ # Fetch UID automatically by default, prompt if disabled
91
+ if slot is None:
92
+ if auto_fetch_uid:
93
+ console.print("[bold cyan]Fetching UID from subnet...[/]")
94
+ try:
95
+ slot = get_uid_from_hotkey(
96
+ network=network, netuid=netuid, hotkey=hotkey
97
+ )
98
+ if slot is None:
99
+ console.print(
100
+ "[bold yellow]Hotkey is not registered or has been deregistered[/] "
101
+ f"on netuid {netuid} ({network} network)."
102
+ )
103
+ console.print(
104
+ "[yellow]You do not belong to any UID at the moment.[/] "
105
+ "Please register your hotkey first using 'cartha miner register'."
106
+ )
107
+ raise typer.Exit(code=0)
108
+ console.print(f"[bold green]Found UID: {slot}[/]")
109
+ except typer.Exit:
110
+ raise
111
+ except Exception as exc:
112
+ console.print(
113
+ "[bold red]Failed to fetch UID automatically[/]: This may be due to Bittensor network issues."
114
+ )
115
+ console.print("[yellow]Falling back to manual input...[/]")
116
+ try:
117
+ slot_input = typer.prompt("Enter your slot UID", type=int)
118
+ slot = slot_input
119
+ console.print(f"[bold green]Using UID: {slot}[/]")
120
+ except (ValueError, KeyboardInterrupt):
121
+ console.print("[bold red]Invalid UID or cancelled.[/]")
122
+ raise typer.Exit(code=1) from exc
123
+ else:
124
+ console.print(
125
+ "[bold cyan]UID not provided.[/] "
126
+ "[yellow]Auto-fetch disabled. Enter UID manually.[/]"
127
+ )
128
+ try:
129
+ slot_input = typer.prompt(
130
+ "Enter your slot UID (from 'cartha miner register' output)",
131
+ type=int,
132
+ )
133
+ slot = slot_input
134
+ console.print(f"[bold green]Using UID: {slot}[/]")
135
+ except (ValueError, KeyboardInterrupt):
136
+ console.print("[bold red]Invalid UID or cancelled.[/]")
137
+ raise typer.Exit(code=1)
138
+
139
+ slot_id = str(slot)
140
+
141
+ console.print("[bold cyan]Signing hotkey ownership challenge...[/]")
142
+ auth_payload = build_pair_auth_payload(
143
+ network=network,
144
+ netuid=netuid,
145
+ slot=slot_id,
146
+ hotkey=hotkey,
147
+ wallet_name=wallet_name,
148
+ wallet_hotkey=wallet_hotkey,
149
+ )
150
+ with console.status(
151
+ "[bold cyan]Verifying ownership with Cartha verifier...[/]",
152
+ spinner="dots",
153
+ ):
154
+ status = fetch_pair_status(
155
+ hotkey=hotkey,
156
+ slot=slot_id,
157
+ network=network,
158
+ netuid=netuid,
159
+ message=auth_payload["message"],
160
+ signature=auth_payload["signature"],
161
+ )
162
+ except bt.KeyFileError as exc:
163
+ handle_wallet_exception(
164
+ wallet_name=wallet_name, wallet_hotkey=wallet_hotkey, exc=exc
165
+ )
166
+ except typer.Exit:
167
+ raise
168
+ except VerifierError as exc:
169
+ error_msg = str(exc)
170
+ if "timed out" in error_msg.lower() or "timeout" in error_msg.lower():
171
+ console.print(f"[bold red]Request timed out[/]")
172
+ console.print(f"[yellow]{error_msg}[/]")
173
+ else:
174
+ console.print(f"[bold red]Verifier request failed[/]: {exc}")
175
+ raise typer.Exit(code=1) from exc
176
+ except Exception as exc:
177
+ error_msg = str(exc)
178
+ error_type = type(exc).__name__
179
+
180
+ is_timeout = (
181
+ "timed out" in error_msg.lower()
182
+ or "timeout" in error_msg.lower()
183
+ or error_type == "Timeout"
184
+ or (
185
+ hasattr(exc, "__cause__")
186
+ and exc.__cause__ is not None
187
+ and (
188
+ "timeout" in str(exc.__cause__).lower()
189
+ or "Timeout" in type(exc.__cause__).__name__
190
+ )
191
+ )
192
+ )
193
+
194
+ if is_timeout:
195
+ console.print(f"[bold red]Request timed out[/]")
196
+ console.print(
197
+ f"[yellow]CLI failed to reach Cartha verifier\n"
198
+ f"Possible causes: Network latency or the verifier is receiving too many requests\n"
199
+ f"Tip: Try again in a moment\n"
200
+ f"Error details: {error_msg}[/]"
201
+ )
202
+ raise typer.Exit(code=1) from exc
203
+
204
+ handle_unexpected_exception("Unable to fetch password", exc)
205
+
206
+ initial_status = dict(status)
207
+ existing_pwd = initial_status.get("pwd")
208
+ state = initial_status.get("state") or "unknown"
209
+ has_pwd_flag = initial_status.get("has_pwd") or bool(existing_pwd)
210
+
211
+ # Password generation is deprecated - only allow viewing existing passwords
212
+ if not has_pwd_flag and not json_output:
213
+ console.print()
214
+ console.print(
215
+ "[bold yellow]⚠️ No password found for this miner.[/]"
216
+ )
217
+ console.print()
218
+ console.print(
219
+ "[dim]Password generation is no longer supported. "
220
+ "The new lock flow uses session tokens instead of passwords.[/]"
221
+ )
222
+ console.print()
223
+ console.print(
224
+ "[bold cyan]To create a lock position, use the new lock flow:[/]"
225
+ )
226
+ console.print(" [green]cartha vault lock[/] --coldkey <name> --hotkey <name> --pool-id <pool> --amount <amount> --lock-days <days> --owner-evm <address> --chain-id <chain> --vault-address <vault>")
227
+ console.print()
228
+ raise typer.Exit(code=0)
229
+
230
+ sanitized = dict(status)
231
+ sanitized.setdefault("state", "unknown")
232
+ password = sanitized.get("pwd")
233
+ issued_at = sanitized.get("issued_at")
234
+
235
+ if json_output:
236
+ console.print(JSON.from_data(sanitized))
237
+ if password:
238
+ console.print(
239
+ "[bold yellow]Keep it safe[/] — for your eyes only. Exposure might allow others to steal your locked USDC rewards."
240
+ )
241
+ return
242
+
243
+ # Display password information
244
+ from rich.table import Table
245
+ from datetime import datetime
246
+
247
+ table = Table(title="Miner Password", show_header=False)
248
+ table.add_row("Hotkey", hotkey)
249
+ table.add_row("Slot UID", slot_id)
250
+ table.add_row("Password issued", "yes" if sanitized.get("has_pwd") else "no")
251
+
252
+ if issued_at:
253
+ try:
254
+ if isinstance(issued_at, (int, float)) or (
255
+ isinstance(issued_at, str) and issued_at.isdigit()
256
+ ):
257
+ formatted_time = format_timestamp(issued_at)
258
+ elif isinstance(issued_at, str):
259
+ try:
260
+ dt = datetime.fromisoformat(issued_at.replace("Z", "+00:00"))
261
+ timestamp = dt.timestamp()
262
+ formatted_time = format_timestamp(timestamp)
263
+ except (ValueError, AttributeError):
264
+ formatted_time = issued_at
265
+ else:
266
+ formatted_time = str(issued_at)
267
+ table.add_row("Password issued at", formatted_time)
268
+ except Exception:
269
+ table.add_row("Password issued at", str(issued_at))
270
+
271
+ if password:
272
+ table.add_row("Pair password", password)
273
+
274
+ console.print(table)
275
+
276
+ # Show password warning
277
+ if password:
278
+ console.print()
279
+ console.print(
280
+ "[bold yellow]🔐 Keep your password safe[/] — Exposure might allow others to steal your locked USDC rewards."
281
+ )
282
+
283
+ return