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,159 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Wallet layout migration utilities.
|
|
3
|
+
|
|
4
|
+
Used by both the CLI command (`htcli wallet upgrade`) and the standalone helper
|
|
5
|
+
script in `scripts/migrate_wallet_layout.py`.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import shutil
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Callable, Iterable, Optional
|
|
15
|
+
|
|
16
|
+
from .crypto import (
|
|
17
|
+
COLDKEY_FILE_SUFFIX,
|
|
18
|
+
HOTKEY_FILE_SUFFIX,
|
|
19
|
+
get_wallet_directory,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
LogFn = Optional[Callable[[str], None]]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _load_json(path: Path) -> Optional[dict]:
|
|
26
|
+
try:
|
|
27
|
+
with open(path) as f:
|
|
28
|
+
return json.load(f)
|
|
29
|
+
except Exception:
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _ensure_backup(path: Path, backup_enabled: bool):
|
|
34
|
+
if not backup_enabled:
|
|
35
|
+
return
|
|
36
|
+
backup_path = path.with_suffix(path.suffix + ".bak")
|
|
37
|
+
if not backup_path.exists():
|
|
38
|
+
shutil.copy2(path, backup_path)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class MigrationReport:
|
|
43
|
+
migrated: list[str] = field(default_factory=list)
|
|
44
|
+
skipped: list[str] = field(default_factory=list)
|
|
45
|
+
warnings: list[str] = field(default_factory=list)
|
|
46
|
+
|
|
47
|
+
def as_dict(self) -> dict:
|
|
48
|
+
return {
|
|
49
|
+
"migrated": self.migrated,
|
|
50
|
+
"skipped": self.skipped,
|
|
51
|
+
"warnings": self.warnings,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def migrate_wallet_layout(
|
|
56
|
+
wallet_dir: Optional[Path] = None,
|
|
57
|
+
*,
|
|
58
|
+
dry_run: bool = False,
|
|
59
|
+
force: bool = False,
|
|
60
|
+
backup: bool = True,
|
|
61
|
+
only_wallets: Optional[Iterable[str]] = None,
|
|
62
|
+
log: LogFn = None,
|
|
63
|
+
) -> MigrationReport:
|
|
64
|
+
"""Migrate flat wallet files into the hierarchical layout."""
|
|
65
|
+
|
|
66
|
+
def emit(message: str):
|
|
67
|
+
if log:
|
|
68
|
+
log(message)
|
|
69
|
+
|
|
70
|
+
target_dir = (wallet_dir or get_wallet_directory()).expanduser()
|
|
71
|
+
report = MigrationReport()
|
|
72
|
+
|
|
73
|
+
if not target_dir.exists():
|
|
74
|
+
warning = f"Wallet directory '{target_dir}' does not exist."
|
|
75
|
+
report.warnings.append(warning)
|
|
76
|
+
emit(f"[yellow]{warning}[/yellow]")
|
|
77
|
+
return report
|
|
78
|
+
|
|
79
|
+
selected = {name for name in only_wallets} if only_wallets else None
|
|
80
|
+
|
|
81
|
+
legacy_coldkeys = sorted(target_dir.glob(f"*{COLDKEY_FILE_SUFFIX}"))
|
|
82
|
+
legacy_hotkeys = sorted(target_dir.glob(f"*{HOTKEY_FILE_SUFFIX}"))
|
|
83
|
+
coldkey_address_map: dict[str, str] = {}
|
|
84
|
+
|
|
85
|
+
for coldkey_file in legacy_coldkeys:
|
|
86
|
+
data = _load_json(coldkey_file)
|
|
87
|
+
if not data:
|
|
88
|
+
warning = f"Unable to read coldkey file '{coldkey_file.name}', skipping."
|
|
89
|
+
report.warnings.append(warning)
|
|
90
|
+
emit(f"[yellow]{warning}[/yellow]")
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
coldkey_name = data.get("name") or coldkey_file.stem.replace(
|
|
94
|
+
COLDKEY_FILE_SUFFIX, ""
|
|
95
|
+
)
|
|
96
|
+
if selected and coldkey_name not in selected:
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
coldkey_address = data.get("ss58_address") or data.get("address")
|
|
100
|
+
if coldkey_address:
|
|
101
|
+
coldkey_address_map[coldkey_address] = coldkey_name
|
|
102
|
+
|
|
103
|
+
target = target_dir / coldkey_name / coldkey_file.name
|
|
104
|
+
if target.exists() and not force:
|
|
105
|
+
msg = f"Target coldkey '{target}' exists. Use --force to overwrite."
|
|
106
|
+
report.skipped.append(str(target))
|
|
107
|
+
emit(f"[cyan]{msg}[/cyan]")
|
|
108
|
+
continue
|
|
109
|
+
|
|
110
|
+
emit(f"[green]Move[/green] {coldkey_file.name} -> {target}")
|
|
111
|
+
report.migrated.append(f"{coldkey_file} -> {target}")
|
|
112
|
+
if dry_run:
|
|
113
|
+
continue
|
|
114
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
115
|
+
_ensure_backup(coldkey_file, backup)
|
|
116
|
+
shutil.move(str(coldkey_file), target)
|
|
117
|
+
|
|
118
|
+
for hotkey_file in legacy_hotkeys:
|
|
119
|
+
data = _load_json(hotkey_file)
|
|
120
|
+
if not data:
|
|
121
|
+
warning = f"Unable to read hotkey file '{hotkey_file.name}', skipping."
|
|
122
|
+
report.warnings.append(warning)
|
|
123
|
+
emit(f"[yellow]{warning}[/yellow]")
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
owner_address = data.get("owner_address")
|
|
127
|
+
coldkey_name = coldkey_address_map.get(owner_address)
|
|
128
|
+
if selected and coldkey_name and coldkey_name not in selected:
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
if not coldkey_name:
|
|
132
|
+
warning = (
|
|
133
|
+
f"Cannot resolve coldkey for hotkey '{hotkey_file.name}'. "
|
|
134
|
+
"Ensure the coldkey is migrated first."
|
|
135
|
+
)
|
|
136
|
+
report.warnings.append(warning)
|
|
137
|
+
emit(f"[yellow]{warning}[/yellow]")
|
|
138
|
+
continue
|
|
139
|
+
|
|
140
|
+
target = target_dir / coldkey_name / "hotkeys" / hotkey_file.name
|
|
141
|
+
if target.exists() and not force:
|
|
142
|
+
msg = f"Target hotkey '{target}' exists. Use --force to overwrite."
|
|
143
|
+
report.skipped.append(str(target))
|
|
144
|
+
emit(f"[cyan]{msg}[/cyan]")
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
emit(f"[green]Move[/green] {hotkey_file.name} -> {target}")
|
|
148
|
+
report.migrated.append(f"{hotkey_file} -> {target}")
|
|
149
|
+
if dry_run:
|
|
150
|
+
continue
|
|
151
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
152
|
+
_ensure_backup(hotkey_file, backup)
|
|
153
|
+
shutil.move(str(hotkey_file), target)
|
|
154
|
+
|
|
155
|
+
if not report.migrated and not report.skipped and not report.warnings:
|
|
156
|
+
emit("[cyan]No legacy wallet files found. Nothing to do.[/cyan]")
|
|
157
|
+
|
|
158
|
+
return report
|
|
159
|
+
|