htcli 1.1.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 (140) hide show
  1. htcli-1.1.0.dist-info/METADATA +509 -0
  2. htcli-1.1.0.dist-info/RECORD +140 -0
  3. htcli-1.1.0.dist-info/WHEEL +4 -0
  4. htcli-1.1.0.dist-info/entry_points.txt +2 -0
  5. htcli-1.1.0.dist-info/licenses/LICENSE +21 -0
  6. src/__init__.py +0 -0
  7. src/htcli/__init__.py +5 -0
  8. src/htcli/client/__init__.py +338 -0
  9. src/htcli/client/extrinsics/__init__.py +26 -0
  10. src/htcli/client/extrinsics/base.py +487 -0
  11. src/htcli/client/extrinsics/consensus.py +79 -0
  12. src/htcli/client/extrinsics/governance.py +714 -0
  13. src/htcli/client/extrinsics/identity.py +490 -0
  14. src/htcli/client/extrinsics/node.py +1054 -0
  15. src/htcli/client/extrinsics/overwatch.py +401 -0
  16. src/htcli/client/extrinsics/staking.py +1504 -0
  17. src/htcli/client/extrinsics/subnet.py +2218 -0
  18. src/htcli/client/extrinsics/validator.py +203 -0
  19. src/htcli/client/extrinsics/wallet.py +323 -0
  20. src/htcli/client/offchain/__init__.py +10 -0
  21. src/htcli/client/offchain/backup.py +385 -0
  22. src/htcli/client/offchain/config.py +541 -0
  23. src/htcli/client/offchain/wallet.py +839 -0
  24. src/htcli/client/rpc/__init__.py +20 -0
  25. src/htcli/client/rpc/chain.py +568 -0
  26. src/htcli/client/rpc/node.py +783 -0
  27. src/htcli/client/rpc/overwatch.py +680 -0
  28. src/htcli/client/rpc/staking.py +216 -0
  29. src/htcli/client/rpc/subnet.py +2104 -0
  30. src/htcli/client/rpc/wallet.py +912 -0
  31. src/htcli/commands/__init__.py +31 -0
  32. src/htcli/commands/chain/__init__.py +66 -0
  33. src/htcli/commands/chain/display.py +204 -0
  34. src/htcli/commands/chain/handlers.py +260 -0
  35. src/htcli/commands/config/__init__.py +158 -0
  36. src/htcli/commands/config/display.py +353 -0
  37. src/htcli/commands/config/handlers.py +347 -0
  38. src/htcli/commands/config/prompts.py +357 -0
  39. src/htcli/commands/consensus/__init__.py +61 -0
  40. src/htcli/commands/consensus/handlers.py +100 -0
  41. src/htcli/commands/governance/__init__.py +49 -0
  42. src/htcli/commands/governance/handlers.py +81 -0
  43. src/htcli/commands/node/__init__.py +304 -0
  44. src/htcli/commands/node/display.py +749 -0
  45. src/htcli/commands/node/error_handling.py +470 -0
  46. src/htcli/commands/node/handlers.py +844 -0
  47. src/htcli/commands/node/prompts.py +346 -0
  48. src/htcli/commands/overwatch/__init__.py +219 -0
  49. src/htcli/commands/overwatch/display.py +396 -0
  50. src/htcli/commands/overwatch/error_handling.py +276 -0
  51. src/htcli/commands/overwatch/handlers.py +443 -0
  52. src/htcli/commands/overwatch/prompts.py +359 -0
  53. src/htcli/commands/stake/__init__.py +736 -0
  54. src/htcli/commands/stake/display.py +1103 -0
  55. src/htcli/commands/stake/error_handling.py +425 -0
  56. src/htcli/commands/stake/handlers.py +1902 -0
  57. src/htcli/commands/stake/prompts.py +1080 -0
  58. src/htcli/commands/subnet/__init__.py +639 -0
  59. src/htcli/commands/subnet/display.py +801 -0
  60. src/htcli/commands/subnet/error_handling.py +524 -0
  61. src/htcli/commands/subnet/handlers.py +2855 -0
  62. src/htcli/commands/subnet/prompts.py +1225 -0
  63. src/htcli/commands/validator/__init__.py +192 -0
  64. src/htcli/commands/validator/display.py +54 -0
  65. src/htcli/commands/validator/handlers.py +340 -0
  66. src/htcli/commands/wallet/__init__.py +546 -0
  67. src/htcli/commands/wallet/display.py +806 -0
  68. src/htcli/commands/wallet/error_handling.py +210 -0
  69. src/htcli/commands/wallet/handlers.py +3040 -0
  70. src/htcli/commands/wallet/prompts.py +1518 -0
  71. src/htcli/config.py +184 -0
  72. src/htcli/dependencies.py +186 -0
  73. src/htcli/errors/__init__.py +63 -0
  74. src/htcli/errors/base.py +141 -0
  75. src/htcli/errors/display.py +20 -0
  76. src/htcli/errors/handlers.py +710 -0
  77. src/htcli/main.py +343 -0
  78. src/htcli/models/__init__.py +21 -0
  79. src/htcli/models/enums/enum_types.py +35 -0
  80. src/htcli/models/errors.py +103 -0
  81. src/htcli/models/requests/__init__.py +197 -0
  82. src/htcli/models/requests/config.py +70 -0
  83. src/htcli/models/requests/consensus.py +19 -0
  84. src/htcli/models/requests/governance.py +38 -0
  85. src/htcli/models/requests/identity.py +51 -0
  86. src/htcli/models/requests/key.py +22 -0
  87. src/htcli/models/requests/node.py +91 -0
  88. src/htcli/models/requests/overwatch.py +64 -0
  89. src/htcli/models/requests/staking.py +580 -0
  90. src/htcli/models/requests/subnet.py +195 -0
  91. src/htcli/models/requests/validator.py +139 -0
  92. src/htcli/models/requests/wallet.py +118 -0
  93. src/htcli/models/responses/__init__.py +147 -0
  94. src/htcli/models/responses/base.py +18 -0
  95. src/htcli/models/responses/chain.py +39 -0
  96. src/htcli/models/responses/config.py +58 -0
  97. src/htcli/models/responses/identity.py +102 -0
  98. src/htcli/models/responses/overwatch.py +51 -0
  99. src/htcli/models/responses/staking.py +502 -0
  100. src/htcli/models/responses/subnet.py +856 -0
  101. src/htcli/models/responses/wallet.py +185 -0
  102. src/htcli/ui/__init__.py +87 -0
  103. src/htcli/ui/colors.py +309 -0
  104. src/htcli/ui/components/__init__.py +60 -0
  105. src/htcli/ui/components/panels.py +174 -0
  106. src/htcli/ui/components/progress.py +166 -0
  107. src/htcli/ui/components/spinners.py +92 -0
  108. src/htcli/ui/components/tables.py +809 -0
  109. src/htcli/ui/components/trees.py +721 -0
  110. src/htcli/ui/display.py +336 -0
  111. src/htcli/ui/prompts.py +870 -0
  112. src/htcli/utils/__init__.py +76 -0
  113. src/htcli/utils/blockchain/__init__.py +75 -0
  114. src/htcli/utils/blockchain/formatting.py +368 -0
  115. src/htcli/utils/blockchain/patches.py +286 -0
  116. src/htcli/utils/blockchain/peer_id.py +186 -0
  117. src/htcli/utils/blockchain/staking.py +448 -0
  118. src/htcli/utils/blockchain/type_registry.py +1373 -0
  119. src/htcli/utils/blockchain/validation.py +179 -0
  120. src/htcli/utils/cache.py +613 -0
  121. src/htcli/utils/constants.py +38 -0
  122. src/htcli/utils/legacy/__init__.py +12 -0
  123. src/htcli/utils/legacy/colors.py +311 -0
  124. src/htcli/utils/legacy/crypto.py +1176 -0
  125. src/htcli/utils/legacy/formatting.py +452 -0
  126. src/htcli/utils/legacy/interactive.py +306 -0
  127. src/htcli/utils/legacy/subnet_manifest.py +265 -0
  128. src/htcli/utils/legacy/validation.py +488 -0
  129. src/htcli/utils/logging.py +183 -0
  130. src/htcli/utils/network/__init__.py +20 -0
  131. src/htcli/utils/network/subnet.py +344 -0
  132. src/htcli/utils/prompts.py +27 -0
  133. src/htcli/utils/scale_codec.py +155 -0
  134. src/htcli/utils/validation/__init__.py +57 -0
  135. src/htcli/utils/validation/prompt_validators.py +267 -0
  136. src/htcli/utils/wallet/__init__.py +65 -0
  137. src/htcli/utils/wallet/auth.py +151 -0
  138. src/htcli/utils/wallet/core.py +1069 -0
  139. src/htcli/utils/wallet/crypto.py +1615 -0
  140. src/htcli/utils/wallet/migration.py +159 -0
@@ -0,0 +1,336 @@
1
+ """
2
+ HTCLI display utilities and console management.
3
+ Provides consistent display functions across the CLI.
4
+ """
5
+
6
+ from typing import Any, Union
7
+
8
+ from rich.align import Align
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+ from rich.rule import Rule
12
+ from rich.text import Text
13
+
14
+ from .colors import HTCLIColors, HTCLITheme
15
+
16
+
17
+ class HTCLIConsole:
18
+ """Enhanced console with HTCLI theming and utilities."""
19
+
20
+ def __init__(self, force_terminal: bool = None):
21
+ # If force_terminal is None, let Rich auto-detect
22
+ # But ensure we have proper terminal capabilities for Live displays
23
+ import sys
24
+ # Check if stdout is a TTY (terminal) - important for Live displays
25
+ is_terminal = sys.stdout.isatty() if force_terminal is None else force_terminal
26
+
27
+ self.console = Console(
28
+ theme=HTCLITheme.get_theme(),
29
+ force_terminal=is_terminal,
30
+ width=120, # Consistent width for better formatting
31
+ # Ensure proper terminal detection for live updates
32
+ legacy_windows=False, # Use modern terminal features
33
+ )
34
+
35
+ def print(self, *args, **kwargs):
36
+ """Print with HTCLI theming."""
37
+ self.console.print(*args, **kwargs)
38
+
39
+ def print_panel(
40
+ self,
41
+ content: Any,
42
+ title: str = None,
43
+ title_style: str = "htcli.panel.title",
44
+ border_style: str = "htcli.border",
45
+ padding: tuple = (1, 2),
46
+ expand: bool = False,
47
+ ):
48
+ """Print content in a styled panel."""
49
+ panel = Panel(
50
+ content,
51
+ title=title,
52
+ title_align="left",
53
+ border_style=border_style,
54
+ padding=padding,
55
+ expand=expand,
56
+ )
57
+ if title:
58
+ panel.title = Text(title, style=title_style)
59
+ self.console.print(panel)
60
+
61
+ def print_rule(
62
+ self, title: str = None, style: str = "htcli.border", align: str = "center"
63
+ ):
64
+ """Print a horizontal rule with optional title."""
65
+ if title:
66
+ rule = Rule(Text(title, style="htcli.title"), style=style, align=align)
67
+ else:
68
+ rule = Rule(style=style)
69
+ self.console.print(rule)
70
+
71
+ def clear(self):
72
+ """Clear the console."""
73
+ self.console.clear()
74
+
75
+ def input(self, prompt: str = "", style: str = "htcli.prompt") -> str:
76
+ """Get input with styled prompt."""
77
+ styled_prompt = Text(prompt, style=style)
78
+ return self.console.input(styled_prompt)
79
+
80
+ def print_json(
81
+ self, data: Any = None, *, indent: int = 2, sort_keys: bool = False
82
+ ) -> None:
83
+ """Proxy to rich Console.print_json for JSON rendering."""
84
+ self.console.print_json(data=data, indent=indent, sort_keys=sort_keys)
85
+
86
+
87
+ # Global console instance
88
+ _console = HTCLIConsole()
89
+
90
+
91
+ def get_console() -> HTCLIConsole:
92
+ """Get the global HTCLI console instance."""
93
+ return _console
94
+
95
+
96
+ def print_success(
97
+ message: str, title: str = None, emoji: bool = True, panel: bool = False
98
+ ):
99
+ """Print a success message."""
100
+ prefix = "✅ " if emoji else ""
101
+ text = f"{prefix}{message}"
102
+
103
+ if panel:
104
+ _console.print_panel(
105
+ Text(text, style="htcli.status.success"),
106
+ title=title,
107
+ border_style="success",
108
+ )
109
+ else:
110
+ _console.print(f"[htcli.status.success]{text}[/]")
111
+
112
+
113
+ def print_error(
114
+ message: str,
115
+ title: str = None,
116
+ emoji: bool = True,
117
+ panel: bool = False,
118
+ suggestions: list[str] = None,
119
+ ):
120
+ """Print an error message with optional suggestions."""
121
+ prefix = "❌ " if emoji else ""
122
+ text = f"{prefix}{message}"
123
+
124
+ content = Text(text, style="htcli.status.error")
125
+
126
+ if suggestions:
127
+ content.append("\n\n")
128
+ content.append("💡 Suggestions:\n", style="htcli.warning")
129
+ for suggestion in suggestions:
130
+ content.append(f"• {suggestion}\n", style="htcli.info")
131
+
132
+ if panel:
133
+ _console.print_panel(content, title=title, border_style="error")
134
+ else:
135
+ _console.print(content)
136
+
137
+
138
+ def print_warning(
139
+ message: str, title: str = None, emoji: bool = True, panel: bool = False
140
+ ):
141
+ """Print a warning message."""
142
+ prefix = "⚠️ " if emoji else "" # Two spaces after emoji for proper spacing
143
+ text = f"{prefix}{message}"
144
+
145
+ if panel:
146
+ _console.print_panel(
147
+ Text(text, style="htcli.status.pending"),
148
+ title=title,
149
+ border_style="warning",
150
+ )
151
+ else:
152
+ _console.print(f"[htcli.status.pending]{text}[/]")
153
+
154
+
155
+ def print_info(
156
+ message: str, title: str = None, emoji: bool = True, panel: bool = False
157
+ ):
158
+ """Print an info message."""
159
+ prefix = "ℹ️ " if emoji else "" # Add space after emoji
160
+ text = f"{prefix}{message}"
161
+
162
+ if panel:
163
+ _console.print_panel(
164
+ Text(text, style="htcli.info"), title=title, border_style="info"
165
+ )
166
+ else:
167
+ _console.print(f"[htcli.info]{text}[/]")
168
+
169
+
170
+ def print_header(
171
+ title: str, subtitle: str = None, version: str = None, width: int = 80
172
+ ):
173
+ """Print a styled header for commands."""
174
+ # Create the main title
175
+ title_text = Text(title, style="htcli.header")
176
+ if version:
177
+ title_text.append(f" v{version}", style="htcli.subtitle")
178
+
179
+ header_content = Align.center(title_text)
180
+
181
+ if subtitle:
182
+ subtitle_text = Text(subtitle, style="htcli.subtitle")
183
+ header_content = Align.center(f"{title_text}\n{subtitle_text}")
184
+
185
+ _console.print_panel(
186
+ header_content, border_style="htcli.primary", padding=(1, 4), expand=False
187
+ )
188
+ _console.print()
189
+
190
+
191
+ def print_footer(message: str = None, show_help: bool = True, command: str = None):
192
+ """Print a styled footer."""
193
+ if not message and not show_help:
194
+ return
195
+
196
+ content = []
197
+
198
+ if message:
199
+ content.append(Text(message, style="htcli.subtitle"))
200
+
201
+ if show_help:
202
+ help_text = "Use --help for more information"
203
+ if command:
204
+ help_text = f"Use 'htcli {command} --help' for more information"
205
+ content.append(Text(help_text, style="htcli.muted"))
206
+
207
+ if content:
208
+ _console.print()
209
+ for item in content:
210
+ _console.print(Align.center(item))
211
+
212
+
213
+ def print_status(status: str, message: str, emoji_map: dict = None):
214
+ """Print a status message with appropriate styling."""
215
+ default_emojis = {
216
+ "success": "✅",
217
+ "error": "❌",
218
+ "warning": "⚠️",
219
+ "info": "ℹ️",
220
+ "loading": "⏳",
221
+ "active": "🟢",
222
+ "inactive": "⚪",
223
+ "pending": "🟡",
224
+ }
225
+
226
+ emojis = emoji_map or default_emojis
227
+ emoji = emojis.get(status.lower(), "•")
228
+ color = HTCLIColors.get_status_color(status)
229
+
230
+ _console.print(f"[{color}]{emoji} {message}[/]")
231
+
232
+
233
+ def print_blockchain_data(title: str, data: dict, highlight_keys: list[str] = None):
234
+ """Print blockchain data in a formatted way."""
235
+ highlight_keys = highlight_keys or []
236
+
237
+ content = []
238
+ for key, value in data.items():
239
+ key_style = "htcli.highlight" if key in highlight_keys else "htcli.subtitle"
240
+
241
+ # Format different types of blockchain data
242
+ if key.lower() in ["address", "account", "validator"]:
243
+ formatted_value = f"[htcli.address]{value}[/]"
244
+ elif key.lower() in ["amount", "balance", "stake", "reward"]:
245
+ formatted_value = f"[htcli.amount]{value}[/]"
246
+ elif key.lower() in ["hash", "block_hash", "tx_hash"]:
247
+ formatted_value = f"[htcli.hash]{value}[/]"
248
+ elif key.lower() in ["status", "state"]:
249
+ formatted_value = f"[htcli.status.{value.lower()}]{value}[/]"
250
+ else:
251
+ formatted_value = f"[htcli.value]{value}[/]"
252
+
253
+ content.append(f"[{key_style}]{key}:[/] {formatted_value}")
254
+
255
+ _console.print_panel("\n".join(content), title=title, border_style="htcli.border")
256
+
257
+
258
+ def print_command_result(
259
+ success: bool,
260
+ message: str,
261
+ data: dict = None,
262
+ transaction_hash: str = None,
263
+ suggestions: list[str] = None,
264
+ ):
265
+ """Print standardized command result."""
266
+ if success:
267
+ print_success(message, panel=True)
268
+ if transaction_hash:
269
+ _console.print(
270
+ f"\n[htcli.subtitle]Transaction Hash:[/] [htcli.hash]{transaction_hash}[/]"
271
+ )
272
+ if data:
273
+ print_blockchain_data("Result Details", data)
274
+ else:
275
+ print_error(message, panel=True, suggestions=suggestions)
276
+
277
+
278
+ def print_separator(char: str = "─", style: str = "htcli.border"):
279
+ """Print a separator line."""
280
+ _console.print(Rule(style=style, characters=char))
281
+
282
+
283
+ def print_logo():
284
+ """Print the HTCLI logo."""
285
+ logo = """
286
+ ██╗ ██╗████████╗ ██████╗██╗ ██╗
287
+ ██║ ██║╚══██╔══╝██╔════╝██║ ██║
288
+ ███████║ ██║ ██║ ██║ ██║
289
+ ██╔══██║ ██║ ██║ ██║ ██║
290
+ ██║ ██║ ██║ ╚██████╗███████╗██║
291
+ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝
292
+
293
+ Hypertensor Command Line Interface
294
+ """
295
+
296
+ _console.print(Align.center(Text(logo, style="htcli.primary", justify="center")))
297
+
298
+
299
+ # Utility functions for quick formatting
300
+ def format_address(address: str, truncate: bool = True) -> str:
301
+ """Format a blockchain address with truncation."""
302
+ if truncate and len(address) > 20:
303
+ return f"{address[:8]}...{address[-8:]}"
304
+ return address
305
+
306
+
307
+ def format_amount(
308
+ amount: Union[int, float], decimals: int = 6, currency: str = "TENSOR"
309
+ ) -> str:
310
+ """Format an amount with proper decimals and currency."""
311
+ if isinstance(amount, int):
312
+ formatted = f"{amount / (10**18):.{decimals}f}"
313
+ else:
314
+ formatted = f"{amount:.{decimals}f}"
315
+ return f"{formatted} {currency}"
316
+
317
+
318
+ def format_hash(hash_value: str, truncate: bool = True) -> str:
319
+ """Format a hash value with optional truncation."""
320
+ if truncate and len(hash_value) > 16:
321
+ return f"{hash_value[:8]}...{hash_value[-8:]}"
322
+ return hash_value
323
+
324
+
325
+ def format_status(status: str) -> str:
326
+ """Format a status with appropriate emoji."""
327
+ status_emojis = {
328
+ "active": "🟢 Active",
329
+ "inactive": "⚪ Inactive",
330
+ "pending": "🟡 Pending",
331
+ "success": "✅ Success",
332
+ "failed": "❌ Failed",
333
+ "error": "❌ Error",
334
+ "warning": "⚠️ Warning",
335
+ }
336
+ return status_emojis.get(status.lower(), f"• {status}")