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,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
+