Skip to content

Commit 025792c

Browse files
authored
Merge pull request #2892 from opentensor/release/9.6.1
Release/9.6.1
2 parents f54004f + fb51b48 commit 025792c

19 files changed

+199
-101
lines changed

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
# Changelog
22

3-
## 9.5.0 /2025-05-15
3+
## 9.6.1 /2025-05-22
4+
5+
## What's Changed
6+
* Release/9.6.0 by @ibraheem-abe in https://github.com/opentensor/bittensor/pull/2882
7+
* Add stake before check `validator_permit` by @basfroman in https://github.com/opentensor/bittensor/pull/2884
8+
* Add defaults for endpoint and network from local env by @basfroman in https://github.com/opentensor/bittensor/pull/2886
9+
* Improve error message by @basfroman in https://github.com/opentensor/bittensor/pull/2888
10+
* Make `unstake` and `unstake_multiple` for all Alphas more clear by @basfroman in https://github.com/opentensor/bittensor/pull/2885
11+
* fix publish metadata by @basfroman in https://github.com/opentensor/bittensor/pull/2890
12+
13+
**Full Changelog**: https://github.com/opentensor/bittensor/compare/v9.6.0...v9.6.1
14+
15+
## 9.6.0 /2025-05-15
416

517
* Add manual way to show the size of virtual environments in the PR by @basfroman in https://github.com/opentensor/bittensor/pull/2875
618
* Improve `Monitor SDK Requirements Size` workflow by @basfroman in https://github.com/opentensor/bittensor/pull/2878

bittensor/core/async_subtensor.py

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3119,6 +3119,9 @@ async def wait_for_block(self, block: Optional[int] = None):
31193119
bool: True if the target block was reached, False if timeout occurred.
31203120
31213121
Example:
3122+
import bittensor as bt
3123+
subtensor = bt.Subtensor()
3124+
31223125
await subtensor.wait_for_block() # Waits for next block
31233126
await subtensor.wait_for_block(block=1234) # Waits for a specific block
31243127
"""
@@ -3380,27 +3383,27 @@ async def add_stake(
33803383
period: Optional[int] = None,
33813384
) -> bool:
33823385
"""
3383-
Adds the specified amount of stake to a neuron identified by the hotkey ``SS58`` address.
3384-
Staking is a fundamental process in the Bittensor network that enables neurons to participate actively and earn
3385-
incentives.
3386+
Adds a stake from the specified wallet to the neuron identified by the SS58 address of its hotkey in specified subnet.
3387+
Staking is a fundamental process in the Bittensor network that enables neurons to participate actively and earn incentives.
33863388
33873389
Args:
3388-
wallet (bittensor_wallet.Wallet): The wallet to be used for staking.
3389-
hotkey_ss58 (Optional[str]): The ``SS58`` address of the hotkey associated with the neuron.
3390-
netuid: subnet UID
3391-
amount (Balance): The amount of TAO to stake.
3392-
wait_for_inclusion (bool): Waits for the transaction to be included in a block.
3393-
wait_for_finalization (bool): Waits for the transaction to be finalized on the blockchain.
3394-
safe_staking (bool): If true, enables price safety checks to protect against fluctuating prices. The stake
3395-
will only execute if the price change doesn't exceed the rate tolerance. Default is False.
3396-
allow_partial_stake (bool): If true and safe_staking is enabled, allows partial staking when
3397-
the full amount would exceed the price threshold. If false, the entire stake fails if it would
3398-
exceed the threshold. Default is False.
3399-
rate_tolerance (float): The maximum allowed price change ratio when staking. For example,
3400-
0.005 = 0.5% maximum price increase. Only used when safe_staking is True. Default is 0.005.
3401-
period (Optional[int]): The number of blocks during which the transaction will remain valid after it's
3402-
submitted. If the transaction is not included in a block within that number of blocks, it will expire
3403-
and be rejected. You can think of it as an expiration date for the transaction.
3390+
wallet: The wallet to be used for staking.
3391+
hotkey_ss58: The SS58 address of the hotkey associated with the neuron to which you intend to delegate your
3392+
stake. If not specified, the wallet's hotkey will be used. Defaults to ``None``.
3393+
netuid: The unique identifier of the subnet to which the neuron belongs.
3394+
amount: The amount of TAO to stake.
3395+
wait_for_inclusion: Waits for the transaction to be included in a block. Defaults to ``True``.
3396+
wait_for_finalization: Waits for the transaction to be finalized on the blockchain. Defaults to ``False``.
3397+
safe_staking: If true, enables price safety checks to protect against fluctuating prices. The stake will
3398+
only execute if the price change doesn't exceed the rate tolerance. Default is ``False``.
3399+
allow_partial_stake: If true and safe_staking is enabled, allows partial staking when the full amount would
3400+
exceed the price tolerance. If false, the entire stake fails if it would exceed the tolerance.
3401+
Default is ``False``.
3402+
rate_tolerance: The maximum allowed price change ratio when staking. For example,
3403+
0.005 = 0.5% maximum price increase. Only used when safe_staking is True. Default is ``0.005``.
3404+
period: The number of blocks during which the transaction will remain valid after it's submitted. If the
3405+
transaction is not included in a block within that number of blocks, it will expire and be rejected. You
3406+
can think of it as an expiration date for the transaction. Defaults to ``None``.
34043407
34053408
Returns:
34063409
bool: ``True`` if the staking is successful, False otherwise.
@@ -4428,6 +4431,7 @@ async def unstake(
44284431
allow_partial_stake: bool = False,
44294432
rate_tolerance: float = 0.005,
44304433
period: Optional[int] = None,
4434+
unstake_all: bool = False,
44314435
) -> bool:
44324436
"""
44334437
Removes a specified amount of stake from a single hotkey account. This function is critical for adjusting
@@ -4451,6 +4455,7 @@ async def unstake(
44514455
period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If
44524456
the transaction is not included in a block within that number of blocks, it will expire and be rejected.
44534457
You can think of it as an expiration date for the transaction.
4458+
unstake_all: If true, unstakes all tokens. Default is ``False``. If `True` amount is ignored.
44544459
44554460
Returns:
44564461
bool: ``True`` if the unstaking process is successful, False otherwise.
@@ -4471,6 +4476,7 @@ async def unstake(
44714476
allow_partial_stake=allow_partial_stake,
44724477
rate_tolerance=rate_tolerance,
44734478
period=period,
4479+
unstake_all=unstake_all,
44744480
)
44754481

44764482
async def unstake_multiple(
@@ -4482,6 +4488,7 @@ async def unstake_multiple(
44824488
wait_for_inclusion: bool = True,
44834489
wait_for_finalization: bool = False,
44844490
period: Optional[int] = None,
4491+
unstake_all: bool = False,
44854492
) -> bool:
44864493
"""
44874494
Performs batch unstaking from multiple hotkey accounts, allowing a neuron to reduce its staked amounts
@@ -4499,6 +4506,7 @@ async def unstake_multiple(
44994506
period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted. If
45004507
the transaction is not included in a block within that number of blocks, it will expire and be rejected.
45014508
You can think of it as an expiration date for the transaction.
4509+
unstake_all: If true, unstakes all tokens. Default is ``False``. If `True` amounts are ignored.
45024510
45034511
Returns:
45044512
bool: ``True`` if the batch unstaking is successful, False otherwise.
@@ -4515,6 +4523,7 @@ async def unstake_multiple(
45154523
wait_for_inclusion=wait_for_inclusion,
45164524
wait_for_finalization=wait_for_finalization,
45174525
period=period,
4526+
unstake_all=unstake_all,
45184527
)
45194528

45204529

bittensor/core/extrinsics/asyncex/serving.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ async def publish_metadata(
282282
success, message = await subtensor.sign_and_send_extrinsic(
283283
call=call,
284284
wallet=wallet,
285+
sign_with="hotkey",
285286
wait_for_inclusion=wait_for_inclusion,
286287
wait_for_finalization=wait_for_finalization,
287288
period=period,

bittensor/core/extrinsics/asyncex/staking.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,27 @@ async def add_stake_extrinsic(
2828
period: Optional[int] = None,
2929
) -> bool:
3030
"""
31-
Adds the specified amount of stake to passed hotkey `uid`.
31+
Adds a stake from the specified wallet to the neuron identified by the SS58 address of its hotkey in specified subnet.
32+
Staking is a fundamental process in the Bittensor network that enables neurons to participate actively and earn incentives.
3233
3334
Arguments:
34-
subtensor: the initialized SubtensorInterface object to use
35+
subtensor: Subtensor instance with the connection to the chain.
3536
wallet: Bittensor wallet object.
3637
old_balance: the balance prior to the staking
37-
hotkey_ss58: The `ss58` address of the hotkey account to stake to defaults to the wallet's hotkey.
38-
netuid: The netuid of the stake to be added
39-
amount: Amount to stake as Bittensor balance, `None` if staking all.
38+
hotkey_ss58: The `ss58` address of the hotkey account to stake to default to the wallet's hotkey. If not
39+
specified, the wallet's hotkey will be used. Defaults to ``None``.
40+
netuid: The unique identifier of the subnet to which the neuron belongs.
41+
amount: Amount to stake as Bittensor balance in TAO always, `None` if staking all. Defaults is ``None``.
4042
wait_for_inclusion: If set, waits for the extrinsic to enter a block before returning `True`, or returns
41-
`False` if the extrinsic fails to enter the block within the timeout.
43+
`False` if the extrinsic fails to enter the block within the timeout. Defaults to ``True``.
4244
wait_for_finalization: If set, waits for the extrinsic to be finalized on the chain before returning `True`,
43-
or returns `False` if the extrinsic fails to be finalized within the timeout.
44-
safe_staking: If set, uses safe staking logic
45-
allow_partial_stake: If set, allows partial stake
46-
rate_tolerance: The rate tolerance for safe staking
45+
or returns `False` if the extrinsic fails to be finalized within the timeout. Defaults to ``False``.
46+
safe_staking: If True, enables price safety checks. Default is ``False``.
47+
allow_partial_stake: If True, allows partial unstaking if price tolerance exceeded. Default is ``False``.
48+
rate_tolerance: Maximum allowed price increase percentage (0.005 = 0.5%). Default is ``0.005``.
4749
period: The number of blocks during which the transaction will remain valid after it's submitted. If
4850
the transaction is not included in a block within that number of blocks, it will expire and be rejected.
49-
You can think of it as an expiration date for the transaction.
51+
You can think of it as an expiration date for the transaction. Defaults to ``None``.
5052
5153
Returns:
5254
success: Flag is `True` if extrinsic was finalized or included in the block. If we did not wait for
@@ -93,7 +95,6 @@ async def add_stake_extrinsic(
9395
)
9496
else:
9597
staking_balance = amount
96-
staking_balance.set_unit(netuid)
9798

9899
# Leave existential balance to keep key alive.
99100
if staking_balance > old_balance - existential_deposit:

bittensor/core/extrinsics/asyncex/unstaking.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ async def unstake_extrinsic(
2525
allow_partial_stake: bool = False,
2626
rate_tolerance: float = 0.005,
2727
period: Optional[int] = None,
28+
unstake_all: bool = False,
2829
) -> bool:
2930
"""Removes stake into the wallet coldkey from the specified hotkey ``uid``.
3031
@@ -45,11 +46,15 @@ async def unstake_extrinsic(
4546
period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted.
4647
If the transaction is not included in a block within that number of blocks, it will expire and be rejected.
4748
You can think of it as an expiration date for the transaction.
49+
unstake_all: If true, unstakes all tokens. Default is ``False``.
4850
4951
Returns:
5052
success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for
5153
finalization / inclusion, the response is ``True``.
5254
"""
55+
if amount and unstake_all:
56+
raise ValueError("Cannot specify both `amount` and `unstake_all`.")
57+
5358
# Decrypt keys,
5459
if not (unlock := unlock_key(wallet)).success:
5560
logging.error(unlock.message)
@@ -204,6 +209,7 @@ async def unstake_multiple_extrinsic(
204209
wait_for_inclusion: bool = True,
205210
wait_for_finalization: bool = False,
206211
period: Optional[int] = None,
212+
unstake_all: bool = False,
207213
) -> bool:
208214
"""Removes stake from each ``hotkey_ss58`` in the list, using each amount, to a common coldkey.
209215
@@ -220,11 +226,15 @@ async def unstake_multiple_extrinsic(
220226
period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted.
221227
If the transaction is not included in a block within that number of blocks, it will expire and be rejected.
222228
You can think of it as an expiration date for the transaction.
229+
unstake_all: If true, unstakes all tokens. Default is ``False``.
223230
224231
Returns:
225232
success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. Flag is ``True`` if any
226233
wallet was unstaked. If we did not wait for finalization / inclusion, the response is ``True``.
227234
"""
235+
if amounts and unstake_all:
236+
raise ValueError("Cannot specify both `amounts` and `unstake_all`.")
237+
228238
if not isinstance(hotkey_ss58s, list) or not all(
229239
isinstance(hotkey_ss58, str) for hotkey_ss58 in hotkey_ss58s
230240
):

bittensor/core/extrinsics/serving.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ def publish_metadata(
278278
success, message = subtensor.sign_and_send_extrinsic(
279279
call=call,
280280
wallet=wallet,
281+
sign_with="hotkey",
281282
wait_for_inclusion=wait_for_inclusion,
282283
wait_for_finalization=wait_for_finalization,
283284
period=period,

bittensor/core/extrinsics/staking.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,26 @@ def add_stake_extrinsic(
2626
period: Optional[int] = None,
2727
) -> bool:
2828
"""
29-
Adds the specified amount of stake to passed hotkey `uid`.
29+
Adds a stake from the specified wallet to the neuron identified by the SS58 address of its hotkey in specified subnet.
30+
Staking is a fundamental process in the Bittensor network that enables neurons to participate actively and earn incentives.
3031
3132
Arguments:
32-
subtensor: the Subtensor object to use
33+
subtensor: Subtensor instance with the connection to the chain.
3334
wallet: Bittensor wallet object.
34-
hotkey_ss58: The `ss58` address of the hotkey account to stake to default to the wallet's hotkey.
35-
netuid (Optional[int]): Subnet unique ID.
36-
amount: Amount to stake as Bittensor balance, `None` if staking all.
35+
hotkey_ss58: The `ss58` address of the hotkey account to stake to default to the wallet's hotkey. If not
36+
specified, the wallet's hotkey will be used. Defaults to ``None``.
37+
netuid: The unique identifier of the subnet to which the neuron belongs.
38+
amount: Amount to stake as Bittensor balance in TAO always, `None` if staking all. Defaults is ``None``.
3739
wait_for_inclusion: If set, waits for the extrinsic to enter a block before returning `True`, or returns
38-
`False` if the extrinsic fails to enter the block within the timeout.
40+
`False` if the extrinsic fails to enter the block within the timeout. Defaults to ``True``.
3941
wait_for_finalization: If set, waits for the extrinsic to be finalized on the chain before returning `True`,
40-
or returns `False` if the extrinsic fails to be finalized within the timeout.
41-
safe_staking (bool): If true, enables price safety checks
42-
allow_partial_stake (bool): If true, allows partial unstaking if price tolerance exceeded
43-
rate_tolerance (float): Maximum allowed price increase percentage (0.005 = 0.5%)
42+
or returns `False` if the extrinsic fails to be finalized within the timeout. Defaults to ``False``.
43+
safe_staking: If True, enables price safety checks. Default is ``False``.
44+
allow_partial_stake: If True, allows partial unstaking if price tolerance exceeded. Default is ``False``.
45+
rate_tolerance: Maximum allowed price increase percentage (0.005 = 0.5%). Default is ``0.005``.
4446
period: The number of blocks during which the transaction will remain valid after it's submitted. If
4547
the transaction is not included in a block within that number of blocks, it will expire and be rejected.
46-
You can think of it as an expiration date for the transaction.
48+
You can think of it as an expiration date for the transaction. Defaults to ``None``.
4749
4850
Returns:
4951
success: Flag is `True` if extrinsic was finalized or included in the block. If we did not wait for
@@ -87,14 +89,11 @@ def add_stake_extrinsic(
8789
)
8890
else:
8991
staking_balance = amount
90-
staking_balance.set_unit(netuid)
9192

9293
# Leave existential balance to keep key alive.
9394
if staking_balance > old_balance - existential_deposit:
9495
# If we are staking all, we need to leave at least the existential deposit.
9596
staking_balance = old_balance - existential_deposit
96-
else:
97-
staking_balance = staking_balance
9897

9998
# Check enough to stake.
10099
if staking_balance > old_balance:
@@ -200,7 +199,7 @@ def add_stake_extrinsic(
200199

201200
except SubstrateRequestException as error:
202201
logging.error(
203-
f":cross_mark: [red]Add Stake Error: {format_error_message((error))}[/red]"
202+
f":cross_mark: [red]Add Stake Error: {format_error_message(error)}[/red]"
204203
)
205204
return False
206205

bittensor/core/extrinsics/unstaking.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def unstake_extrinsic(
2424
allow_partial_stake: bool = False,
2525
rate_tolerance: float = 0.005,
2626
period: Optional[int] = None,
27+
unstake_all: bool = False,
2728
) -> bool:
2829
"""Removes stake into the wallet coldkey from the specified hotkey ``uid``.
2930
@@ -44,11 +45,15 @@ def unstake_extrinsic(
4445
period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted.
4546
If the transaction is not included in a block within that number of blocks, it will expire and be rejected.
4647
You can think of it as an expiration date for the transaction.
48+
unstake_all: If true, unstakes all tokens. Default is ``False``.
4749
4850
Returns:
4951
success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. If we did not wait for
5052
finalization / inclusion, the response is ``True``.
5153
"""
54+
if amount and unstake_all:
55+
raise ValueError("Cannot specify both `amount` and `unstake_all`.")
56+
5257
# Decrypt keys,
5358
if not (unlock := unlock_key(wallet)).success:
5459
logging.error(unlock.message)
@@ -201,6 +206,7 @@ def unstake_multiple_extrinsic(
201206
wait_for_inclusion: bool = True,
202207
wait_for_finalization: bool = False,
203208
period: Optional[int] = None,
209+
unstake_all: bool = False,
204210
) -> bool:
205211
"""Removes stake from each ``hotkey_ss58`` in the list, using each amount, to a common coldkey.
206212
@@ -217,11 +223,14 @@ def unstake_multiple_extrinsic(
217223
period (Optional[int]): The number of blocks during which the transaction will remain valid after it's submitted.
218224
If the transaction is not included in a block within that number of blocks, it will expire and be rejected.
219225
You can think of it as an expiration date for the transaction.
226+
unstake_all: If true, unstakes all tokens. Default is ``False``.
220227
221228
Returns:
222229
success (bool): Flag is ``True`` if extrinsic was finalized or included in the block. Flag is ``True`` if any
223230
wallet was unstaked. If we did not wait for finalization / inclusion, the response is ``True``.
224231
"""
232+
if amounts and unstake_all:
233+
raise ValueError("Cannot specify both `amounts` and `unstake_all`.")
225234

226235
if not isinstance(hotkey_ss58s, list) or not all(
227236
isinstance(hotkey_ss58, str) for hotkey_ss58 in hotkey_ss58s

0 commit comments

Comments
 (0)