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,192 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Validator command module.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
|
|
9
|
+
from . import handlers as validator_handlers
|
|
10
|
+
|
|
11
|
+
app = typer.Typer(name="validator", help="Validator operations")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@app.command("register")
|
|
15
|
+
def register_validator(
|
|
16
|
+
hotkey: Optional[str] = typer.Option(
|
|
17
|
+
None, "--hotkey", help="Validator hotkey address"
|
|
18
|
+
),
|
|
19
|
+
delegate_rate: Optional[int] = typer.Option(
|
|
20
|
+
None,
|
|
21
|
+
"--delegate-rate",
|
|
22
|
+
help="Delegate reward rate (0-100 as percent, or 1e18-format value)",
|
|
23
|
+
),
|
|
24
|
+
delegate_account: Optional[str] = typer.Option(
|
|
25
|
+
None, "--delegate-account", help="Optional delegate account address"
|
|
26
|
+
),
|
|
27
|
+
delegate_account_rate: Optional[int] = typer.Option(
|
|
28
|
+
None,
|
|
29
|
+
"--delegate-account-rate",
|
|
30
|
+
help="Optional delegate account rate (0-100 as percent, or 1e18-format value)",
|
|
31
|
+
),
|
|
32
|
+
coldkey: Optional[str] = typer.Option(
|
|
33
|
+
None,
|
|
34
|
+
"--coldkey",
|
|
35
|
+
help="Coldkey wallet name or address to sign the registration extrinsic",
|
|
36
|
+
),
|
|
37
|
+
):
|
|
38
|
+
"""Register a validator."""
|
|
39
|
+
validator_handlers.register_validator_handler(
|
|
40
|
+
hotkey=hotkey,
|
|
41
|
+
delegate_rate=delegate_rate,
|
|
42
|
+
delegate_account=delegate_account,
|
|
43
|
+
delegate_account_rate=delegate_account_rate,
|
|
44
|
+
coldkey=coldkey,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@app.command("update-delegate-rate")
|
|
49
|
+
def update_delegate_rate(
|
|
50
|
+
validator_id: Optional[int] = typer.Option(
|
|
51
|
+
None, "--validator-id", help="Validator ID to update"
|
|
52
|
+
),
|
|
53
|
+
delegate_rate: Optional[int] = typer.Option(
|
|
54
|
+
None,
|
|
55
|
+
"--delegate-rate",
|
|
56
|
+
help="Delegate reward rate (0-100 as percent, or 1e18-format value)",
|
|
57
|
+
),
|
|
58
|
+
coldkey: Optional[str] = typer.Option(
|
|
59
|
+
None,
|
|
60
|
+
"--coldkey",
|
|
61
|
+
help="Coldkey wallet name or address to sign the update extrinsic",
|
|
62
|
+
),
|
|
63
|
+
):
|
|
64
|
+
"""Update a validator delegate reward rate."""
|
|
65
|
+
validator_handlers.update_delegate_rate_handler(
|
|
66
|
+
validator_id=validator_id,
|
|
67
|
+
delegate_rate=delegate_rate,
|
|
68
|
+
coldkey=coldkey,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@app.command("update-delegate-account")
|
|
73
|
+
def update_delegate_account(
|
|
74
|
+
validator_id: Optional[int] = typer.Option(
|
|
75
|
+
None, "--validator-id", help="Validator ID to update"
|
|
76
|
+
),
|
|
77
|
+
delegate_account: Optional[str] = typer.Option(
|
|
78
|
+
None, "--delegate-account", help="Delegate account address"
|
|
79
|
+
),
|
|
80
|
+
delegate_account_rate: Optional[int] = typer.Option(
|
|
81
|
+
None,
|
|
82
|
+
"--delegate-account-rate",
|
|
83
|
+
help="Delegate account rate (0-100 as percent, or 1e18-format value)",
|
|
84
|
+
),
|
|
85
|
+
clear: bool = typer.Option(
|
|
86
|
+
False, "--clear", help="Clear the validator delegate account"
|
|
87
|
+
),
|
|
88
|
+
coldkey: Optional[str] = typer.Option(
|
|
89
|
+
None,
|
|
90
|
+
"--coldkey",
|
|
91
|
+
help="Coldkey wallet name or address to sign the update extrinsic",
|
|
92
|
+
),
|
|
93
|
+
):
|
|
94
|
+
"""Update or clear a validator delegate account."""
|
|
95
|
+
validator_handlers.update_delegate_account_handler(
|
|
96
|
+
validator_id=validator_id,
|
|
97
|
+
delegate_account=delegate_account,
|
|
98
|
+
delegate_account_rate=delegate_account_rate,
|
|
99
|
+
clear=clear,
|
|
100
|
+
coldkey=coldkey,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@app.command("update-hotkey")
|
|
105
|
+
def update_hotkey(
|
|
106
|
+
validator_id: Optional[int] = typer.Option(
|
|
107
|
+
None, "--validator-id", help="Validator ID to update"
|
|
108
|
+
),
|
|
109
|
+
hotkey: Optional[str] = typer.Option(
|
|
110
|
+
None, "--hotkey", help="New validator hotkey address"
|
|
111
|
+
),
|
|
112
|
+
coldkey: Optional[str] = typer.Option(
|
|
113
|
+
None,
|
|
114
|
+
"--coldkey",
|
|
115
|
+
help="Coldkey wallet name or address to sign the update extrinsic",
|
|
116
|
+
),
|
|
117
|
+
):
|
|
118
|
+
"""Update a validator hotkey."""
|
|
119
|
+
validator_handlers.update_hotkey_handler(
|
|
120
|
+
validator_id=validator_id,
|
|
121
|
+
hotkey=hotkey,
|
|
122
|
+
coldkey=coldkey,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@app.command("update-coldkey")
|
|
127
|
+
def update_coldkey(
|
|
128
|
+
validator_id: Optional[int] = typer.Option(
|
|
129
|
+
None, "--validator-id", help="Validator ID to update"
|
|
130
|
+
),
|
|
131
|
+
new_coldkey: Optional[str] = typer.Option(
|
|
132
|
+
None, "--new-coldkey", help="New validator coldkey address"
|
|
133
|
+
),
|
|
134
|
+
coldkey: Optional[str] = typer.Option(
|
|
135
|
+
None,
|
|
136
|
+
"--coldkey",
|
|
137
|
+
help="Current coldkey wallet name or address to sign the update extrinsic",
|
|
138
|
+
),
|
|
139
|
+
):
|
|
140
|
+
"""Update a validator coldkey."""
|
|
141
|
+
validator_handlers.update_coldkey_handler(
|
|
142
|
+
validator_id=validator_id,
|
|
143
|
+
new_coldkey=new_coldkey,
|
|
144
|
+
coldkey=coldkey,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@app.command("update-identity")
|
|
149
|
+
def update_identity(
|
|
150
|
+
validator_id: Optional[int] = typer.Option(
|
|
151
|
+
None, "--validator-id", help="Validator ID to update"
|
|
152
|
+
),
|
|
153
|
+
name: Optional[str] = typer.Option(None, "--name", help="Display name"),
|
|
154
|
+
url: Optional[str] = typer.Option(None, "--url", help="Website URL"),
|
|
155
|
+
image: Optional[str] = typer.Option(None, "--image", help="Profile image URL"),
|
|
156
|
+
discord: Optional[str] = typer.Option(None, "--discord", help="Discord handle"),
|
|
157
|
+
x: Optional[str] = typer.Option(None, "--x", help="X handle"),
|
|
158
|
+
telegram: Optional[str] = typer.Option(None, "--telegram", help="Telegram handle"),
|
|
159
|
+
github: Optional[str] = typer.Option(None, "--github", help="GitHub profile URL"),
|
|
160
|
+
hugging_face: Optional[str] = typer.Option(
|
|
161
|
+
None, "--hugging-face", help="Hugging Face profile URL"
|
|
162
|
+
),
|
|
163
|
+
description: Optional[str] = typer.Option(
|
|
164
|
+
None, "--description", help="Short description"
|
|
165
|
+
),
|
|
166
|
+
misc: Optional[str] = typer.Option(None, "--misc", help="Additional data"),
|
|
167
|
+
clear: bool = typer.Option(False, "--clear", help="Clear validator identity"),
|
|
168
|
+
coldkey: Optional[str] = typer.Option(
|
|
169
|
+
None,
|
|
170
|
+
"--coldkey",
|
|
171
|
+
help="Coldkey wallet name or address to sign the update extrinsic",
|
|
172
|
+
),
|
|
173
|
+
):
|
|
174
|
+
"""Update or clear a validator identity."""
|
|
175
|
+
validator_handlers.update_identity_handler(
|
|
176
|
+
validator_id=validator_id,
|
|
177
|
+
name=name,
|
|
178
|
+
url=url,
|
|
179
|
+
image=image,
|
|
180
|
+
discord=discord,
|
|
181
|
+
x=x,
|
|
182
|
+
telegram=telegram,
|
|
183
|
+
github=github,
|
|
184
|
+
hugging_face=hugging_face,
|
|
185
|
+
description=description,
|
|
186
|
+
misc=misc,
|
|
187
|
+
clear=clear,
|
|
188
|
+
coldkey=coldkey,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
__all__ = ["app"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Validator command display helpers.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ...ui.colors import error, info, success
|
|
8
|
+
from ...ui.components import HTCLIPanel
|
|
9
|
+
from ...ui.display import HTCLIConsole
|
|
10
|
+
|
|
11
|
+
console = HTCLIConsole()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _response_value(response: Any, field: str, default: Any = None) -> Any:
|
|
15
|
+
if isinstance(response, dict):
|
|
16
|
+
return response.get(field, default)
|
|
17
|
+
return getattr(response, field, default)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def display_validator_result(response: Any, operation: str) -> None:
|
|
21
|
+
"""Display a validator extrinsic response."""
|
|
22
|
+
succeeded = _response_value(response, "success", False)
|
|
23
|
+
message = _response_value(response, "message") or operation
|
|
24
|
+
transaction_hash = _response_value(response, "transaction_hash")
|
|
25
|
+
block_number = _response_value(response, "block_number")
|
|
26
|
+
validator_id = _response_value(response, "validator_id")
|
|
27
|
+
hotkey = _response_value(response, "hotkey")
|
|
28
|
+
|
|
29
|
+
if not succeeded:
|
|
30
|
+
error_message = _response_value(response, "error", f"{operation} failed")
|
|
31
|
+
panel = HTCLIPanel(
|
|
32
|
+
error(str(error_message)),
|
|
33
|
+
title=f"{operation} Failed",
|
|
34
|
+
border_style="htcli.error",
|
|
35
|
+
)
|
|
36
|
+
panel.render(console.console)
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
lines = [success(str(message))]
|
|
40
|
+
if validator_id is not None:
|
|
41
|
+
lines.append(f"[htcli.value]Validator ID:[/htcli.value] {validator_id}")
|
|
42
|
+
if hotkey:
|
|
43
|
+
lines.append(f"[htcli.value]Hotkey:[/htcli.value] {hotkey}")
|
|
44
|
+
if transaction_hash:
|
|
45
|
+
lines.append(f"[htcli.value]Transaction:[/htcli.value] {transaction_hash}")
|
|
46
|
+
if block_number is not None:
|
|
47
|
+
lines.append(f"[htcli.value]Block:[/htcli.value] {block_number}")
|
|
48
|
+
|
|
49
|
+
panel = HTCLIPanel(
|
|
50
|
+
"\n".join(lines) if lines else info("Submitted"),
|
|
51
|
+
title=operation,
|
|
52
|
+
border_style="htcli.success",
|
|
53
|
+
)
|
|
54
|
+
panel.render(console.console)
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Validator command handlers.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from ...dependencies import get_client
|
|
8
|
+
from ...errors.handlers import handle_and_display_error
|
|
9
|
+
from ...models.requests.validator import (
|
|
10
|
+
ValidatorColdkeyUpdateRequest,
|
|
11
|
+
ValidatorDelegateAccountUpdateRequest,
|
|
12
|
+
ValidatorDelegateRewardRateUpdateRequest,
|
|
13
|
+
ValidatorHotkeyUpdateRequest,
|
|
14
|
+
ValidatorIdentityUpdateRequest,
|
|
15
|
+
ValidatorRegisterRequest,
|
|
16
|
+
)
|
|
17
|
+
from ...ui.components import HTCLILoadingContext
|
|
18
|
+
from ...ui.display import print_error
|
|
19
|
+
from ...utils import retrieve_wallet_with_validation
|
|
20
|
+
from ...utils.prompts import integer_prompt, string_prompt
|
|
21
|
+
from ..node.prompts import normalize_delegate_reward_rate
|
|
22
|
+
from .display import display_validator_result
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _resolve_signing_keypair(coldkey: Optional[str], purpose: str):
|
|
26
|
+
if coldkey:
|
|
27
|
+
from ...utils.wallet.core import resolve_coldkey_and_get_keypair
|
|
28
|
+
|
|
29
|
+
return resolve_coldkey_and_get_keypair(coldkey)
|
|
30
|
+
return retrieve_wallet_with_validation(wallet_type="coldkey", purpose=purpose)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _connect_client():
|
|
34
|
+
client = get_client()
|
|
35
|
+
if not client.connect():
|
|
36
|
+
print_error("Failed to connect to blockchain")
|
|
37
|
+
return None
|
|
38
|
+
if not client.substrate:
|
|
39
|
+
print_error("Blockchain connection failed!")
|
|
40
|
+
raise RuntimeError("Not connected to blockchain")
|
|
41
|
+
if not client.extrinsics:
|
|
42
|
+
print_error("Extrinsics layer not initialized. Connection may have failed.")
|
|
43
|
+
raise RuntimeError("Extrinsics layer not available")
|
|
44
|
+
return client
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _rate_or_prompt(value: Optional[int], prompt_text: str) -> int:
|
|
48
|
+
if value is None:
|
|
49
|
+
value = integer_prompt(prompt_text)
|
|
50
|
+
return normalize_delegate_reward_rate(value)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def register_validator_handler(
|
|
54
|
+
hotkey: Optional[str] = None,
|
|
55
|
+
delegate_rate: Optional[int] = None,
|
|
56
|
+
delegate_account: Optional[str] = None,
|
|
57
|
+
delegate_account_rate: Optional[int] = None,
|
|
58
|
+
coldkey: Optional[str] = None,
|
|
59
|
+
):
|
|
60
|
+
"""Handle validator registration."""
|
|
61
|
+
try:
|
|
62
|
+
if hotkey is None:
|
|
63
|
+
hotkey = string_prompt("Enter validator hotkey address")
|
|
64
|
+
|
|
65
|
+
delegate_reward_rate = _rate_or_prompt(
|
|
66
|
+
delegate_rate, "Enter delegate reward rate"
|
|
67
|
+
)
|
|
68
|
+
delegate_account_rate = (
|
|
69
|
+
normalize_delegate_reward_rate(delegate_account_rate)
|
|
70
|
+
if delegate_account_rate is not None
|
|
71
|
+
else None
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
_, keypair = _resolve_signing_keypair(
|
|
75
|
+
coldkey, "sign the validator registration transaction"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
request = ValidatorRegisterRequest(
|
|
79
|
+
hotkey=hotkey,
|
|
80
|
+
delegate_reward_rate=delegate_reward_rate,
|
|
81
|
+
delegate_account_id=delegate_account,
|
|
82
|
+
delegate_account_rate=delegate_account_rate,
|
|
83
|
+
identity=None,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
client = _connect_client()
|
|
87
|
+
if client is None:
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
with HTCLILoadingContext("Registering validator..."):
|
|
91
|
+
response = client.extrinsics.validator.register_validator(request, keypair)
|
|
92
|
+
|
|
93
|
+
display_validator_result(response, "Validator Registration")
|
|
94
|
+
except Exception as e:
|
|
95
|
+
handle_and_display_error(e, operation="validator register")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def update_delegate_rate_handler(
|
|
99
|
+
validator_id: Optional[int] = None,
|
|
100
|
+
delegate_rate: Optional[int] = None,
|
|
101
|
+
coldkey: Optional[str] = None,
|
|
102
|
+
):
|
|
103
|
+
"""Handle validator delegate reward rate updates."""
|
|
104
|
+
try:
|
|
105
|
+
if validator_id is None:
|
|
106
|
+
validator_id = integer_prompt("Enter validator ID")
|
|
107
|
+
new_delegate_reward_rate = _rate_or_prompt(
|
|
108
|
+
delegate_rate, "Enter new delegate reward rate"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
_, keypair = _resolve_signing_keypair(
|
|
112
|
+
coldkey, "sign the validator delegate reward rate update transaction"
|
|
113
|
+
)
|
|
114
|
+
request = ValidatorDelegateRewardRateUpdateRequest(
|
|
115
|
+
validator_id=validator_id,
|
|
116
|
+
new_delegate_reward_rate=new_delegate_reward_rate,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
client = _connect_client()
|
|
120
|
+
if client is None:
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
with HTCLILoadingContext(
|
|
124
|
+
f"Updating validator {validator_id} delegate reward rate..."
|
|
125
|
+
):
|
|
126
|
+
response = (
|
|
127
|
+
client.extrinsics.validator.update_validator_delegate_reward_rate(
|
|
128
|
+
request, keypair
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
display_validator_result(response, "Validator Delegate Rate Update")
|
|
133
|
+
except Exception as e:
|
|
134
|
+
handle_and_display_error(e, operation="validator update delegate rate")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def update_delegate_account_handler(
|
|
138
|
+
validator_id: Optional[int] = None,
|
|
139
|
+
delegate_account: Optional[str] = None,
|
|
140
|
+
delegate_account_rate: Optional[int] = None,
|
|
141
|
+
clear: bool = False,
|
|
142
|
+
coldkey: Optional[str] = None,
|
|
143
|
+
):
|
|
144
|
+
"""Handle validator delegate account updates."""
|
|
145
|
+
try:
|
|
146
|
+
if validator_id is None:
|
|
147
|
+
validator_id = integer_prompt("Enter validator ID")
|
|
148
|
+
|
|
149
|
+
if clear:
|
|
150
|
+
delegate_account = None
|
|
151
|
+
delegate_rate = None
|
|
152
|
+
else:
|
|
153
|
+
if delegate_account is None:
|
|
154
|
+
delegate_account = string_prompt("Enter delegate account address")
|
|
155
|
+
delegate_rate = (
|
|
156
|
+
normalize_delegate_reward_rate(delegate_account_rate)
|
|
157
|
+
if delegate_account_rate is not None
|
|
158
|
+
else None
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
_, keypair = _resolve_signing_keypair(
|
|
162
|
+
coldkey, "sign the validator delegate account update transaction"
|
|
163
|
+
)
|
|
164
|
+
request = ValidatorDelegateAccountUpdateRequest(
|
|
165
|
+
validator_id=validator_id,
|
|
166
|
+
delegate_account_id=delegate_account,
|
|
167
|
+
delegate_rate=delegate_rate,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
client = _connect_client()
|
|
171
|
+
if client is None:
|
|
172
|
+
return
|
|
173
|
+
|
|
174
|
+
with HTCLILoadingContext(
|
|
175
|
+
f"Updating validator {validator_id} delegate account..."
|
|
176
|
+
):
|
|
177
|
+
response = client.extrinsics.validator.update_validator_delegate_account(
|
|
178
|
+
request, keypair
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
display_validator_result(response, "Validator Delegate Account Update")
|
|
182
|
+
except Exception as e:
|
|
183
|
+
handle_and_display_error(e, operation="validator update delegate account")
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def update_hotkey_handler(
|
|
187
|
+
validator_id: Optional[int] = None,
|
|
188
|
+
hotkey: Optional[str] = None,
|
|
189
|
+
coldkey: Optional[str] = None,
|
|
190
|
+
):
|
|
191
|
+
"""Handle validator hotkey updates."""
|
|
192
|
+
try:
|
|
193
|
+
if validator_id is None:
|
|
194
|
+
validator_id = integer_prompt("Enter validator ID")
|
|
195
|
+
if hotkey is None:
|
|
196
|
+
hotkey = string_prompt("Enter new validator hotkey address")
|
|
197
|
+
|
|
198
|
+
_, keypair = _resolve_signing_keypair(
|
|
199
|
+
coldkey, "sign the validator hotkey update transaction"
|
|
200
|
+
)
|
|
201
|
+
request = ValidatorHotkeyUpdateRequest(
|
|
202
|
+
validator_id=validator_id,
|
|
203
|
+
new_hotkey=hotkey,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
client = _connect_client()
|
|
207
|
+
if client is None:
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
with HTCLILoadingContext(f"Updating validator {validator_id} hotkey..."):
|
|
211
|
+
response = client.extrinsics.validator.update_validator_hotkey(
|
|
212
|
+
request, keypair
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
display_validator_result(response, "Validator Hotkey Update")
|
|
216
|
+
except Exception as e:
|
|
217
|
+
handle_and_display_error(e, operation="validator update hotkey")
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def update_coldkey_handler(
|
|
221
|
+
validator_id: Optional[int] = None,
|
|
222
|
+
new_coldkey: Optional[str] = None,
|
|
223
|
+
coldkey: Optional[str] = None,
|
|
224
|
+
):
|
|
225
|
+
"""Handle validator coldkey updates."""
|
|
226
|
+
try:
|
|
227
|
+
if validator_id is None:
|
|
228
|
+
validator_id = integer_prompt("Enter validator ID")
|
|
229
|
+
if new_coldkey is None:
|
|
230
|
+
new_coldkey = string_prompt("Enter new validator coldkey address")
|
|
231
|
+
|
|
232
|
+
_, keypair = _resolve_signing_keypair(
|
|
233
|
+
coldkey, "sign the validator coldkey update transaction"
|
|
234
|
+
)
|
|
235
|
+
request = ValidatorColdkeyUpdateRequest(
|
|
236
|
+
validator_id=validator_id,
|
|
237
|
+
new_coldkey=new_coldkey,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
client = _connect_client()
|
|
241
|
+
if client is None:
|
|
242
|
+
return
|
|
243
|
+
|
|
244
|
+
with HTCLILoadingContext(f"Updating validator {validator_id} coldkey..."):
|
|
245
|
+
response = client.extrinsics.validator.update_validator_coldkey(
|
|
246
|
+
request, keypair
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
display_validator_result(response, "Validator Coldkey Update")
|
|
250
|
+
except Exception as e:
|
|
251
|
+
handle_and_display_error(e, operation="validator update coldkey")
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _encode_identity_fields(
|
|
255
|
+
name: Optional[str] = None,
|
|
256
|
+
url: Optional[str] = None,
|
|
257
|
+
image: Optional[str] = None,
|
|
258
|
+
discord: Optional[str] = None,
|
|
259
|
+
x: Optional[str] = None,
|
|
260
|
+
telegram: Optional[str] = None,
|
|
261
|
+
github: Optional[str] = None,
|
|
262
|
+
hugging_face: Optional[str] = None,
|
|
263
|
+
description: Optional[str] = None,
|
|
264
|
+
misc: Optional[str] = None,
|
|
265
|
+
) -> dict[str, bytes]:
|
|
266
|
+
values = {
|
|
267
|
+
"name": name,
|
|
268
|
+
"url": url,
|
|
269
|
+
"image": image,
|
|
270
|
+
"discord": discord,
|
|
271
|
+
"x": x,
|
|
272
|
+
"telegram": telegram,
|
|
273
|
+
"github": github,
|
|
274
|
+
"hugging_face": hugging_face,
|
|
275
|
+
"description": description,
|
|
276
|
+
"misc": misc,
|
|
277
|
+
}
|
|
278
|
+
if not any(value is not None for value in values.values()):
|
|
279
|
+
raise ValueError("Provide at least one identity field or use --clear")
|
|
280
|
+
return {
|
|
281
|
+
field: ("" if value is None else value).encode("utf-8")
|
|
282
|
+
for field, value in values.items()
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def update_identity_handler(
|
|
287
|
+
validator_id: Optional[int] = None,
|
|
288
|
+
name: Optional[str] = None,
|
|
289
|
+
url: Optional[str] = None,
|
|
290
|
+
image: Optional[str] = None,
|
|
291
|
+
discord: Optional[str] = None,
|
|
292
|
+
x: Optional[str] = None,
|
|
293
|
+
telegram: Optional[str] = None,
|
|
294
|
+
github: Optional[str] = None,
|
|
295
|
+
hugging_face: Optional[str] = None,
|
|
296
|
+
description: Optional[str] = None,
|
|
297
|
+
misc: Optional[str] = None,
|
|
298
|
+
clear: bool = False,
|
|
299
|
+
coldkey: Optional[str] = None,
|
|
300
|
+
):
|
|
301
|
+
"""Handle validator identity updates."""
|
|
302
|
+
try:
|
|
303
|
+
if validator_id is None:
|
|
304
|
+
validator_id = integer_prompt("Enter validator ID")
|
|
305
|
+
|
|
306
|
+
identity = None
|
|
307
|
+
if not clear:
|
|
308
|
+
identity = _encode_identity_fields(
|
|
309
|
+
name=name,
|
|
310
|
+
url=url,
|
|
311
|
+
image=image,
|
|
312
|
+
discord=discord,
|
|
313
|
+
x=x,
|
|
314
|
+
telegram=telegram,
|
|
315
|
+
github=github,
|
|
316
|
+
hugging_face=hugging_face,
|
|
317
|
+
description=description,
|
|
318
|
+
misc=misc,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
_, keypair = _resolve_signing_keypair(
|
|
322
|
+
coldkey, "sign the validator identity update transaction"
|
|
323
|
+
)
|
|
324
|
+
request = ValidatorIdentityUpdateRequest(
|
|
325
|
+
validator_id=validator_id,
|
|
326
|
+
identity=identity,
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
client = _connect_client()
|
|
330
|
+
if client is None:
|
|
331
|
+
return
|
|
332
|
+
|
|
333
|
+
with HTCLILoadingContext(f"Updating validator {validator_id} identity..."):
|
|
334
|
+
response = client.extrinsics.validator.update_validator_identity(
|
|
335
|
+
request, keypair
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
display_validator_result(response, "Validator Identity Update")
|
|
339
|
+
except Exception as e:
|
|
340
|
+
handle_and_display_error(e, operation="validator update identity")
|