bittensor-cli 9.3.0__py3-none-any.whl → 9.4.1__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 +152 -43
- bittensor_cli/src/__init__.py +440 -441
- bittensor_cli/src/bittensor/subtensor_interface.py +19 -19
- bittensor_cli/src/bittensor/utils.py +6 -2
- bittensor_cli/src/commands/subnets/subnets.py +120 -1
- bittensor_cli/src/commands/sudo.py +4 -2
- bittensor_cli/version.py +12 -10
- {bittensor_cli-9.3.0.dist-info → bittensor_cli-9.4.1.dist-info}/METADATA +4 -3
- {bittensor_cli-9.3.0.dist-info → bittensor_cli-9.4.1.dist-info}/RECORD +12 -12
- {bittensor_cli-9.3.0.dist-info → bittensor_cli-9.4.1.dist-info}/WHEEL +1 -1
- {bittensor_cli-9.3.0.dist-info → bittensor_cli-9.4.1.dist-info}/entry_points.txt +0 -0
- {bittensor_cli-9.3.0.dist-info → bittensor_cli-9.4.1.dist-info}/top_level.txt +0 -0
@@ -238,25 +238,25 @@ class SubtensorInterface:
|
|
238
238
|
|
239
239
|
:return: Balance: The stake under the coldkey - hotkey pairing.
|
240
240
|
"""
|
241
|
-
alpha_shares = await
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
241
|
+
alpha_shares, hotkey_alpha, hotkey_shares = await asyncio.gather(
|
242
|
+
self.query(
|
243
|
+
module="SubtensorModule",
|
244
|
+
storage_function="Alpha",
|
245
|
+
params=[hotkey_ss58, coldkey_ss58, netuid],
|
246
|
+
block_hash=block_hash,
|
247
|
+
),
|
248
|
+
self.query(
|
249
|
+
module="SubtensorModule",
|
250
|
+
storage_function="TotalHotkeyAlpha",
|
251
|
+
params=[hotkey_ss58, netuid],
|
252
|
+
block_hash=block_hash,
|
253
|
+
),
|
254
|
+
self.query(
|
255
|
+
module="SubtensorModule",
|
256
|
+
storage_function="TotalHotkeyShares",
|
257
|
+
params=[hotkey_ss58, netuid],
|
258
|
+
block_hash=block_hash,
|
259
|
+
),
|
260
260
|
)
|
261
261
|
|
262
262
|
alpha_shares_as_float = fixed_to_float(alpha_shares or 0)
|
@@ -31,6 +31,7 @@ from bittensor_cli.src import defaults, Constants
|
|
31
31
|
|
32
32
|
if TYPE_CHECKING:
|
33
33
|
from bittensor_cli.src.bittensor.chain_data import SubnetHyperparameters
|
34
|
+
from rich.prompt import PromptBase
|
34
35
|
|
35
36
|
console = Console()
|
36
37
|
json_console = Console()
|
@@ -557,7 +558,10 @@ def format_error_message(error_message: Union[dict, Exception]) -> str:
|
|
557
558
|
err_type = error_message.get("type", err_type)
|
558
559
|
err_name = error_message.get("name", err_name)
|
559
560
|
err_docs = error_message.get("docs", [err_description])
|
560
|
-
|
561
|
+
if isinstance(err_docs, list):
|
562
|
+
err_description = " ".join(err_docs)
|
563
|
+
else:
|
564
|
+
err_description = err_docs
|
561
565
|
|
562
566
|
return f"Subtensor returned `{err_name}({err_type})` error. This means: `{err_description}`."
|
563
567
|
|
@@ -1007,7 +1011,7 @@ def retry_prompt(
|
|
1007
1011
|
rejection_text: str,
|
1008
1012
|
default="",
|
1009
1013
|
show_default=False,
|
1010
|
-
prompt_type=Prompt.ask,
|
1014
|
+
prompt_type: "PromptBase.ask" = Prompt.ask,
|
1011
1015
|
):
|
1012
1016
|
"""
|
1013
1017
|
Allows for asking prompts again if they do not meet a certain criteria (as defined in `rejection`)
|
@@ -10,7 +10,7 @@ from rich.progress import Progress, BarColumn, TextColumn
|
|
10
10
|
from rich.table import Column, Table
|
11
11
|
from rich import box
|
12
12
|
|
13
|
-
from bittensor_cli.src import COLOR_PALETTE
|
13
|
+
from bittensor_cli.src import COLOR_PALETTE, Constants
|
14
14
|
from bittensor_cli.src.bittensor.balances import Balance
|
15
15
|
from bittensor_cli.src.bittensor.extrinsics.registration import (
|
16
16
|
register_extrinsic,
|
@@ -34,6 +34,7 @@ from bittensor_cli.src.bittensor.utils import (
|
|
34
34
|
prompt_for_identity,
|
35
35
|
get_subnet_name,
|
36
36
|
unlock_key,
|
37
|
+
blocks_to_duration,
|
37
38
|
json_console,
|
38
39
|
)
|
39
40
|
|
@@ -2308,3 +2309,121 @@ async def get_identity(
|
|
2308
2309
|
else:
|
2309
2310
|
console.print(table)
|
2310
2311
|
return identity
|
2312
|
+
|
2313
|
+
|
2314
|
+
async def get_start_schedule(
|
2315
|
+
subtensor: "SubtensorInterface",
|
2316
|
+
netuid: int,
|
2317
|
+
) -> None:
|
2318
|
+
"""Fetch and display existing emission schedule information."""
|
2319
|
+
|
2320
|
+
if not await subtensor.subnet_exists(netuid):
|
2321
|
+
print_error(f"Subnet {netuid} does not exist.")
|
2322
|
+
return None
|
2323
|
+
block_hash = await subtensor.substrate.get_chain_head()
|
2324
|
+
registration_block, min_blocks_to_start, current_block = await asyncio.gather(
|
2325
|
+
subtensor.query(
|
2326
|
+
module="SubtensorModule",
|
2327
|
+
storage_function="NetworkRegisteredAt",
|
2328
|
+
params=[netuid],
|
2329
|
+
block_hash=block_hash,
|
2330
|
+
),
|
2331
|
+
subtensor.substrate.get_constant(
|
2332
|
+
module_name="SubtensorModule",
|
2333
|
+
constant_name="DurationOfStartCall",
|
2334
|
+
block_hash=block_hash,
|
2335
|
+
),
|
2336
|
+
subtensor.substrate.get_block_number(block_hash=block_hash),
|
2337
|
+
)
|
2338
|
+
|
2339
|
+
potential_start_block = registration_block + min_blocks_to_start
|
2340
|
+
if current_block < potential_start_block:
|
2341
|
+
blocks_to_wait = potential_start_block - current_block
|
2342
|
+
time_to_wait = blocks_to_duration(blocks_to_wait)
|
2343
|
+
|
2344
|
+
console.print(
|
2345
|
+
f"[blue]Subnet {netuid}[/blue]:\n"
|
2346
|
+
f"[blue]Registered at:[/blue] {registration_block}\n"
|
2347
|
+
f"[blue]Minimum start block:[/blue] {potential_start_block}\n"
|
2348
|
+
f"[blue]Current block:[/blue] {current_block}\n"
|
2349
|
+
f"[blue]Blocks remaining:[/blue] {blocks_to_wait}\n"
|
2350
|
+
f"[blue]Time to wait:[/blue] {time_to_wait}"
|
2351
|
+
)
|
2352
|
+
else:
|
2353
|
+
console.print(
|
2354
|
+
f"[blue]Subnet {netuid}[/blue]:\n"
|
2355
|
+
f"[blue]Registered at:[/blue] {registration_block}\n"
|
2356
|
+
f"[blue]Current block:[/blue] {current_block}\n"
|
2357
|
+
f"[blue]Minimum start block:[/blue] {potential_start_block}\n"
|
2358
|
+
f"[dark_sea_green3]Emission schedule can be started[/dark_sea_green3]"
|
2359
|
+
)
|
2360
|
+
|
2361
|
+
return
|
2362
|
+
|
2363
|
+
|
2364
|
+
async def start_subnet(
|
2365
|
+
wallet: "Wallet",
|
2366
|
+
subtensor: "SubtensorInterface",
|
2367
|
+
netuid: int,
|
2368
|
+
prompt: bool = False,
|
2369
|
+
) -> bool:
|
2370
|
+
"""Start a subnet's emission schedule"""
|
2371
|
+
|
2372
|
+
if not await subtensor.subnet_exists(netuid):
|
2373
|
+
print_error(f"Subnet {netuid} does not exist.")
|
2374
|
+
return False
|
2375
|
+
|
2376
|
+
subnet_owner = await subtensor.query(
|
2377
|
+
module="SubtensorModule",
|
2378
|
+
storage_function="SubnetOwner",
|
2379
|
+
params=[netuid],
|
2380
|
+
)
|
2381
|
+
if subnet_owner != wallet.coldkeypub.ss58_address:
|
2382
|
+
print_error(":cross_mark: This wallet doesn't own the specified subnet.")
|
2383
|
+
return False
|
2384
|
+
|
2385
|
+
if prompt:
|
2386
|
+
if not Confirm.ask(
|
2387
|
+
f"Are you sure you want to start subnet {netuid}'s emission schedule?"
|
2388
|
+
):
|
2389
|
+
return False
|
2390
|
+
|
2391
|
+
if not unlock_key(wallet).success:
|
2392
|
+
return False
|
2393
|
+
|
2394
|
+
with console.status(
|
2395
|
+
f":satellite: Starting subnet {netuid}'s emission schedule...", spinner="earth"
|
2396
|
+
):
|
2397
|
+
start_call = await subtensor.substrate.compose_call(
|
2398
|
+
call_module="SubtensorModule",
|
2399
|
+
call_function="start_call",
|
2400
|
+
call_params={"netuid": netuid},
|
2401
|
+
)
|
2402
|
+
|
2403
|
+
signed_ext = await subtensor.substrate.create_signed_extrinsic(
|
2404
|
+
call=start_call,
|
2405
|
+
keypair=wallet.coldkey,
|
2406
|
+
)
|
2407
|
+
|
2408
|
+
response = await subtensor.substrate.submit_extrinsic(
|
2409
|
+
extrinsic=signed_ext,
|
2410
|
+
wait_for_inclusion=True,
|
2411
|
+
wait_for_finalization=True,
|
2412
|
+
)
|
2413
|
+
|
2414
|
+
if await response.is_success:
|
2415
|
+
console.print(
|
2416
|
+
f":white_heavy_check_mark: [green]Successfully started subnet {netuid}'s emission schedule.[/green]"
|
2417
|
+
)
|
2418
|
+
return True
|
2419
|
+
else:
|
2420
|
+
error_msg = format_error_message(await response.error_message)
|
2421
|
+
if "FirstEmissionBlockNumberAlreadySet" in error_msg:
|
2422
|
+
console.print(
|
2423
|
+
f"[dark_sea_green3]Subnet {netuid} already has an emission schedule.[/dark_sea_green3]"
|
2424
|
+
)
|
2425
|
+
return True
|
2426
|
+
|
2427
|
+
await get_start_schedule(subtensor, netuid)
|
2428
|
+
print_error(f":cross_mark: Failed to start subnet: {error_msg}")
|
2429
|
+
return False
|
@@ -145,6 +145,7 @@ async def set_hyperparameter_extrinsic(
|
|
145
145
|
value: Optional[Union[str, bool, float, list[float]]],
|
146
146
|
wait_for_inclusion: bool = False,
|
147
147
|
wait_for_finalization: bool = True,
|
148
|
+
prompt: bool = True,
|
148
149
|
) -> bool:
|
149
150
|
"""Sets a hyperparameter for a specific subnetwork.
|
150
151
|
|
@@ -190,7 +191,7 @@ async def set_hyperparameter_extrinsic(
|
|
190
191
|
":cross_mark: [red]Invalid hyperparameter specified.[/red]"
|
191
192
|
)
|
192
193
|
return False
|
193
|
-
if sudo_:
|
194
|
+
if sudo_ and prompt:
|
194
195
|
if not Confirm.ask(
|
195
196
|
"This hyperparam is only settable by root sudo users. If you are not, this will fail. Please confirm"
|
196
197
|
):
|
@@ -574,6 +575,7 @@ async def sudo_set_hyperparameter(
|
|
574
575
|
netuid: int,
|
575
576
|
param_name: str,
|
576
577
|
param_value: Optional[str],
|
578
|
+
prompt: bool,
|
577
579
|
json_output: bool,
|
578
580
|
):
|
579
581
|
"""Set subnet hyperparameters."""
|
@@ -602,7 +604,7 @@ async def sudo_set_hyperparameter(
|
|
602
604
|
)
|
603
605
|
return False
|
604
606
|
success = await set_hyperparameter_extrinsic(
|
605
|
-
subtensor, wallet, netuid, param_name, value
|
607
|
+
subtensor, wallet, netuid, param_name, value, prompt=prompt
|
606
608
|
)
|
607
609
|
if json_output:
|
608
610
|
return success
|
bittensor_cli/version.py
CHANGED
@@ -3,18 +3,20 @@ import re
|
|
3
3
|
|
4
4
|
|
5
5
|
def version_as_int(version):
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
match = re.match(r"^\d+\.\d+\.\d+", version)
|
7
|
+
if not match:
|
8
|
+
raise ValueError(f"Invalid version format: {version}")
|
9
|
+
core_version = match.group(0)
|
10
|
+
version_split = core_version.split(".")
|
11
|
+
version_info = tuple(int(part) for part in version_split)
|
12
|
+
version_int_base = 1000
|
13
|
+
assert max(version_info) < version_int_base
|
11
14
|
|
12
|
-
|
13
|
-
e * (
|
15
|
+
version_as_int_: int = sum(
|
16
|
+
e * (version_int_base**i) for i, e in enumerate(reversed(version_info))
|
14
17
|
)
|
15
|
-
assert
|
16
|
-
|
17
|
-
return __version_as_int__
|
18
|
+
assert version_as_int_ < 2**31 # fits in int32
|
19
|
+
return version_as_int_
|
18
20
|
|
19
21
|
|
20
22
|
__version__ = importlib.metadata.version("bittensor-cli")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: bittensor-cli
|
3
|
-
Version: 9.
|
3
|
+
Version: 9.4.1
|
4
4
|
Summary: Bittensor CLI
|
5
5
|
Author: bittensor.com
|
6
6
|
Project-URL: homepage, https://github.com/opentensor/btcli
|
@@ -12,6 +12,7 @@ Requires-Dist: async-property==0.2.2
|
|
12
12
|
Requires-Dist: async-substrate-interface>=1.1.0
|
13
13
|
Requires-Dist: aiohttp~=3.10.2
|
14
14
|
Requires-Dist: backoff~=2.2.1
|
15
|
+
Requires-Dist: click<8.2.0
|
15
16
|
Requires-Dist: GitPython>=3.0.0
|
16
17
|
Requires-Dist: fuzzywuzzy~=0.18.0
|
17
18
|
Requires-Dist: netaddr~=1.3.0
|
@@ -29,7 +30,7 @@ Requires-Dist: plotille>=5.0.0
|
|
29
30
|
Requires-Dist: pywry>=0.6.2
|
30
31
|
Requires-Dist: plotly>=6.0.0
|
31
32
|
Provides-Extra: cuda
|
32
|
-
Requires-Dist: torch<
|
33
|
+
Requires-Dist: torch<3.0,>=1.13.1; extra == "cuda"
|
33
34
|
|
34
35
|
<div align="center">
|
35
36
|
|
@@ -72,7 +73,7 @@ Installation steps are described below. For a full documentation on how to use `
|
|
72
73
|
|
73
74
|
## Install on macOS and Linux
|
74
75
|
|
75
|
-
You can install `btcli` on your local machine directly from source, or from
|
76
|
+
You can install `btcli` on your local machine directly from source, or from PyPI. **Make sure you verify your installation after you install**:
|
76
77
|
|
77
78
|
|
78
79
|
### Install from PyPI
|
@@ -1,21 +1,21 @@
|
|
1
1
|
bittensor_cli/__init__.py,sha256=Lpv4NkbAQgwrfqFOnTMuR_S-fqGdaWCSLhxnFnGTHM0,1232
|
2
|
-
bittensor_cli/cli.py,sha256=
|
2
|
+
bittensor_cli/cli.py,sha256=3tanMizgAIw0b8n-vgqw5GOZwcpEBDHhfarKOzMt4aM,217087
|
3
3
|
bittensor_cli/doc_generation_helper.py,sha256=GexqjEIKulWg84hpNBEchJ840oOgOi7DWpt447nsdNI,91
|
4
|
-
bittensor_cli/version.py,sha256=
|
5
|
-
bittensor_cli/src/__init__.py,sha256=
|
4
|
+
bittensor_cli/version.py,sha256=dU1xsa3mG5FPdhzvqlzDByNcCHmzcFQH3q1pQr4u76g,720
|
5
|
+
bittensor_cli/src/__init__.py,sha256=dRBcdUWIqHTyusuvuhP4PrRc9MWmnmj76WDWLHxhjmA,33795
|
6
6
|
bittensor_cli/src/bittensor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
bittensor_cli/src/bittensor/balances.py,sha256=q5KkxF8wmUguWAFddEKstfDKTxPe5ISHpT6br8x32rc,11148
|
8
8
|
bittensor_cli/src/bittensor/chain_data.py,sha256=yOQyPZ472BlfhAfaemdi22qunEGHlVvugRdUeYpZxwQ,41663
|
9
9
|
bittensor_cli/src/bittensor/minigraph.py,sha256=BIzmSVLfBYiRAeGD_i1LAC8Cw7zxp38a91SIFEPMqYc,10479
|
10
10
|
bittensor_cli/src/bittensor/networking.py,sha256=pZLMs8YXpZzDMLXWMBb_Bj6TVkm_q9khyY-lnbwVMuE,462
|
11
|
-
bittensor_cli/src/bittensor/subtensor_interface.py,sha256=
|
12
|
-
bittensor_cli/src/bittensor/utils.py,sha256=
|
11
|
+
bittensor_cli/src/bittensor/subtensor_interface.py,sha256=StNlKxk348cq-nEU-5qye0yMTG5snLU_whw1dALRX2I,58976
|
12
|
+
bittensor_cli/src/bittensor/utils.py,sha256=vetZCwy-LSJjYj58f_5wIuTi2A2sHyCMjrHR1DqT6bY,47729
|
13
13
|
bittensor_cli/src/bittensor/extrinsics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
14
|
bittensor_cli/src/bittensor/extrinsics/registration.py,sha256=mZt6z8PRK5MaIczLygmVvAUnfl_dl5zDF7ysIFkwHvs,64511
|
15
15
|
bittensor_cli/src/bittensor/extrinsics/root.py,sha256=rVogWhT28NJ1CrVXtbq_Pyi7etB_zTZicbjiHAHLdSs,19214
|
16
16
|
bittensor_cli/src/bittensor/extrinsics/transfer.py,sha256=vxLzKQkTSsV-ark7WAJjEN4QasEJI_9MXt2Dg8eR2j4,8569
|
17
17
|
bittensor_cli/src/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
-
bittensor_cli/src/commands/sudo.py,sha256=
|
18
|
+
bittensor_cli/src/commands/sudo.py,sha256=or_wkOMf4RAE64pp2SiX2ybeN0V89hlsEf86cyLPsV4,33062
|
19
19
|
bittensor_cli/src/commands/view.py,sha256=2MdhWWbY9rwGqDilzs8r2ioa0l2GzrYxe8pKkavEVWs,109517
|
20
20
|
bittensor_cli/src/commands/wallets.py,sha256=N3ERh4Iw0juJSy9-AUQaTC1SfZsklD-lxCcFfODfcGE,73142
|
21
21
|
bittensor_cli/src/commands/weights.py,sha256=BCJm_mlw0pVK4YEZuEMqQBpvvOoB7B1rzdvMeN3uTfM,16503
|
@@ -27,9 +27,9 @@ bittensor_cli/src/commands/stake/move.py,sha256=AVeo0l4bvGAtjbdzx2Fn7_-jiI28B7LM
|
|
27
27
|
bittensor_cli/src/commands/stake/remove.py,sha256=l7TtLK2Z6-TJ5-DEwUzm6HT2GQC-MhKZS9SONS9DKtA,49902
|
28
28
|
bittensor_cli/src/commands/subnets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
29
29
|
bittensor_cli/src/commands/subnets/price.py,sha256=O8oK12hCtm1asQGx2MR1xtYA9ygkklhFtXvBON4DcGM,30069
|
30
|
-
bittensor_cli/src/commands/subnets/subnets.py,sha256=
|
31
|
-
bittensor_cli-9.
|
32
|
-
bittensor_cli-9.
|
33
|
-
bittensor_cli-9.
|
34
|
-
bittensor_cli-9.
|
35
|
-
bittensor_cli-9.
|
30
|
+
bittensor_cli/src/commands/subnets/subnets.py,sha256=QJuFm9UGG9EBeK9IjtBFpASV1qV6XEdz1L96Ka8zfB4,93692
|
31
|
+
bittensor_cli-9.4.1.dist-info/METADATA,sha256=Jvz2rvjzoHPj2ygRVI9GGXmSY8-q4p2PJJusejKw9Z8,6482
|
32
|
+
bittensor_cli-9.4.1.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
33
|
+
bittensor_cli-9.4.1.dist-info/entry_points.txt,sha256=hBTLGLbVxmAKy69XSKaUZvjTCmyEzDGZKq4S8UOto8I,49
|
34
|
+
bittensor_cli-9.4.1.dist-info/top_level.txt,sha256=DvgvXpmTtI_Q1BbDZMlK90LFcGFCreN1daViEPV2iFw,14
|
35
|
+
bittensor_cli-9.4.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|