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,714 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Governance extrinsics for HTCLI.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
from substrateinterface import Keypair, SubstrateInterface
|
|
8
|
+
|
|
9
|
+
from ...models.requests import (
|
|
10
|
+
GovernanceCollectiveRemoveOverwatchNodeRequest,
|
|
11
|
+
GovernanceCollectiveRemoveSubnetNodeRequest,
|
|
12
|
+
GovernanceCollectiveRemoveSubnetRequest,
|
|
13
|
+
GovernanceParameterUpdateRequest,
|
|
14
|
+
GovernancePauseRequest,
|
|
15
|
+
GovernanceUnpauseRequest,
|
|
16
|
+
)
|
|
17
|
+
from ...utils.logging import get_logger
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class GovernanceExtrinsics:
|
|
23
|
+
"""Client for governance-related extrinsics."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, substrate: Optional[SubstrateInterface] = None):
|
|
26
|
+
"""Initialize the governance client."""
|
|
27
|
+
self.substrate = substrate
|
|
28
|
+
|
|
29
|
+
# ============================================================================
|
|
30
|
+
# NETWORK PAUSE/UNPAUSE
|
|
31
|
+
# ============================================================================
|
|
32
|
+
|
|
33
|
+
def pause_network(
|
|
34
|
+
self, request: GovernancePauseRequest, keypair: Keypair
|
|
35
|
+
) -> dict[str, Any]:
|
|
36
|
+
"""
|
|
37
|
+
Pause the network (governance only).
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
request: Network pause request
|
|
41
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
dictionary with operation result
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
logger.info("Pausing network")
|
|
48
|
+
|
|
49
|
+
call = self.substrate.compose_call(
|
|
50
|
+
call_module="Network", call_function="pause_network", call_params={}
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
response = self._submit_extrinsic(call, keypair)
|
|
54
|
+
|
|
55
|
+
if response["success"]:
|
|
56
|
+
response["message"] = "Network paused successfully"
|
|
57
|
+
|
|
58
|
+
return response
|
|
59
|
+
|
|
60
|
+
except Exception as e:
|
|
61
|
+
logger.error(f"Error pausing network: {e}")
|
|
62
|
+
return {"success": False, "error": str(e)}
|
|
63
|
+
|
|
64
|
+
def unpause_network(
|
|
65
|
+
self, request: GovernanceUnpauseRequest, keypair: Keypair
|
|
66
|
+
) -> dict[str, Any]:
|
|
67
|
+
"""
|
|
68
|
+
Unpause the network (governance only).
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
request: Network unpause request
|
|
72
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
dictionary with operation result
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
logger.info("Unpausing network")
|
|
79
|
+
|
|
80
|
+
call = self.substrate.compose_call(
|
|
81
|
+
call_module="Network", call_function="unpause_network", call_params={}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
response = self._submit_extrinsic(call, keypair)
|
|
85
|
+
|
|
86
|
+
if response["success"]:
|
|
87
|
+
response["message"] = "Network unpaused successfully"
|
|
88
|
+
|
|
89
|
+
return response
|
|
90
|
+
|
|
91
|
+
except Exception as e:
|
|
92
|
+
logger.error(f"Error unpausing network: {e}")
|
|
93
|
+
return {"success": False, "error": str(e)}
|
|
94
|
+
|
|
95
|
+
# ============================================================================
|
|
96
|
+
# COLLECTIVE REMOVAL OPERATIONS
|
|
97
|
+
# ============================================================================
|
|
98
|
+
|
|
99
|
+
def collective_remove_subnet(
|
|
100
|
+
self, request: GovernanceCollectiveRemoveSubnetRequest, keypair: Keypair
|
|
101
|
+
) -> dict[str, Any]:
|
|
102
|
+
"""
|
|
103
|
+
Remove a subnet collectively (governance only).
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
request: Collective subnet removal request
|
|
107
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
dictionary with operation result
|
|
111
|
+
"""
|
|
112
|
+
try:
|
|
113
|
+
logger.info(f"Collectively removing subnet {request.subnet_id}")
|
|
114
|
+
|
|
115
|
+
call = self.substrate.compose_call(
|
|
116
|
+
call_module="Network",
|
|
117
|
+
call_function="collective_remove_subnet",
|
|
118
|
+
call_params={"subnet_id": request.subnet_id},
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
response = self._submit_extrinsic(call, keypair)
|
|
122
|
+
|
|
123
|
+
if response["success"]:
|
|
124
|
+
response["message"] = f"Subnet {request.subnet_id} removed collectively"
|
|
125
|
+
|
|
126
|
+
return response
|
|
127
|
+
|
|
128
|
+
except Exception as e:
|
|
129
|
+
logger.error(f"Error collectively removing subnet: {e}")
|
|
130
|
+
return {"success": False, "error": str(e)}
|
|
131
|
+
|
|
132
|
+
def collective_remove_subnet_node(
|
|
133
|
+
self, request: GovernanceCollectiveRemoveSubnetNodeRequest, keypair: Keypair
|
|
134
|
+
) -> dict[str, Any]:
|
|
135
|
+
"""
|
|
136
|
+
Remove a subnet node collectively (governance only).
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
request: Collective subnet node removal request
|
|
140
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
dictionary with operation result
|
|
144
|
+
"""
|
|
145
|
+
try:
|
|
146
|
+
logger.info(
|
|
147
|
+
f"Collectively removing subnet {request.subnet_id} node {request.subnet_node_id}"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
call = self.substrate.compose_call(
|
|
151
|
+
call_module="Network",
|
|
152
|
+
call_function="collective_remove_subnet_node",
|
|
153
|
+
call_params={
|
|
154
|
+
"subnet_id": request.subnet_id,
|
|
155
|
+
"subnet_node_id": request.subnet_node_id,
|
|
156
|
+
},
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
response = self._submit_extrinsic(call, keypair)
|
|
160
|
+
|
|
161
|
+
if response["success"]:
|
|
162
|
+
response["message"] = (
|
|
163
|
+
f"Subnet {request.subnet_id} node {request.subnet_node_id} removed collectively"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
return response
|
|
167
|
+
|
|
168
|
+
except Exception as e:
|
|
169
|
+
logger.error(f"Error collectively removing subnet node: {e}")
|
|
170
|
+
return {"success": False, "error": str(e)}
|
|
171
|
+
|
|
172
|
+
def collective_remove_overwatch_node(
|
|
173
|
+
self, request: GovernanceCollectiveRemoveOverwatchNodeRequest, keypair: Keypair
|
|
174
|
+
) -> dict[str, Any]:
|
|
175
|
+
"""
|
|
176
|
+
Remove an overwatch node collectively (governance only).
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
request: Collective overwatch node removal request
|
|
180
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
dictionary with operation result
|
|
184
|
+
"""
|
|
185
|
+
try:
|
|
186
|
+
logger.info(
|
|
187
|
+
f"Collectively removing overwatch node {request.overwatch_node_id}"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
call = self.substrate.compose_call(
|
|
191
|
+
call_module="Network",
|
|
192
|
+
call_function="collective_remove_overwatch_node",
|
|
193
|
+
call_params={"overwatch_node_id": request.overwatch_node_id},
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
response = self._submit_extrinsic(call, keypair)
|
|
197
|
+
|
|
198
|
+
if response["success"]:
|
|
199
|
+
response["message"] = (
|
|
200
|
+
f"Overwatch node {request.overwatch_node_id} removed collectively"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return response
|
|
204
|
+
|
|
205
|
+
except Exception as e:
|
|
206
|
+
logger.error(f"Error collectively removing overwatch node: {e}")
|
|
207
|
+
return {"success": False, "error": str(e)}
|
|
208
|
+
|
|
209
|
+
# ============================================================================
|
|
210
|
+
# PARAMETER UPDATES
|
|
211
|
+
# ============================================================================
|
|
212
|
+
|
|
213
|
+
def set_min_delegate_stake_percentage(
|
|
214
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
215
|
+
) -> dict[str, Any]:
|
|
216
|
+
"""
|
|
217
|
+
Set minimum delegate stake percentage (governance only).
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
request: Parameter update request
|
|
221
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
dictionary with operation result
|
|
225
|
+
"""
|
|
226
|
+
try:
|
|
227
|
+
logger.info(f"Setting min delegate stake percentage to {request.value}")
|
|
228
|
+
|
|
229
|
+
call = self.substrate.compose_call(
|
|
230
|
+
call_module="Network",
|
|
231
|
+
call_function="set_min_delegate_stake_percentage",
|
|
232
|
+
call_params={"value": request.value},
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
response = self._submit_extrinsic(call, keypair)
|
|
236
|
+
|
|
237
|
+
if response["success"]:
|
|
238
|
+
response["message"] = (
|
|
239
|
+
f"Min delegate stake percentage set to {request.value}"
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
return response
|
|
243
|
+
|
|
244
|
+
except Exception as e:
|
|
245
|
+
logger.error(f"Error setting min delegate stake percentage: {e}")
|
|
246
|
+
return {"success": False, "error": str(e)}
|
|
247
|
+
|
|
248
|
+
def set_max_delegate_stake_percentage(
|
|
249
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
250
|
+
) -> dict[str, Any]:
|
|
251
|
+
"""
|
|
252
|
+
Set maximum delegate stake percentage (governance only).
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
request: Parameter update request
|
|
256
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
dictionary with operation result
|
|
260
|
+
"""
|
|
261
|
+
try:
|
|
262
|
+
logger.info(f"Setting max delegate stake percentage to {request.value}")
|
|
263
|
+
|
|
264
|
+
call = self.substrate.compose_call(
|
|
265
|
+
call_module="Network",
|
|
266
|
+
call_function="set_max_delegate_stake_percentage",
|
|
267
|
+
call_params={"value": request.value},
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
response = self._submit_extrinsic(call, keypair)
|
|
271
|
+
|
|
272
|
+
if response["success"]:
|
|
273
|
+
response["message"] = (
|
|
274
|
+
f"Max delegate stake percentage set to {request.value}"
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
return response
|
|
278
|
+
|
|
279
|
+
except Exception as e:
|
|
280
|
+
logger.error(f"Error setting max delegate stake percentage: {e}")
|
|
281
|
+
return {"success": False, "error": str(e)}
|
|
282
|
+
|
|
283
|
+
def set_min_max_registered_nodes(
|
|
284
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
285
|
+
) -> dict[str, Any]:
|
|
286
|
+
"""
|
|
287
|
+
Set minimum max registered nodes (governance only).
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
request: Parameter update request
|
|
291
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
dictionary with operation result
|
|
295
|
+
"""
|
|
296
|
+
try:
|
|
297
|
+
logger.info(f"Setting min max registered nodes to {request.value}")
|
|
298
|
+
|
|
299
|
+
call = self.substrate.compose_call(
|
|
300
|
+
call_module="Network",
|
|
301
|
+
call_function="set_min_max_registered_nodes",
|
|
302
|
+
call_params={"value": request.value},
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
response = self._submit_extrinsic(call, keypair)
|
|
306
|
+
|
|
307
|
+
if response["success"]:
|
|
308
|
+
response["message"] = f"Min max registered nodes set to {request.value}"
|
|
309
|
+
|
|
310
|
+
return response
|
|
311
|
+
|
|
312
|
+
except Exception as e:
|
|
313
|
+
logger.error(f"Error setting min max registered nodes: {e}")
|
|
314
|
+
return {"success": False, "error": str(e)}
|
|
315
|
+
|
|
316
|
+
def set_max_max_registered_nodes(
|
|
317
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
318
|
+
) -> dict[str, Any]:
|
|
319
|
+
"""
|
|
320
|
+
Set maximum max registered nodes (governance only).
|
|
321
|
+
|
|
322
|
+
Args:
|
|
323
|
+
request: Parameter update request
|
|
324
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
325
|
+
|
|
326
|
+
Returns:
|
|
327
|
+
dictionary with operation result
|
|
328
|
+
"""
|
|
329
|
+
try:
|
|
330
|
+
logger.info(f"Setting max max registered nodes to {request.value}")
|
|
331
|
+
|
|
332
|
+
call = self.substrate.compose_call(
|
|
333
|
+
call_module="Network",
|
|
334
|
+
call_function="set_max_max_registered_nodes",
|
|
335
|
+
call_params={"value": request.value},
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
response = self._submit_extrinsic(call, keypair)
|
|
339
|
+
|
|
340
|
+
if response["success"]:
|
|
341
|
+
response["message"] = f"Max max registered nodes set to {request.value}"
|
|
342
|
+
|
|
343
|
+
return response
|
|
344
|
+
|
|
345
|
+
except Exception as e:
|
|
346
|
+
logger.error(f"Error setting max max registered nodes: {e}")
|
|
347
|
+
return {"success": False, "error": str(e)}
|
|
348
|
+
|
|
349
|
+
def set_network_min_stake_balance(
|
|
350
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
351
|
+
) -> dict[str, Any]:
|
|
352
|
+
"""
|
|
353
|
+
Set network minimum stake balance (governance only).
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
request: Parameter update request
|
|
357
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
dictionary with operation result
|
|
361
|
+
"""
|
|
362
|
+
try:
|
|
363
|
+
logger.info(f"Setting network min stake balance to {request.value}")
|
|
364
|
+
|
|
365
|
+
call = self.substrate.compose_call(
|
|
366
|
+
call_module="Network",
|
|
367
|
+
call_function="set_network_min_stake_balance",
|
|
368
|
+
call_params={"value": request.value},
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
response = self._submit_extrinsic(call, keypair)
|
|
372
|
+
|
|
373
|
+
if response["success"]:
|
|
374
|
+
response["message"] = (
|
|
375
|
+
f"Network min stake balance set to {request.value}"
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
return response
|
|
379
|
+
|
|
380
|
+
except Exception as e:
|
|
381
|
+
logger.error(f"Error setting network min stake balance: {e}")
|
|
382
|
+
return {"success": False, "error": str(e)}
|
|
383
|
+
|
|
384
|
+
def set_network_max_stake_balance(
|
|
385
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
386
|
+
) -> dict[str, Any]:
|
|
387
|
+
"""
|
|
388
|
+
Set network maximum stake balance (governance only).
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
request: Parameter update request
|
|
392
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
393
|
+
|
|
394
|
+
Returns:
|
|
395
|
+
dictionary with operation result
|
|
396
|
+
"""
|
|
397
|
+
try:
|
|
398
|
+
logger.info(f"Setting network max stake balance to {request.value}")
|
|
399
|
+
|
|
400
|
+
call = self.substrate.compose_call(
|
|
401
|
+
call_module="Network",
|
|
402
|
+
call_function="set_network_max_stake_balance",
|
|
403
|
+
call_params={"value": request.value},
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
response = self._submit_extrinsic(call, keypair)
|
|
407
|
+
|
|
408
|
+
if response["success"]:
|
|
409
|
+
response["message"] = (
|
|
410
|
+
f"Network max stake balance set to {request.value}"
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
return response
|
|
414
|
+
|
|
415
|
+
except Exception as e:
|
|
416
|
+
logger.error(f"Error setting network max stake balance: {e}")
|
|
417
|
+
return {"success": False, "error": str(e)}
|
|
418
|
+
|
|
419
|
+
def set_tx_rate_limit(
|
|
420
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
421
|
+
) -> dict[str, Any]:
|
|
422
|
+
"""
|
|
423
|
+
Set transaction rate limit (governance only).
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
request: Parameter update request
|
|
427
|
+
keypair: Keypair for signing the transaction (must be governance)
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
dictionary with operation result
|
|
431
|
+
"""
|
|
432
|
+
try:
|
|
433
|
+
logger.info(f"Setting transaction rate limit to {request.value}")
|
|
434
|
+
|
|
435
|
+
call = self.substrate.compose_call(
|
|
436
|
+
call_module="Network",
|
|
437
|
+
call_function="set_tx_rate_limit",
|
|
438
|
+
call_params={"value": request.value},
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
response = self._submit_extrinsic(call, keypair)
|
|
442
|
+
|
|
443
|
+
if response["success"]:
|
|
444
|
+
response["message"] = f"Transaction rate limit set to {request.value}"
|
|
445
|
+
|
|
446
|
+
return response
|
|
447
|
+
|
|
448
|
+
except Exception as e:
|
|
449
|
+
logger.error(f"Error setting transaction rate limit: {e}")
|
|
450
|
+
return {"success": False, "error": str(e)}
|
|
451
|
+
|
|
452
|
+
def set_min_registration_cost(
|
|
453
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
454
|
+
) -> dict[str, Any]:
|
|
455
|
+
"""Set min registration cost."""
|
|
456
|
+
try:
|
|
457
|
+
logger.info(f"Setting min registration cost to {request.value}")
|
|
458
|
+
call = self.substrate.compose_call(
|
|
459
|
+
call_module="Network",
|
|
460
|
+
call_function="set_min_registration_cost",
|
|
461
|
+
call_params={"value": request.value},
|
|
462
|
+
)
|
|
463
|
+
return self._submit_extrinsic(call, keypair)
|
|
464
|
+
except Exception as e:
|
|
465
|
+
logger.error(f"Error setting min registration cost: {e}")
|
|
466
|
+
return {"success": False, "error": str(e)}
|
|
467
|
+
|
|
468
|
+
def set_target_registrations_per_interval(
|
|
469
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
470
|
+
) -> dict[str, Any]:
|
|
471
|
+
"""Set target registrations per interval."""
|
|
472
|
+
try:
|
|
473
|
+
logger.info(f"Setting target regs per interval to {request.value}")
|
|
474
|
+
call = self.substrate.compose_call(
|
|
475
|
+
call_module="Network",
|
|
476
|
+
call_function="set_target_registrations_per_interval",
|
|
477
|
+
call_params={"value": request.value},
|
|
478
|
+
)
|
|
479
|
+
return self._submit_extrinsic(call, keypair)
|
|
480
|
+
except Exception as e:
|
|
481
|
+
logger.error(f"Error setting target regs per interval: {e}")
|
|
482
|
+
return {"success": False, "error": str(e)}
|
|
483
|
+
|
|
484
|
+
def set_max_registrations_per_interval(
|
|
485
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
486
|
+
) -> dict[str, Any]:
|
|
487
|
+
"""Set max registrations per interval."""
|
|
488
|
+
try:
|
|
489
|
+
logger.info(f"Setting max regs per interval to {request.value}")
|
|
490
|
+
call = self.substrate.compose_call(
|
|
491
|
+
call_module="Network",
|
|
492
|
+
call_function="set_max_registrations_per_interval",
|
|
493
|
+
call_params={"value": request.value},
|
|
494
|
+
)
|
|
495
|
+
return self._submit_extrinsic(call, keypair)
|
|
496
|
+
except Exception as e:
|
|
497
|
+
logger.error(f"Error setting max regs per interval: {e}")
|
|
498
|
+
return {"success": False, "error": str(e)}
|
|
499
|
+
|
|
500
|
+
def set_adjustment_alpha(
|
|
501
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
502
|
+
) -> dict[str, Any]:
|
|
503
|
+
"""Set adjustment alpha."""
|
|
504
|
+
try:
|
|
505
|
+
logger.info(f"Setting adjustment alpha to {request.value}")
|
|
506
|
+
call = self.substrate.compose_call(
|
|
507
|
+
call_module="Network",
|
|
508
|
+
call_function="set_adjustment_alpha",
|
|
509
|
+
call_params={"value": request.value},
|
|
510
|
+
)
|
|
511
|
+
return self._submit_extrinsic(call, keypair)
|
|
512
|
+
except Exception as e:
|
|
513
|
+
logger.error(f"Error setting adjustment alpha: {e}")
|
|
514
|
+
return {"success": False, "error": str(e)}
|
|
515
|
+
|
|
516
|
+
def set_target_max_subnet_nodes(
|
|
517
|
+
self, request: GovernanceParameterUpdateRequest, keypair: Keypair
|
|
518
|
+
) -> dict[str, Any]:
|
|
519
|
+
"""Set target max subnet nodes."""
|
|
520
|
+
try:
|
|
521
|
+
logger.info(f"Setting target max subnet nodes to {request.value}")
|
|
522
|
+
call = self.substrate.compose_call(
|
|
523
|
+
call_module="Network",
|
|
524
|
+
call_function="set_target_max_subnet_nodes",
|
|
525
|
+
call_params={"value": request.value},
|
|
526
|
+
)
|
|
527
|
+
return self._submit_extrinsic(call, keypair)
|
|
528
|
+
except Exception as e:
|
|
529
|
+
logger.error(f"Error setting target max subnet nodes: {e}")
|
|
530
|
+
return {"success": False, "error": str(e)}
|
|
531
|
+
|
|
532
|
+
# ============================================================================
|
|
533
|
+
# QUERY METHODS
|
|
534
|
+
# ============================================================================
|
|
535
|
+
|
|
536
|
+
def get_network_state(self) -> str:
|
|
537
|
+
"""
|
|
538
|
+
Get the current network state.
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
Network state (Active/Paused)
|
|
542
|
+
"""
|
|
543
|
+
try:
|
|
544
|
+
is_paused = self.substrate.query(
|
|
545
|
+
module="Network", storage_function="IsPaused"
|
|
546
|
+
).value
|
|
547
|
+
|
|
548
|
+
return "Paused" if is_paused else "Active"
|
|
549
|
+
|
|
550
|
+
except Exception as e:
|
|
551
|
+
logger.error(f"Error getting network state: {e}")
|
|
552
|
+
return "Unknown"
|
|
553
|
+
|
|
554
|
+
def get_governance_parameters(self) -> dict[str, Any]:
|
|
555
|
+
"""
|
|
556
|
+
Get current governance parameters.
|
|
557
|
+
|
|
558
|
+
Returns:
|
|
559
|
+
dictionary with governance parameters
|
|
560
|
+
"""
|
|
561
|
+
try:
|
|
562
|
+
parameters = {}
|
|
563
|
+
|
|
564
|
+
# Query various governance parameters
|
|
565
|
+
parameter_queries = [
|
|
566
|
+
("min_delegate_stake_percentage", "MinDelegateStakePercentage"),
|
|
567
|
+
("max_delegate_stake_percentage", "MaxDelegateStakePercentage"),
|
|
568
|
+
("min_max_registered_nodes", "MinMaxRegisteredNodes"),
|
|
569
|
+
("max_max_registered_nodes", "MaxMaxRegisteredNodes"),
|
|
570
|
+
("network_min_stake_balance", "NetworkMinStakeBalance"),
|
|
571
|
+
("network_max_stake_balance", "NetworkMaxStakeBalance"),
|
|
572
|
+
("tx_rate_limit", "TxRateLimit"),
|
|
573
|
+
("epoch_length", "EpochLength"),
|
|
574
|
+
("min_stake_balance", "MinStakeBalance"),
|
|
575
|
+
("max_stake_balance", "MaxStakeBalance"),
|
|
576
|
+
]
|
|
577
|
+
|
|
578
|
+
for param_name, storage_key in parameter_queries:
|
|
579
|
+
try:
|
|
580
|
+
value = self.substrate.query(
|
|
581
|
+
module="Network", storage_function=storage_key
|
|
582
|
+
).value
|
|
583
|
+
parameters[param_name] = value
|
|
584
|
+
except Exception as e:
|
|
585
|
+
logger.warning(f"Could not query {param_name}: {e}")
|
|
586
|
+
parameters[param_name] = None
|
|
587
|
+
|
|
588
|
+
return parameters
|
|
589
|
+
|
|
590
|
+
except Exception as e:
|
|
591
|
+
logger.error(f"Error getting governance parameters: {e}")
|
|
592
|
+
return {}
|
|
593
|
+
|
|
594
|
+
def get_network_info(self) -> dict[str, Any]:
|
|
595
|
+
"""
|
|
596
|
+
Get general network information.
|
|
597
|
+
|
|
598
|
+
Returns:
|
|
599
|
+
dictionary with network information
|
|
600
|
+
"""
|
|
601
|
+
try:
|
|
602
|
+
info = {}
|
|
603
|
+
|
|
604
|
+
# Get basic network stats
|
|
605
|
+
total_subnets = (
|
|
606
|
+
self.substrate.query(
|
|
607
|
+
module="Network", storage_function="TotalSubnetUids"
|
|
608
|
+
).value
|
|
609
|
+
or 0
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
total_nodes = (
|
|
613
|
+
self.substrate.query(
|
|
614
|
+
module="Network", storage_function="TotalSubnetNodes"
|
|
615
|
+
).value
|
|
616
|
+
or 0
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
total_overwatch_nodes = (
|
|
620
|
+
self.substrate.query(
|
|
621
|
+
module="Network", storage_function="TotalOverwatchNodes"
|
|
622
|
+
).value
|
|
623
|
+
or 0
|
|
624
|
+
)
|
|
625
|
+
|
|
626
|
+
current_epoch = self.get_current_epoch()
|
|
627
|
+
network_state = self.get_network_state()
|
|
628
|
+
|
|
629
|
+
info.update(
|
|
630
|
+
{
|
|
631
|
+
"total_subnets": total_subnets,
|
|
632
|
+
"total_nodes": total_nodes,
|
|
633
|
+
"total_overwatch_nodes": total_overwatch_nodes,
|
|
634
|
+
"current_epoch": current_epoch,
|
|
635
|
+
"network_state": network_state,
|
|
636
|
+
}
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
return info
|
|
640
|
+
|
|
641
|
+
except Exception as e:
|
|
642
|
+
logger.error(f"Error getting network info: {e}")
|
|
643
|
+
return {}
|
|
644
|
+
|
|
645
|
+
def get_current_epoch(self) -> int:
|
|
646
|
+
"""
|
|
647
|
+
Get the current epoch number.
|
|
648
|
+
|
|
649
|
+
Returns:
|
|
650
|
+
Current epoch number
|
|
651
|
+
"""
|
|
652
|
+
try:
|
|
653
|
+
current_block = self.substrate.get_block_number()
|
|
654
|
+
epoch_length = (
|
|
655
|
+
self.substrate.query(
|
|
656
|
+
module="Network", storage_function="EpochLength"
|
|
657
|
+
).value
|
|
658
|
+
or 300
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
return current_block // epoch_length
|
|
662
|
+
|
|
663
|
+
except Exception as e:
|
|
664
|
+
logger.error(f"Error getting current epoch: {e}")
|
|
665
|
+
return 0
|
|
666
|
+
|
|
667
|
+
# ============================================================================
|
|
668
|
+
# PRIVATE HELPER METHODS
|
|
669
|
+
# ============================================================================
|
|
670
|
+
|
|
671
|
+
def _submit_extrinsic(self, call, keypair: Keypair) -> dict[str, Any]:
|
|
672
|
+
"""Submit an extrinsic and return the result."""
|
|
673
|
+
try:
|
|
674
|
+
extrinsic = self.substrate.create_signed_extrinsic(
|
|
675
|
+
call=call,
|
|
676
|
+
keypair=keypair,
|
|
677
|
+
era={"period": 64}, # 64 block era
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
response = self.substrate.submit_extrinsic(
|
|
681
|
+
extrinsic, wait_for_inclusion=True, wait_for_finalization=True
|
|
682
|
+
)
|
|
683
|
+
|
|
684
|
+
if response.is_success:
|
|
685
|
+
return {
|
|
686
|
+
"success": True,
|
|
687
|
+
"extrinsic_hash": response.extrinsic_hash,
|
|
688
|
+
"block_hash": response.block_hash,
|
|
689
|
+
"block_number": response.block_number,
|
|
690
|
+
}
|
|
691
|
+
else:
|
|
692
|
+
error_msg = self._extract_error_message(response)
|
|
693
|
+
return {"success": False, "error": error_msg}
|
|
694
|
+
|
|
695
|
+
except Exception as e:
|
|
696
|
+
logger.error(f"Error submitting extrinsic: {e}")
|
|
697
|
+
return {"success": False, "error": str(e)}
|
|
698
|
+
|
|
699
|
+
def _extract_error_message(self, response) -> str:
|
|
700
|
+
"""Extract error message from failed response."""
|
|
701
|
+
try:
|
|
702
|
+
for event in response.triggered_events:
|
|
703
|
+
if (
|
|
704
|
+
event.value["module_id"] == "System"
|
|
705
|
+
and event.value["event_id"] == "ExtrinsicFailed"
|
|
706
|
+
):
|
|
707
|
+
error = event.value["attributes"][0]
|
|
708
|
+
if hasattr(error, "name"):
|
|
709
|
+
return f"Extrinsic failed: {error.name}"
|
|
710
|
+
return f"Extrinsic failed: {str(error)}"
|
|
711
|
+
except Exception as e:
|
|
712
|
+
logger.warning(f"Could not extract error message: {e}")
|
|
713
|
+
|
|
714
|
+
return "Unknown error occurred"
|