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,179 @@
1
+ """
2
+ Blockchain validation utilities with EVM/ECDSA focus.
3
+ Validates addresses, amounts, and other blockchain-related inputs.
4
+ """
5
+
6
+ import re
7
+ from pathlib import Path
8
+ from typing import Optional, Union
9
+
10
+
11
+ def validate_address(address: str) -> bool:
12
+ """Validate an EVM/Ethereum address format."""
13
+ if not address:
14
+ return False
15
+ if address.startswith("0x") and len(address) == 42:
16
+ try:
17
+ int(address[2:], 16)
18
+ return True
19
+ except ValueError:
20
+ return False
21
+ return False
22
+
23
+
24
+ def validate_ethereum_address(address: str) -> bool:
25
+ """Validate Ethereum address format (alias for validate_address)."""
26
+ return validate_address(address)
27
+
28
+
29
+ def validate_hotkey_address(address: str) -> bool:
30
+ """Validate hotkey address - should be Bytes20 format for EVM compatibility."""
31
+ return validate_ethereum_address(address)
32
+
33
+
34
+ def validate_amount(amount: Union[str, float, int]) -> bool:
35
+ """Validate a token amount."""
36
+ try:
37
+ if isinstance(amount, str):
38
+ amount = float(amount)
39
+ return isinstance(amount, (int, float)) and amount > 0
40
+ except (ValueError, TypeError):
41
+ return False
42
+
43
+
44
+ def validate_subnet_id(subnet_id: Union[str, int]) -> bool:
45
+ """Validate a subnet ID."""
46
+ try:
47
+ if isinstance(subnet_id, str):
48
+ subnet_id = int(subnet_id)
49
+ return isinstance(subnet_id, int) and subnet_id >= 0
50
+ except (ValueError, TypeError):
51
+ return False
52
+
53
+
54
+ def validate_node_id(node_id: Union[str, int]) -> bool:
55
+ """Validate a node ID."""
56
+ try:
57
+ if isinstance(node_id, str):
58
+ node_id = int(node_id)
59
+ return isinstance(node_id, int) and node_id >= 0
60
+ except (ValueError, TypeError):
61
+ return False
62
+
63
+
64
+ def validate_peer_id(peer_id: str) -> bool:
65
+ """Validate a peer ID format."""
66
+ if not peer_id or not isinstance(peer_id, str):
67
+ return False
68
+ valid_prefixes = ["12D3KooW", "Qm", "1"]
69
+ return any(peer_id.startswith(prefix) for prefix in valid_prefixes)
70
+
71
+
72
+ def validate_key_type(key_type: str) -> bool:
73
+ """Validate cryptographic key type."""
74
+ valid_types = ["ecdsa", "secp256k1", "sr25519", "ed25519"]
75
+ return key_type.lower() in valid_types
76
+
77
+
78
+ def validate_password(password: Optional[str]) -> bool:
79
+ """Validate password strength."""
80
+ if password is None:
81
+ return True
82
+ if not isinstance(password, str) or len(password) < 8:
83
+ return False
84
+ return True
85
+
86
+
87
+ def validate_file_path(file_path: str) -> bool:
88
+ """Validate file path format and accessibility."""
89
+ try:
90
+ path = Path(file_path)
91
+ if not str(path):
92
+ return False
93
+ parent = path.parent
94
+ return parent.exists() or parent == Path(".")
95
+ except Exception:
96
+ return False
97
+
98
+
99
+ def validate_wallet_name(wallet_name: str) -> bool:
100
+ """Validate wallet name format."""
101
+ if not wallet_name or not isinstance(wallet_name, str):
102
+ return False
103
+ pattern = r"^[a-zA-Z0-9_-]+$"
104
+ if not re.match(pattern, wallet_name):
105
+ return False
106
+ if len(wallet_name) < 1 or len(wallet_name) > 64:
107
+ return False
108
+ if wallet_name.startswith(("-", "_")) or wallet_name.endswith(("-", "_")):
109
+ return False
110
+ return True
111
+
112
+
113
+ def validate_network_url(url: str) -> bool:
114
+ """Validate network URL format."""
115
+ if not url or not isinstance(url, str):
116
+ return False
117
+ valid_schemes = ["ws://", "wss://", "http://", "https://"]
118
+ return any(url.startswith(scheme) for scheme in valid_schemes)
119
+
120
+
121
+ def validate_hex_string(hex_str: str, expected_length: Optional[int] = None) -> bool:
122
+ """Validate hexadecimal string format."""
123
+ if not hex_str or not isinstance(hex_str, str):
124
+ return False
125
+ if hex_str.startswith("0x"):
126
+ hex_str = hex_str[2:]
127
+ try:
128
+ int(hex_str, 16)
129
+ except ValueError:
130
+ return False
131
+ if expected_length is not None:
132
+ return len(hex_str) == expected_length
133
+ return True
134
+
135
+
136
+ def validate_mnemonic(mnemonic: str) -> bool:
137
+ """Validate mnemonic phrase format."""
138
+ if not mnemonic or not isinstance(mnemonic, str):
139
+ return False
140
+ words = mnemonic.strip().split()
141
+ valid_lengths = [12, 15, 18, 21, 24]
142
+ if len(words) not in valid_lengths:
143
+ return False
144
+ for word in words:
145
+ if not re.match(r"^[a-z]+$", word):
146
+ return False
147
+ return True
148
+
149
+
150
+ def validate_tensor_amount(amount: Union[str, float, int]) -> bool:
151
+ """Validate TENSOR token amount."""
152
+ try:
153
+ from .formatting import TensorAmount
154
+
155
+ tensor_amount = TensorAmount(amount)
156
+ return tensor_amount.is_valid()
157
+ except (ValueError, TypeError):
158
+ return False
159
+
160
+
161
+ def detect_address_type(address: str) -> tuple[str, str, bool]:
162
+ """Detect the type and format of an address."""
163
+ if not address:
164
+ return "unknown", "Invalid", False
165
+ if address.startswith("0x"):
166
+ if len(address) == 42:
167
+ return "ecdsa", "EVM/ECDSA (20-byte)", True
168
+ else:
169
+ return (
170
+ "invalid_evm",
171
+ f"Invalid EVM (expected 42 chars, got {len(address)})",
172
+ False,
173
+ )
174
+ elif len(address) > 40 and address[0].isdigit():
175
+ return "ss58", "SS58/Substrate (32-byte)", False
176
+ elif len(address) < 20:
177
+ return "unknown", "Too Short", False
178
+ else:
179
+ return "unknown", "Unknown Format", False