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.
- htcli-1.1.0.dist-info/METADATA +509 -0
- htcli-1.1.0.dist-info/RECORD +140 -0
- htcli-1.1.0.dist-info/WHEEL +4 -0
- htcli-1.1.0.dist-info/entry_points.txt +2 -0
- htcli-1.1.0.dist-info/licenses/LICENSE +21 -0
- src/__init__.py +0 -0
- src/htcli/__init__.py +5 -0
- src/htcli/client/__init__.py +338 -0
- src/htcli/client/extrinsics/__init__.py +26 -0
- src/htcli/client/extrinsics/base.py +487 -0
- src/htcli/client/extrinsics/consensus.py +79 -0
- src/htcli/client/extrinsics/governance.py +714 -0
- src/htcli/client/extrinsics/identity.py +490 -0
- src/htcli/client/extrinsics/node.py +1054 -0
- src/htcli/client/extrinsics/overwatch.py +401 -0
- src/htcli/client/extrinsics/staking.py +1504 -0
- src/htcli/client/extrinsics/subnet.py +2218 -0
- src/htcli/client/extrinsics/validator.py +203 -0
- src/htcli/client/extrinsics/wallet.py +323 -0
- src/htcli/client/offchain/__init__.py +10 -0
- src/htcli/client/offchain/backup.py +385 -0
- src/htcli/client/offchain/config.py +541 -0
- src/htcli/client/offchain/wallet.py +839 -0
- src/htcli/client/rpc/__init__.py +20 -0
- src/htcli/client/rpc/chain.py +568 -0
- src/htcli/client/rpc/node.py +783 -0
- src/htcli/client/rpc/overwatch.py +680 -0
- src/htcli/client/rpc/staking.py +216 -0
- src/htcli/client/rpc/subnet.py +2104 -0
- src/htcli/client/rpc/wallet.py +912 -0
- src/htcli/commands/__init__.py +31 -0
- src/htcli/commands/chain/__init__.py +66 -0
- src/htcli/commands/chain/display.py +204 -0
- src/htcli/commands/chain/handlers.py +260 -0
- src/htcli/commands/config/__init__.py +158 -0
- src/htcli/commands/config/display.py +353 -0
- src/htcli/commands/config/handlers.py +347 -0
- src/htcli/commands/config/prompts.py +357 -0
- src/htcli/commands/consensus/__init__.py +61 -0
- src/htcli/commands/consensus/handlers.py +100 -0
- src/htcli/commands/governance/__init__.py +49 -0
- src/htcli/commands/governance/handlers.py +81 -0
- src/htcli/commands/node/__init__.py +304 -0
- src/htcli/commands/node/display.py +749 -0
- src/htcli/commands/node/error_handling.py +470 -0
- src/htcli/commands/node/handlers.py +844 -0
- src/htcli/commands/node/prompts.py +346 -0
- src/htcli/commands/overwatch/__init__.py +219 -0
- src/htcli/commands/overwatch/display.py +396 -0
- src/htcli/commands/overwatch/error_handling.py +276 -0
- src/htcli/commands/overwatch/handlers.py +443 -0
- src/htcli/commands/overwatch/prompts.py +359 -0
- src/htcli/commands/stake/__init__.py +736 -0
- src/htcli/commands/stake/display.py +1103 -0
- src/htcli/commands/stake/error_handling.py +425 -0
- src/htcli/commands/stake/handlers.py +1902 -0
- src/htcli/commands/stake/prompts.py +1080 -0
- src/htcli/commands/subnet/__init__.py +639 -0
- src/htcli/commands/subnet/display.py +801 -0
- src/htcli/commands/subnet/error_handling.py +524 -0
- src/htcli/commands/subnet/handlers.py +2855 -0
- src/htcli/commands/subnet/prompts.py +1225 -0
- src/htcli/commands/validator/__init__.py +192 -0
- src/htcli/commands/validator/display.py +54 -0
- src/htcli/commands/validator/handlers.py +340 -0
- src/htcli/commands/wallet/__init__.py +546 -0
- src/htcli/commands/wallet/display.py +806 -0
- src/htcli/commands/wallet/error_handling.py +210 -0
- src/htcli/commands/wallet/handlers.py +3040 -0
- src/htcli/commands/wallet/prompts.py +1518 -0
- src/htcli/config.py +184 -0
- src/htcli/dependencies.py +186 -0
- src/htcli/errors/__init__.py +63 -0
- src/htcli/errors/base.py +141 -0
- src/htcli/errors/display.py +20 -0
- src/htcli/errors/handlers.py +710 -0
- src/htcli/main.py +343 -0
- src/htcli/models/__init__.py +21 -0
- src/htcli/models/enums/enum_types.py +35 -0
- src/htcli/models/errors.py +103 -0
- src/htcli/models/requests/__init__.py +197 -0
- src/htcli/models/requests/config.py +70 -0
- src/htcli/models/requests/consensus.py +19 -0
- src/htcli/models/requests/governance.py +38 -0
- src/htcli/models/requests/identity.py +51 -0
- src/htcli/models/requests/key.py +22 -0
- src/htcli/models/requests/node.py +91 -0
- src/htcli/models/requests/overwatch.py +64 -0
- src/htcli/models/requests/staking.py +580 -0
- src/htcli/models/requests/subnet.py +195 -0
- src/htcli/models/requests/validator.py +139 -0
- src/htcli/models/requests/wallet.py +118 -0
- src/htcli/models/responses/__init__.py +147 -0
- src/htcli/models/responses/base.py +18 -0
- src/htcli/models/responses/chain.py +39 -0
- src/htcli/models/responses/config.py +58 -0
- src/htcli/models/responses/identity.py +102 -0
- src/htcli/models/responses/overwatch.py +51 -0
- src/htcli/models/responses/staking.py +502 -0
- src/htcli/models/responses/subnet.py +856 -0
- src/htcli/models/responses/wallet.py +185 -0
- src/htcli/ui/__init__.py +87 -0
- src/htcli/ui/colors.py +309 -0
- src/htcli/ui/components/__init__.py +60 -0
- src/htcli/ui/components/panels.py +174 -0
- src/htcli/ui/components/progress.py +166 -0
- src/htcli/ui/components/spinners.py +92 -0
- src/htcli/ui/components/tables.py +809 -0
- src/htcli/ui/components/trees.py +721 -0
- src/htcli/ui/display.py +336 -0
- src/htcli/ui/prompts.py +870 -0
- src/htcli/utils/__init__.py +76 -0
- src/htcli/utils/blockchain/__init__.py +75 -0
- src/htcli/utils/blockchain/formatting.py +368 -0
- src/htcli/utils/blockchain/patches.py +286 -0
- src/htcli/utils/blockchain/peer_id.py +186 -0
- src/htcli/utils/blockchain/staking.py +448 -0
- src/htcli/utils/blockchain/type_registry.py +1373 -0
- src/htcli/utils/blockchain/validation.py +179 -0
- src/htcli/utils/cache.py +613 -0
- src/htcli/utils/constants.py +38 -0
- src/htcli/utils/legacy/__init__.py +12 -0
- src/htcli/utils/legacy/colors.py +311 -0
- src/htcli/utils/legacy/crypto.py +1176 -0
- src/htcli/utils/legacy/formatting.py +452 -0
- src/htcli/utils/legacy/interactive.py +306 -0
- src/htcli/utils/legacy/subnet_manifest.py +265 -0
- src/htcli/utils/legacy/validation.py +488 -0
- src/htcli/utils/logging.py +183 -0
- src/htcli/utils/network/__init__.py +20 -0
- src/htcli/utils/network/subnet.py +344 -0
- src/htcli/utils/prompts.py +27 -0
- src/htcli/utils/scale_codec.py +155 -0
- src/htcli/utils/validation/__init__.py +57 -0
- src/htcli/utils/validation/prompt_validators.py +267 -0
- src/htcli/utils/wallet/__init__.py +65 -0
- src/htcli/utils/wallet/auth.py +151 -0
- src/htcli/utils/wallet/core.py +1069 -0
- src/htcli/utils/wallet/crypto.py +1615 -0
- src/htcli/utils/wallet/migration.py +159 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration management commands for the Hypertensor CLI.
|
|
3
|
+
|
|
4
|
+
Following the 3-step command pattern:
|
|
5
|
+
1. Prompts - Collect user input
|
|
6
|
+
2. Handlers - Execute business logic
|
|
7
|
+
3. Display - Format and show results
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
import typer
|
|
13
|
+
|
|
14
|
+
from .handlers import (
|
|
15
|
+
edit_handler,
|
|
16
|
+
get_handler,
|
|
17
|
+
init_handler,
|
|
18
|
+
path_handler,
|
|
19
|
+
set_handler,
|
|
20
|
+
show_handler,
|
|
21
|
+
validate_handler,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
app = typer.Typer(name="config", help="Configuration management")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@app.command()
|
|
28
|
+
def init(
|
|
29
|
+
config_file: Optional[str] = typer.Option(
|
|
30
|
+
None, "--config", "-c", help="Custom configuration file path"
|
|
31
|
+
),
|
|
32
|
+
force: bool = typer.Option(
|
|
33
|
+
False, "--force", "-f", help="Overwrite existing configuration"
|
|
34
|
+
),
|
|
35
|
+
endpoint: Optional[str] = typer.Option(
|
|
36
|
+
None, "--endpoint", "-e", help="RPC endpoint URL"
|
|
37
|
+
),
|
|
38
|
+
ws_endpoint: Optional[str] = typer.Option(
|
|
39
|
+
None, "--ws-endpoint", "-w", help="WebSocket endpoint URL"
|
|
40
|
+
),
|
|
41
|
+
timeout: Optional[int] = typer.Option(
|
|
42
|
+
None, "--timeout", "-t", help="Connection timeout in seconds"
|
|
43
|
+
),
|
|
44
|
+
retry_attempts: Optional[int] = typer.Option(
|
|
45
|
+
None, "--retry-attempts", "-r", help="Number of retry attempts"
|
|
46
|
+
),
|
|
47
|
+
output_format: Optional[str] = typer.Option(
|
|
48
|
+
None, "--output-format", "-o", help="Default output format (table/json/csv)"
|
|
49
|
+
),
|
|
50
|
+
verbose: Optional[bool] = typer.Option(
|
|
51
|
+
None, "--verbose/--no-verbose", help="Enable verbose output"
|
|
52
|
+
),
|
|
53
|
+
color: Optional[bool] = typer.Option(
|
|
54
|
+
None, "--color/--no-color", help="Enable colored output"
|
|
55
|
+
),
|
|
56
|
+
wallet_path: Optional[str] = typer.Option(
|
|
57
|
+
None, "--wallet-path", "-p", help="Wallet storage path"
|
|
58
|
+
),
|
|
59
|
+
default_wallet: Optional[str] = typer.Option(
|
|
60
|
+
None, "--default-wallet", "-d", help="Default wallet name"
|
|
61
|
+
),
|
|
62
|
+
encryption_enabled: Optional[bool] = typer.Option(
|
|
63
|
+
None, "--encryption/--no-encryption", help="Enable wallet encryption"
|
|
64
|
+
),
|
|
65
|
+
):
|
|
66
|
+
"""Initialize Hypertensor CLI configuration interactively."""
|
|
67
|
+
init_handler(
|
|
68
|
+
config_file=config_file,
|
|
69
|
+
force=force,
|
|
70
|
+
endpoint=endpoint,
|
|
71
|
+
ws_endpoint=ws_endpoint,
|
|
72
|
+
timeout=timeout,
|
|
73
|
+
retry_attempts=retry_attempts,
|
|
74
|
+
output_format=output_format,
|
|
75
|
+
verbose=verbose,
|
|
76
|
+
color=color,
|
|
77
|
+
wallet_path=wallet_path,
|
|
78
|
+
default_wallet=default_wallet,
|
|
79
|
+
encryption_enabled=encryption_enabled,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@app.command()
|
|
84
|
+
def show(
|
|
85
|
+
config_file: Optional[str] = typer.Option(
|
|
86
|
+
None, "--config", "-c", help="Custom configuration file path"
|
|
87
|
+
),
|
|
88
|
+
format_type: str = typer.Option(
|
|
89
|
+
"table", "--format", "-f", help="Output format (table/yaml/json)"
|
|
90
|
+
),
|
|
91
|
+
):
|
|
92
|
+
"""Show current configuration."""
|
|
93
|
+
show_handler(config_file=config_file, format_type=format_type)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@app.command()
|
|
97
|
+
def path(
|
|
98
|
+
config_file: Optional[str] = typer.Option(
|
|
99
|
+
None, "--config", "-c", help="Custom configuration file path"
|
|
100
|
+
),
|
|
101
|
+
):
|
|
102
|
+
"""Show configuration file path."""
|
|
103
|
+
path_handler(config_file=config_file)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@app.command()
|
|
107
|
+
def edit(
|
|
108
|
+
config_file: Optional[str] = typer.Option(
|
|
109
|
+
None, "--config", "-c", help="Custom configuration file path"
|
|
110
|
+
),
|
|
111
|
+
):
|
|
112
|
+
"""Edit configuration interactively in the terminal."""
|
|
113
|
+
edit_handler(config_file=config_file)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@app.command()
|
|
117
|
+
def validate(
|
|
118
|
+
config_file: Optional[str] = typer.Option(
|
|
119
|
+
None, "--config", "-c", help="Custom configuration file path"
|
|
120
|
+
),
|
|
121
|
+
):
|
|
122
|
+
"""Validate configuration file."""
|
|
123
|
+
validate_handler(config_file=config_file)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@app.command()
|
|
127
|
+
def set(
|
|
128
|
+
key: Optional[str] = typer.Option(
|
|
129
|
+
None,
|
|
130
|
+
"--key",
|
|
131
|
+
"-k",
|
|
132
|
+
help="Configuration key (e.g., 'network.endpoint'). If omitted, you can select interactively.",
|
|
133
|
+
),
|
|
134
|
+
value: Optional[str] = typer.Option(
|
|
135
|
+
None,
|
|
136
|
+
"--value",
|
|
137
|
+
"-v",
|
|
138
|
+
help="Value to set. If omitted, you will be prompted to enter a value.",
|
|
139
|
+
),
|
|
140
|
+
config_file: Optional[str] = typer.Option(
|
|
141
|
+
None, "--config-file", "-c", help="Custom configuration file path"
|
|
142
|
+
),
|
|
143
|
+
):
|
|
144
|
+
"""Set a specific configuration value."""
|
|
145
|
+
set_handler(key=key, value=value, config_file=config_file)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@app.command()
|
|
149
|
+
def get(
|
|
150
|
+
key: Optional[str] = typer.Option(
|
|
151
|
+
None, "--key", "-k", help="Configuration key (e.g., 'network.endpoint'). If omitted, you can select interactively."
|
|
152
|
+
),
|
|
153
|
+
config_file: Optional[str] = typer.Option(
|
|
154
|
+
None, "--config-file", "-c", help="Custom configuration file path"
|
|
155
|
+
),
|
|
156
|
+
):
|
|
157
|
+
"""Get a specific configuration value."""
|
|
158
|
+
get_handler(key=key, config_file=config_file)
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Config command display logic.
|
|
3
|
+
|
|
4
|
+
Handles formatting and displaying results for configuration operations using HTCLI UI components.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from ...models.responses import (
|
|
10
|
+
ConfigGetResponse,
|
|
11
|
+
ConfigInitResponse,
|
|
12
|
+
ConfigPathResponse,
|
|
13
|
+
ConfigSetResponse,
|
|
14
|
+
ConfigShowResponse,
|
|
15
|
+
ConfigValidateResponse,
|
|
16
|
+
)
|
|
17
|
+
from ...ui.colors import error, info, primary, success, warning
|
|
18
|
+
from ...ui.components import HTCLIPanel, HTCLITable
|
|
19
|
+
from ...ui.display import HTCLIConsole
|
|
20
|
+
|
|
21
|
+
console = HTCLIConsole()
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def display_config_init_result(response: ConfigInitResponse) -> None:
|
|
25
|
+
"""Display configuration initialization results."""
|
|
26
|
+
if response.created:
|
|
27
|
+
console.print(success("✅ Configuration created successfully!"))
|
|
28
|
+
else:
|
|
29
|
+
console.print(success("✅ Configuration updated successfully!"))
|
|
30
|
+
|
|
31
|
+
console.print()
|
|
32
|
+
console.print(f"[bold]Configuration file:[/bold] {response.config_path}")
|
|
33
|
+
console.print(f"[bold]Status:[/bold] {response.message}")
|
|
34
|
+
|
|
35
|
+
if response.created:
|
|
36
|
+
console.print()
|
|
37
|
+
console.print(info("💡 Next steps:"))
|
|
38
|
+
console.print(" • Use 'htcli config show' to view your configuration")
|
|
39
|
+
console.print(" • Use 'htcli config edit' to modify settings")
|
|
40
|
+
console.print(" • Use 'htcli wallet list' to check your wallets")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def display_config_show_result(response: ConfigShowResponse, format_type: str) -> None:
|
|
44
|
+
"""Display configuration show results."""
|
|
45
|
+
console.print(f"[bold]Configuration file:[/bold] {response.config_path}")
|
|
46
|
+
console.print()
|
|
47
|
+
|
|
48
|
+
if not response.exists:
|
|
49
|
+
console.print(error("❌ Configuration file not found"))
|
|
50
|
+
console.print(info("💡 Run 'htcli config init' to create a configuration file"))
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
if format_type == "json":
|
|
54
|
+
console.print_json(data=response.config_data)
|
|
55
|
+
elif format_type == "yaml":
|
|
56
|
+
_display_config_as_yaml(response.config_data)
|
|
57
|
+
else: # table format
|
|
58
|
+
_display_config_as_table(response.config_data)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _display_config_as_table(config_data: dict[str, Any]) -> None:
|
|
62
|
+
"""Display configuration as formatted tables."""
|
|
63
|
+
# Network configuration table
|
|
64
|
+
if "network" in config_data:
|
|
65
|
+
network_table = HTCLITable(
|
|
66
|
+
title="[bold #60A5FA]🌐 Network Configuration[/bold #60A5FA]",
|
|
67
|
+
border_style="#60A5FA",
|
|
68
|
+
header_style="#60A5FA",
|
|
69
|
+
)
|
|
70
|
+
network_table.add_column("Setting", style="bold #60A5FA", width=25)
|
|
71
|
+
network_table.add_column("Value", width=50)
|
|
72
|
+
|
|
73
|
+
network = config_data["network"]
|
|
74
|
+
# Display all fields from default_config
|
|
75
|
+
# Alternate Value column colors: GRAY_200, GRAY_300, GRAY_200, GRAY_300
|
|
76
|
+
network_table.add_row(
|
|
77
|
+
"RPC Endpoint", f"[#E5E7EB]{network.get('endpoint', 'Not set')}[/]"
|
|
78
|
+
)
|
|
79
|
+
network_table.add_row(
|
|
80
|
+
"WebSocket Endpoint", f"[#D1D5DB]{network.get('ws_endpoint', 'Not set')}[/]"
|
|
81
|
+
)
|
|
82
|
+
network_table.add_row(
|
|
83
|
+
"Timeout", f"[#E5E7EB]{network.get('timeout', 'Not set')}s[/]"
|
|
84
|
+
)
|
|
85
|
+
network_table.add_row(
|
|
86
|
+
"Retry Attempts", f"[#D1D5DB]{network.get('retry_attempts', 'Not set')}[/]"
|
|
87
|
+
)
|
|
88
|
+
network_table.add_row(
|
|
89
|
+
"Chain Name", f"[#E5E7EB]{network.get('chain', 'Not set')}[/]"
|
|
90
|
+
)
|
|
91
|
+
network_table.render()
|
|
92
|
+
console.print() # Add spacing between tables
|
|
93
|
+
|
|
94
|
+
# Output configuration table
|
|
95
|
+
if "output" in config_data:
|
|
96
|
+
output_table = HTCLITable(
|
|
97
|
+
title="[bold #34D399]🎨 Output Configuration[/bold #34D399]",
|
|
98
|
+
border_style="#34D399",
|
|
99
|
+
header_style="#34D399",
|
|
100
|
+
)
|
|
101
|
+
output_table.add_column("Setting", style="bold #34D399", width=25)
|
|
102
|
+
output_table.add_column("Value", width=50)
|
|
103
|
+
|
|
104
|
+
output = config_data["output"]
|
|
105
|
+
# Only display fields that are prompted during config init
|
|
106
|
+
# Alternate Value column colors: GRAY_200, GRAY_300, GRAY_200, GRAY_300
|
|
107
|
+
output_table.add_row(
|
|
108
|
+
"Default Format", f"[#E5E7EB]{output.get('format', 'Not set')}[/]"
|
|
109
|
+
)
|
|
110
|
+
output_table.add_row(
|
|
111
|
+
"Verbose",
|
|
112
|
+
f"[#D1D5DB]{'Enabled' if output.get('verbose') else 'Disabled'}[/]",
|
|
113
|
+
)
|
|
114
|
+
output_table.add_row(
|
|
115
|
+
"Colors",
|
|
116
|
+
f"[#E5E7EB]{'Enabled' if output.get('color') else 'Disabled'}[/]",
|
|
117
|
+
)
|
|
118
|
+
output_table.render()
|
|
119
|
+
console.print() # Add spacing between tables
|
|
120
|
+
# Legacy display section support (backward compatibility)
|
|
121
|
+
elif "display" in config_data:
|
|
122
|
+
display_table = HTCLITable(
|
|
123
|
+
title="[bold #34D399]🎨 Display Configuration[/bold #34D399]",
|
|
124
|
+
border_style="#34D399",
|
|
125
|
+
header_style="#34D399",
|
|
126
|
+
)
|
|
127
|
+
display_table.add_column("Setting", style="bold #34D399", width=25)
|
|
128
|
+
display_table.add_column("Value", width=50)
|
|
129
|
+
|
|
130
|
+
display = config_data["display"]
|
|
131
|
+
# Alternate Value column colors: GRAY_200, GRAY_300, GRAY_200, GRAY_300
|
|
132
|
+
display_table.add_row(
|
|
133
|
+
"Default Format", f"[#E5E7EB]{display.get('format', 'Not set')}[/]"
|
|
134
|
+
)
|
|
135
|
+
display_table.add_row(
|
|
136
|
+
"Verbose",
|
|
137
|
+
f"[#D1D5DB]{'Enabled' if display.get('verbose') else 'Disabled'}[/]",
|
|
138
|
+
)
|
|
139
|
+
display_table.add_row(
|
|
140
|
+
"Colors",
|
|
141
|
+
f"[#E5E7EB]{'Enabled' if display.get('colors') else 'Disabled'}[/]",
|
|
142
|
+
)
|
|
143
|
+
display_table.add_row(
|
|
144
|
+
"Show Guidance",
|
|
145
|
+
f"[#D1D5DB]{'Enabled' if display.get('show_guidance') else 'Disabled'}[/]",
|
|
146
|
+
)
|
|
147
|
+
display_table.render()
|
|
148
|
+
console.print() # Add spacing between tables
|
|
149
|
+
|
|
150
|
+
# Wallet configuration table
|
|
151
|
+
if "wallet" in config_data:
|
|
152
|
+
wallet_table = HTCLITable(
|
|
153
|
+
title="[bold #FBBF24]💰 Wallet Configuration[/bold #FBBF24]",
|
|
154
|
+
border_style="#FBBF24",
|
|
155
|
+
header_style="#FBBF24",
|
|
156
|
+
)
|
|
157
|
+
wallet_table.add_column("Setting", style="bold #FBBF24", width=25)
|
|
158
|
+
wallet_table.add_column("Value", width=50)
|
|
159
|
+
|
|
160
|
+
wallet = config_data["wallet"]
|
|
161
|
+
# Only display fields that are prompted during config init
|
|
162
|
+
# Alternate Value column colors: GRAY_200, GRAY_300, GRAY_200
|
|
163
|
+
wallet_table.add_row(
|
|
164
|
+
"Wallet Path", f"[#E5E7EB]{wallet.get('path', 'Not set')}[/]"
|
|
165
|
+
)
|
|
166
|
+
wallet_table.add_row(
|
|
167
|
+
"Default Wallet", f"[#D1D5DB]{wallet.get('default_name', wallet.get('default_wallet', 'Not set'))}[/]"
|
|
168
|
+
)
|
|
169
|
+
wallet_table.add_row(
|
|
170
|
+
"Encryption Enabled",
|
|
171
|
+
f"[#E5E7EB]{'Enabled' if wallet.get('encryption_enabled') else 'Disabled'}[/]",
|
|
172
|
+
)
|
|
173
|
+
wallet_table.render()
|
|
174
|
+
console.print() # Add spacing between tables
|
|
175
|
+
|
|
176
|
+
# Security configuration table (legacy support for old configs)
|
|
177
|
+
if "security" in config_data:
|
|
178
|
+
security_table = HTCLITable(
|
|
179
|
+
title="[bold #F87171]🔒 Security Configuration[/bold #F87171]",
|
|
180
|
+
border_style="#F87171",
|
|
181
|
+
header_style="#F87171",
|
|
182
|
+
)
|
|
183
|
+
security_table.add_column("Setting", style="bold #F87171", width=25)
|
|
184
|
+
security_table.add_column("Value", width=50)
|
|
185
|
+
|
|
186
|
+
security = config_data["security"]
|
|
187
|
+
# Alternate Value column colors: GRAY_200, GRAY_300, GRAY_200
|
|
188
|
+
security_table.add_row(
|
|
189
|
+
"Password Timeout",
|
|
190
|
+
f"[#E5E7EB]{security.get('password_timeout', 'Not set')}s[/]",
|
|
191
|
+
)
|
|
192
|
+
security_table.add_row(
|
|
193
|
+
"Require Confirmation",
|
|
194
|
+
f"[#D1D5DB]{'Enabled' if security.get('require_confirmation') else 'Disabled'}[/]",
|
|
195
|
+
)
|
|
196
|
+
security_table.add_row(
|
|
197
|
+
"Log Transactions",
|
|
198
|
+
f"[#E5E7EB]{'Enabled' if security.get('log_transactions') else 'Disabled'}[/]",
|
|
199
|
+
)
|
|
200
|
+
security_table.render()
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def _display_config_as_yaml(config_data: dict[str, Any]) -> None:
|
|
204
|
+
"""Display configuration as formatted YAML."""
|
|
205
|
+
import yaml
|
|
206
|
+
|
|
207
|
+
# Format as YAML with comments
|
|
208
|
+
yaml_content = yaml.dump(
|
|
209
|
+
config_data, default_flow_style=False, indent=2, sort_keys=True
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# Add syntax highlighting if possible
|
|
213
|
+
try:
|
|
214
|
+
from rich.syntax import Syntax
|
|
215
|
+
|
|
216
|
+
syntax = Syntax(yaml_content, "yaml", theme="monokai", line_numbers=True)
|
|
217
|
+
console.print(syntax)
|
|
218
|
+
except ImportError:
|
|
219
|
+
console.print(yaml_content)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def display_config_set_result(response: ConfigSetResponse) -> None:
|
|
223
|
+
"""Display configuration set results."""
|
|
224
|
+
console.print(success(f"✅ Configuration updated: {response.key}"))
|
|
225
|
+
console.print()
|
|
226
|
+
|
|
227
|
+
# Create comparison table
|
|
228
|
+
table = HTCLITable(title="Configuration Change")
|
|
229
|
+
table.add_column("Key", style="htcli.value")
|
|
230
|
+
table.add_column("Old Value", style="htcli.error")
|
|
231
|
+
table.add_column("New Value", style="htcli.success")
|
|
232
|
+
|
|
233
|
+
table.add_row(response.key, str(response.old_value), str(response.new_value))
|
|
234
|
+
|
|
235
|
+
table.render()
|
|
236
|
+
|
|
237
|
+
console.print()
|
|
238
|
+
console.print(f"[bold]Configuration saved to:[/bold] {response.config_path}")
|
|
239
|
+
console.print(f"[bold]Status:[/bold] {response.message}")
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def display_config_get_result(response: ConfigGetResponse) -> None:
|
|
243
|
+
"""Display configuration get results."""
|
|
244
|
+
panel = HTCLIPanel(
|
|
245
|
+
f"[bold #60A5FA]Configuration Value[/bold #60A5FA]\n\n"
|
|
246
|
+
f"[bold]Key:[/bold] {response.key}\n"
|
|
247
|
+
f"[bold]Type:[/bold] {response.value_type}\n"
|
|
248
|
+
f"[bold]Value:[/bold] {response.value}\n\n"
|
|
249
|
+
f"{info('💡 Tip:')} Use 'htcli config set --key {response.key} --value <new_value>' to change this value",
|
|
250
|
+
title="Configuration Get",
|
|
251
|
+
)
|
|
252
|
+
panel.render()
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def display_config_validate_result(response: ConfigValidateResponse) -> None:
|
|
256
|
+
"""Display configuration validation results."""
|
|
257
|
+
if response.valid:
|
|
258
|
+
console.print(success("✅ Configuration file is valid!"))
|
|
259
|
+
console.print(
|
|
260
|
+
f"Configuration loaded successfully from: [bold]{response.config_path}[/bold]"
|
|
261
|
+
)
|
|
262
|
+
else:
|
|
263
|
+
console.print(error("❌ Configuration file is invalid!"))
|
|
264
|
+
console.print()
|
|
265
|
+
|
|
266
|
+
if response.errors:
|
|
267
|
+
console.print(error("Validation errors:"))
|
|
268
|
+
for error_msg in response.errors:
|
|
269
|
+
console.print(f" • {error_msg}")
|
|
270
|
+
|
|
271
|
+
console.print()
|
|
272
|
+
console.print(f"[bold]Status:[/bold] {response.message}")
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def display_config_path_result(response: ConfigPathResponse) -> None:
|
|
276
|
+
"""Display configuration path results."""
|
|
277
|
+
console.print(f"Configuration file path: [bold]{response.config_path}[/bold]")
|
|
278
|
+
console.print(f"Absolute path: [bold]{response.absolute_path}[/bold]")
|
|
279
|
+
|
|
280
|
+
if response.exists:
|
|
281
|
+
console.print(success("✅ File exists"))
|
|
282
|
+
else:
|
|
283
|
+
console.print(warning("⚠️ File does not exist"))
|
|
284
|
+
console.print()
|
|
285
|
+
console.print(
|
|
286
|
+
info("💡 Run 'htcli config init' to create the configuration file")
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def display_config_changes_summary(
|
|
291
|
+
old_config: dict[str, Any], new_config: dict[str, Any]
|
|
292
|
+
) -> None:
|
|
293
|
+
"""Display configuration changes summary."""
|
|
294
|
+
console.print(primary("📋 Configuration Changes Summary"))
|
|
295
|
+
console.print()
|
|
296
|
+
|
|
297
|
+
changes_found = False
|
|
298
|
+
|
|
299
|
+
# Check network changes
|
|
300
|
+
if "network" in old_config and "network" in new_config:
|
|
301
|
+
network_changes = _get_section_changes(
|
|
302
|
+
"Network", old_config["network"], new_config["network"]
|
|
303
|
+
)
|
|
304
|
+
if network_changes:
|
|
305
|
+
changes_found = True
|
|
306
|
+
network_changes.render()
|
|
307
|
+
|
|
308
|
+
# Check output changes
|
|
309
|
+
if "output" in old_config and "output" in new_config:
|
|
310
|
+
output_changes = _get_section_changes(
|
|
311
|
+
"Output", old_config["output"], new_config["output"]
|
|
312
|
+
)
|
|
313
|
+
if output_changes:
|
|
314
|
+
changes_found = True
|
|
315
|
+
output_changes.render()
|
|
316
|
+
|
|
317
|
+
# Check wallet changes
|
|
318
|
+
if "wallet" in old_config and "wallet" in new_config:
|
|
319
|
+
wallet_changes = _get_section_changes(
|
|
320
|
+
"Wallet", old_config["wallet"], new_config["wallet"]
|
|
321
|
+
)
|
|
322
|
+
if wallet_changes:
|
|
323
|
+
changes_found = True
|
|
324
|
+
wallet_changes.render()
|
|
325
|
+
|
|
326
|
+
if not changes_found:
|
|
327
|
+
console.print(info("No changes detected"))
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def _get_section_changes(
|
|
331
|
+
section_name: str, old_section: dict[str, Any], new_section: dict[str, Any]
|
|
332
|
+
) -> HTCLITable:
|
|
333
|
+
"""Get changes for a configuration section."""
|
|
334
|
+
table = HTCLITable(title=f"{section_name} Configuration Changes")
|
|
335
|
+
table.add_column("Setting", style="htcli.value")
|
|
336
|
+
table.add_column("Old Value", style="htcli.error")
|
|
337
|
+
table.add_column("New Value", style="htcli.success")
|
|
338
|
+
table.add_column("Changed", style="htcli.warning")
|
|
339
|
+
|
|
340
|
+
has_changes = False
|
|
341
|
+
for key in set(old_section.keys()) | set(new_section.keys()):
|
|
342
|
+
old_value = old_section.get(key, "Not set")
|
|
343
|
+
new_value = new_section.get(key, "Not set")
|
|
344
|
+
changed = "Yes" if old_value != new_value else "No"
|
|
345
|
+
|
|
346
|
+
if changed == "Yes":
|
|
347
|
+
has_changes = True
|
|
348
|
+
|
|
349
|
+
table.add_row(
|
|
350
|
+
key.title().replace("_", " "), str(old_value), str(new_value), changed
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
return table if has_changes else None
|