bittensor-cli 9.2.0__py3-none-any.whl → 9.3.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.
- bittensor_cli/cli.py +525 -131
- bittensor_cli/src/__init__.py +444 -465
- bittensor_cli/src/bittensor/chain_data.py +6 -2
- bittensor_cli/src/bittensor/extrinsics/registration.py +47 -23
- bittensor_cli/src/bittensor/extrinsics/root.py +10 -11
- bittensor_cli/src/bittensor/extrinsics/transfer.py +5 -3
- bittensor_cli/src/bittensor/subtensor_interface.py +59 -5
- bittensor_cli/src/bittensor/utils.py +4 -1
- bittensor_cli/src/commands/stake/add.py +127 -98
- bittensor_cli/src/commands/stake/children_hotkeys.py +120 -79
- bittensor_cli/src/commands/stake/list.py +54 -20
- bittensor_cli/src/commands/stake/move.py +15 -12
- bittensor_cli/src/commands/stake/remove.py +101 -80
- bittensor_cli/src/commands/subnets/price.py +11 -9
- bittensor_cli/src/commands/subnets/subnets.py +223 -80
- bittensor_cli/src/commands/sudo.py +76 -22
- bittensor_cli/src/commands/wallets.py +656 -40
- bittensor_cli/src/commands/weights.py +21 -11
- bittensor_cli/version.py +2 -1
- {bittensor_cli-9.2.0.dist-info → bittensor_cli-9.3.0.dist-info}/METADATA +7 -8
- bittensor_cli-9.3.0.dist-info/RECORD +35 -0
- {bittensor_cli-9.2.0.dist-info → bittensor_cli-9.3.0.dist-info}/WHEEL +1 -1
- bittensor_cli-9.2.0.dist-info/RECORD +0 -35
- {bittensor_cli-9.2.0.dist-info → bittensor_cli-9.3.0.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-9.2.0.dist-info → bittensor_cli-9.3.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,6 @@
|
|
1
1
|
import asyncio
|
2
|
+
import json
|
3
|
+
from collections import defaultdict
|
2
4
|
from functools import partial
|
3
5
|
|
4
6
|
from typing import TYPE_CHECKING, Optional
|
@@ -17,6 +19,7 @@ from bittensor_cli.src.bittensor.utils import (
|
|
17
19
|
print_error,
|
18
20
|
print_verbose,
|
19
21
|
unlock_key,
|
22
|
+
json_console,
|
20
23
|
)
|
21
24
|
from bittensor_wallet import Wallet
|
22
25
|
|
@@ -38,6 +41,8 @@ async def stake_add(
|
|
38
41
|
safe_staking: bool,
|
39
42
|
rate_tolerance: float,
|
40
43
|
allow_partial_stake: bool,
|
44
|
+
json_output: bool,
|
45
|
+
era: int,
|
41
46
|
):
|
42
47
|
"""
|
43
48
|
Args:
|
@@ -53,6 +58,8 @@ async def stake_add(
|
|
53
58
|
safe_staking: whether to use safe staking
|
54
59
|
rate_tolerance: rate tolerance percentage for stake operations
|
55
60
|
allow_partial_stake: whether to allow partial stake
|
61
|
+
json_output: whether to output stake info in JSON format
|
62
|
+
era: Blocks for which the transaction should be valid.
|
56
63
|
|
57
64
|
Returns:
|
58
65
|
bool: True if stake operation is successful, False otherwise
|
@@ -65,28 +72,31 @@ async def stake_add(
|
|
65
72
|
hotkey_ss58_: str,
|
66
73
|
price_limit: Balance,
|
67
74
|
status=None,
|
68
|
-
) ->
|
75
|
+
) -> bool:
|
69
76
|
err_out = partial(print_error, status=status)
|
70
77
|
failure_prelude = (
|
71
78
|
f":cross_mark: [red]Failed[/red] to stake {amount_} on Netuid {netuid_}"
|
72
79
|
)
|
73
|
-
current_balance = await
|
74
|
-
|
75
|
-
wallet.coldkeypub.ss58_address
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
current_balance, next_nonce, call = await asyncio.gather(
|
81
|
+
subtensor.get_balance(wallet.coldkeypub.ss58_address),
|
82
|
+
subtensor.substrate.get_account_next_index(wallet.coldkeypub.ss58_address),
|
83
|
+
subtensor.substrate.compose_call(
|
84
|
+
call_module="SubtensorModule",
|
85
|
+
call_function="add_stake_limit",
|
86
|
+
call_params={
|
87
|
+
"hotkey": hotkey_ss58_,
|
88
|
+
"netuid": netuid_,
|
89
|
+
"amount_staked": amount_.rao,
|
90
|
+
"limit_price": price_limit,
|
91
|
+
"allow_partial": allow_partial_stake,
|
92
|
+
},
|
93
|
+
),
|
87
94
|
)
|
88
95
|
extrinsic = await subtensor.substrate.create_signed_extrinsic(
|
89
|
-
call=call,
|
96
|
+
call=call,
|
97
|
+
keypair=wallet.coldkey,
|
98
|
+
nonce=next_nonce,
|
99
|
+
era={"period": era},
|
90
100
|
)
|
91
101
|
try:
|
92
102
|
response = await subtensor.substrate.submit_extrinsic(
|
@@ -100,73 +110,80 @@ async def stake_add(
|
|
100
110
|
f"Either increase price tolerance or enable partial staking.",
|
101
111
|
status=status,
|
102
112
|
)
|
103
|
-
return
|
113
|
+
return False
|
104
114
|
else:
|
105
115
|
err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
|
106
|
-
return
|
116
|
+
return False
|
117
|
+
if not await response.is_success:
|
118
|
+
err_out(
|
119
|
+
f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
|
120
|
+
)
|
121
|
+
return False
|
107
122
|
else:
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
)
|
130
|
-
|
131
|
-
amount_staked = current_balance - new_balance
|
132
|
-
if allow_partial_stake and (amount_staked != amount_):
|
133
|
-
console.print(
|
134
|
-
"Partial stake transaction. Staked:\n"
|
135
|
-
f" [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{amount_staked}[/{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}] "
|
136
|
-
f"instead of "
|
137
|
-
f"[blue]{amount_}[/blue]"
|
138
|
-
)
|
123
|
+
if json_output:
|
124
|
+
# the rest of this checking is not necessary if using json_output
|
125
|
+
return True
|
126
|
+
block_hash = await subtensor.substrate.get_chain_head()
|
127
|
+
new_balance, new_stake = await asyncio.gather(
|
128
|
+
subtensor.get_balance(wallet.coldkeypub.ss58_address, block_hash),
|
129
|
+
subtensor.get_stake(
|
130
|
+
hotkey_ss58=hotkey_ss58_,
|
131
|
+
coldkey_ss58=wallet.coldkeypub.ss58_address,
|
132
|
+
netuid=netuid_,
|
133
|
+
block_hash=block_hash,
|
134
|
+
),
|
135
|
+
)
|
136
|
+
console.print(
|
137
|
+
f":white_heavy_check_mark: [dark_sea_green3]Finalized. "
|
138
|
+
f"Stake added to netuid: {netuid_}[/dark_sea_green3]"
|
139
|
+
)
|
140
|
+
console.print(
|
141
|
+
f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: "
|
142
|
+
f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
|
143
|
+
)
|
139
144
|
|
145
|
+
amount_staked = current_balance - new_balance
|
146
|
+
if allow_partial_stake and (amount_staked != amount_):
|
140
147
|
console.print(
|
141
|
-
|
142
|
-
f"
|
143
|
-
f"
|
144
|
-
f"
|
145
|
-
f"[{
|
148
|
+
"Partial stake transaction. Staked:\n"
|
149
|
+
f" [{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{amount_staked}"
|
150
|
+
f"[/{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}] "
|
151
|
+
f"instead of "
|
152
|
+
f"[blue]{amount_}[/blue]"
|
146
153
|
)
|
147
154
|
|
155
|
+
console.print(
|
156
|
+
f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]"
|
157
|
+
f"{netuid_}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
|
158
|
+
f"Stake:\n"
|
159
|
+
f" [blue]{current_stake}[/blue] "
|
160
|
+
f":arrow_right: "
|
161
|
+
f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_stake}\n"
|
162
|
+
)
|
163
|
+
return True
|
164
|
+
|
148
165
|
async def stake_extrinsic(
|
149
166
|
netuid_i, amount_, current, staking_address_ss58, status=None
|
150
|
-
):
|
167
|
+
) -> bool:
|
151
168
|
err_out = partial(print_error, status=status)
|
152
|
-
current_balance = await
|
169
|
+
current_balance, next_nonce, call = await asyncio.gather(
|
170
|
+
subtensor.get_balance(wallet.coldkeypub.ss58_address),
|
171
|
+
subtensor.substrate.get_account_next_index(wallet.coldkeypub.ss58_address),
|
172
|
+
subtensor.substrate.compose_call(
|
173
|
+
call_module="SubtensorModule",
|
174
|
+
call_function="add_stake",
|
175
|
+
call_params={
|
176
|
+
"hotkey": staking_address_ss58,
|
177
|
+
"netuid": netuid_i,
|
178
|
+
"amount_staked": amount_.rao,
|
179
|
+
},
|
180
|
+
),
|
181
|
+
)
|
153
182
|
failure_prelude = (
|
154
183
|
f":cross_mark: [red]Failed[/red] to stake {amount} on Netuid {netuid_i}"
|
155
184
|
)
|
156
|
-
next_nonce = await subtensor.substrate.get_account_next_index(
|
157
|
-
wallet.coldkeypub.ss58_address
|
158
|
-
)
|
159
|
-
call = await subtensor.substrate.compose_call(
|
160
|
-
call_module="SubtensorModule",
|
161
|
-
call_function="add_stake",
|
162
|
-
call_params={
|
163
|
-
"hotkey": staking_address_ss58,
|
164
|
-
"netuid": netuid_i,
|
165
|
-
"amount_staked": amount_.rao,
|
166
|
-
},
|
167
|
-
)
|
168
185
|
extrinsic = await subtensor.substrate.create_signed_extrinsic(
|
169
|
-
call=call, keypair=wallet.coldkey, nonce=next_nonce
|
186
|
+
call=call, keypair=wallet.coldkey, nonce=next_nonce, era={"period": era}
|
170
187
|
)
|
171
188
|
try:
|
172
189
|
response = await subtensor.substrate.submit_extrinsic(
|
@@ -174,35 +191,46 @@ async def stake_add(
|
|
174
191
|
)
|
175
192
|
except SubstrateRequestException as e:
|
176
193
|
err_out(f"\n{failure_prelude} with error: {format_error_message(e)}")
|
177
|
-
return
|
194
|
+
return False
|
178
195
|
else:
|
179
|
-
await response.process_events()
|
180
196
|
if not await response.is_success:
|
181
197
|
err_out(
|
182
198
|
f"\n{failure_prelude} with error: {format_error_message(await response.error_message)}"
|
183
199
|
)
|
200
|
+
return False
|
184
201
|
else:
|
202
|
+
if json_output:
|
203
|
+
# the rest of this is not necessary if using json_output
|
204
|
+
return True
|
205
|
+
new_block_hash = await subtensor.substrate.get_chain_head()
|
185
206
|
new_balance, new_stake = await asyncio.gather(
|
186
|
-
subtensor.get_balance(
|
207
|
+
subtensor.get_balance(
|
208
|
+
wallet.coldkeypub.ss58_address, block_hash=new_block_hash
|
209
|
+
),
|
187
210
|
subtensor.get_stake(
|
188
211
|
hotkey_ss58=staking_address_ss58,
|
189
212
|
coldkey_ss58=wallet.coldkeypub.ss58_address,
|
190
213
|
netuid=netuid_i,
|
214
|
+
block_hash=new_block_hash,
|
191
215
|
),
|
192
216
|
)
|
193
217
|
console.print(
|
194
|
-
f":white_heavy_check_mark:
|
218
|
+
f":white_heavy_check_mark: "
|
219
|
+
f"[dark_sea_green3]Finalized. Stake added to netuid: {netuid_i}[/dark_sea_green3]"
|
195
220
|
)
|
196
221
|
console.print(
|
197
|
-
f"Balance:\n [blue]{current_balance}[/blue] :arrow_right:
|
222
|
+
f"Balance:\n [blue]{current_balance}[/blue] :arrow_right: "
|
223
|
+
f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_balance}"
|
198
224
|
)
|
199
225
|
console.print(
|
200
|
-
f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]
|
226
|
+
f"Subnet: [{COLOR_PALETTE['GENERAL']['SUBHEADING']}]"
|
227
|
+
f"{netuid_i}[/{COLOR_PALETTE['GENERAL']['SUBHEADING']}] "
|
201
228
|
f"Stake:\n"
|
202
229
|
f" [blue]{current}[/blue] "
|
203
230
|
f":arrow_right: "
|
204
231
|
f"[{COLOR_PALETTE['STAKE']['STAKE_AMOUNT']}]{new_stake}\n"
|
205
232
|
)
|
233
|
+
return True
|
206
234
|
|
207
235
|
netuids = (
|
208
236
|
[int(netuid)]
|
@@ -333,7 +361,9 @@ async def stake_add(
|
|
333
361
|
base_row.extend(
|
334
362
|
[
|
335
363
|
f"{rate_with_tolerance} {Balance.get_unit(netuid)}/{Balance.get_unit(0)} ",
|
336
|
-
f"[{'dark_sea_green3' if allow_partial_stake else 'red'}]
|
364
|
+
f"[{'dark_sea_green3' if allow_partial_stake else 'red'}]"
|
365
|
+
# safe staking
|
366
|
+
f"{allow_partial_stake}[/{'dark_sea_green3' if allow_partial_stake else 'red'}]",
|
337
367
|
]
|
338
368
|
)
|
339
369
|
|
@@ -352,7 +382,7 @@ async def stake_add(
|
|
352
382
|
return False
|
353
383
|
|
354
384
|
if safe_staking:
|
355
|
-
stake_coroutines =
|
385
|
+
stake_coroutines = {}
|
356
386
|
for i, (ni, am, curr, price_with_tolerance) in enumerate(
|
357
387
|
zip(
|
358
388
|
netuids, amounts_to_stake, current_stake_balances, prices_with_tolerance
|
@@ -361,27 +391,23 @@ async def stake_add(
|
|
361
391
|
for _, staking_address in hotkeys_to_stake_to:
|
362
392
|
# Regular extrinsic for root subnet
|
363
393
|
if ni == 0:
|
364
|
-
stake_coroutines
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
staking_address_ss58=staking_address,
|
370
|
-
)
|
394
|
+
stake_coroutines[(ni, staking_address)] = stake_extrinsic(
|
395
|
+
netuid_i=ni,
|
396
|
+
amount_=am,
|
397
|
+
current=curr,
|
398
|
+
staking_address_ss58=staking_address,
|
371
399
|
)
|
372
400
|
else:
|
373
|
-
stake_coroutines
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
price_limit=price_with_tolerance,
|
380
|
-
)
|
401
|
+
stake_coroutines[(ni, staking_address)] = safe_stake_extrinsic(
|
402
|
+
netuid_=ni,
|
403
|
+
amount_=am,
|
404
|
+
current_stake=curr,
|
405
|
+
hotkey_ss58_=staking_address,
|
406
|
+
price_limit=price_with_tolerance,
|
381
407
|
)
|
382
408
|
else:
|
383
|
-
stake_coroutines =
|
384
|
-
stake_extrinsic(
|
409
|
+
stake_coroutines = {
|
410
|
+
(ni, staking_address): stake_extrinsic(
|
385
411
|
netuid_i=ni,
|
386
412
|
amount_=am,
|
387
413
|
current=curr,
|
@@ -391,12 +417,15 @@ async def stake_add(
|
|
391
417
|
zip(netuids, amounts_to_stake, current_stake_balances)
|
392
418
|
)
|
393
419
|
for _, staking_address in hotkeys_to_stake_to
|
394
|
-
|
395
|
-
|
420
|
+
}
|
421
|
+
successes = defaultdict(dict)
|
396
422
|
with console.status(f"\n:satellite: Staking on netuid(s): {netuids} ..."):
|
397
423
|
# We can gather them all at once but balance reporting will be in race-condition.
|
398
|
-
for coroutine in stake_coroutines:
|
399
|
-
await coroutine
|
424
|
+
for (ni, staking_address), coroutine in stake_coroutines.items():
|
425
|
+
success = await coroutine
|
426
|
+
successes[ni][staking_address] = success
|
427
|
+
if json_output:
|
428
|
+
json_console.print(json.dumps({"staking_success": successes}))
|
400
429
|
|
401
430
|
|
402
431
|
# Helper functions
|