Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bittensor/core/extrinsics/staking.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@ def _check_threshold_amount(
if amount is None:
# Stake it all.
staking_balance = Balance.from_tao(old_balance.tao)
elif not isinstance(amount, Balance):
staking_balance = Balance.from_tao(amount)
else:
staking_balance = Balance.from_tao(amount.tao)
staking_balance = amount

# Leave existential balance to keep key alive.
if staking_balance > old_balance - existential_deposit:
Expand Down
55 changes: 28 additions & 27 deletions tests/unit_tests/extrinsics/test_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
def mock_subtensor(mocker):
mock = mocker.MagicMock(spec=Subtensor)
mock.network = "magic_mock"
mock.substrate = mocker.Mock()
return mock


Expand All @@ -30,17 +31,17 @@ def mock_wallet(mocker):
(
False,
True,
[False, True],
[False, 1],
True,
True,
), # Registration succeeds with user confirmation
(False, True, [False, False], False, None), # Registration fails
(False, True, [False, None], False, False), # Registration fails
(
False,
True,
[False, False],
[False, None],
True,
None,
False,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

root.root_register_extrinsic no longer returns no response (only True/False)

), # Registration succeeds but neuron not found
],
ids=[
Expand All @@ -61,13 +62,19 @@ def test_root_register_extrinsic(
mocker,
):
# Arrange
mock_subtensor.is_hotkey_registered.side_effect = hotkey_registered
mock_subtensor.is_hotkey_registered.return_value = hotkey_registered[0]

# Preps
mock_register = mocker.Mock(
mocked_sign_and_send_extrinsic = mocker.patch.object(
mock_subtensor,
"sign_and_send_extrinsic",
return_value=(registration_success, "Error registering")
)
root._do_root_register = mock_register
mocker.patch.object(
mock_subtensor.substrate,
"query",
return_value=hotkey_registered[1],
)

# Act
result = root.root_register_extrinsic(
Expand All @@ -80,7 +87,17 @@ def test_root_register_extrinsic(
assert result == expected_result

if not hotkey_registered[0]:
mock_register.assert_called_once()
mock_subtensor.substrate.compose_call.assert_called_once_with(
call_module="SubtensorModule",
call_function="root_register",
call_params={"hotkey": "fake_hotkey_address"},
)
mocked_sign_and_send_extrinsic.assert_called_once_with(
mock_subtensor.substrate.compose_call.return_value,
wallet=mock_wallet,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization
)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -115,21 +132,13 @@ def test_root_register_extrinsic(
[0.5, 0.5],
False,
), # Failure - setting weights failed
(
True,
False,
[],
[],
False,
), # Exception catched - ValueError 'min() arg is an empty sequence'
],
ids=[
"success-weights-set",
"success-not-wait",
"success-large-value",
"success-single-value",
"failure-setting-weights",
"failure-value-error-exception",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only handle SubstrateRequestException

],
)
def test_set_root_weights_extrinsic(
Expand All @@ -146,8 +155,9 @@ def test_set_root_weights_extrinsic(
root._do_set_root_weights = mocker.Mock(
return_value=(expected_success, "Mock error")
)
mock_subtensor.min_allowed_weights = mocker.Mock(return_value=0)
mock_subtensor.max_weight_limit = mocker.Mock(return_value=1)
root._get_limits = mocker.Mock(
return_value=(0, 1),
)

# Call
result = root.set_root_weights_extrinsic(
Expand Down Expand Up @@ -200,22 +210,13 @@ def test_set_root_weights_extrinsic(
None,
False,
), # Failure - setting weights failed
(
True,
False,
[],
[],
False,
False,
), # Exception catched - ValueError 'min() arg is an empty sequence'
],
ids=[
"success-weights-set",
"success-not-wait",
"success-large-value",
"success-single-value",
"failure-setting-weights",
"failure-value-error-exception",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only handle SubstrateRequestException

],
)
def test_set_root_weights_extrinsic_torch(
Expand Down
116 changes: 82 additions & 34 deletions tests/unit_tests/extrinsics/test_staking.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
from bittensor.core.extrinsics import staking
from bittensor.utils.balance import Balance


def test_add_stake_extrinsic(mocker):
"""Verify that sync `add_stake_extrinsic` method calls proper async method."""
# Preps
fake_subtensor = mocker.Mock()
fake_wallet = mocker.Mock()
fake_subtensor = mocker.Mock(
**{
"get_balance.return_value": Balance(10),
"get_existential_deposit.return_value": Balance(1),
"get_hotkey_owner.return_value": "hotkey_owner",
"sign_and_send_extrinsic.return_value": (True, ""),
}
)
fake_wallet = mocker.Mock(
**{
"coldkeypub.ss58_address": "hotkey_owner",
}
)
hotkey_ss58 = "hotkey"
amount = 1.1
wait_for_inclusion = True
wait_for_finalization = True

mocked_execute_coroutine = mocker.patch.object(staking, "execute_coroutine")
mocked_add_stake_extrinsic = mocker.Mock()
staking.async_add_stake_extrinsic = mocked_add_stake_extrinsic

# Call
result = staking.add_stake_extrinsic(
subtensor=fake_subtensor,
Expand All @@ -26,35 +34,62 @@ def test_add_stake_extrinsic(mocker):
)

# Asserts
mocked_execute_coroutine.assert_called_once_with(
coroutine=mocked_add_stake_extrinsic.return_value,
event_loop=fake_subtensor.event_loop,
assert result is True

fake_subtensor.substrate.compose_call.assert_called_once_with(
call_module="SubtensorModule",
call_function="add_stake",
call_params={
"hotkey": "hotkey",
"amount_staked": 9,
},
)
mocked_add_stake_extrinsic.assert_called_once_with(
subtensor=fake_subtensor.async_subtensor,
wallet=fake_wallet,
hotkey_ss58=hotkey_ss58,
amount=amount,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
fake_subtensor.sign_and_send_extrinsic.assert_called_once_with(
fake_subtensor.substrate.compose_call.return_value,
fake_wallet,
True,
True,
)
assert result == mocked_execute_coroutine.return_value


def test_add_stake_multiple_extrinsic(mocker):
"""Verify that sync `add_stake_multiple_extrinsic` method calls proper async method."""
# Preps
fake_subtensor = mocker.Mock()
fake_wallet = mocker.Mock()
fake_subtensor = mocker.Mock(
**{
"get_balance.return_value": Balance(10.0),
"sign_and_send_extrinsic.return_value": (True, ""),
"substrate.query_multi.return_value": [
(
mocker.Mock(
**{
"params": ["hotkey1"],
},
),
0,
),
(
mocker.Mock(
**{
"params": ["hotkey2"],
},
),
0,
),
],
"substrate.query.return_value": 0,
}
)
fake_wallet = mocker.Mock(
**{
"coldkeypub.ss58_address": "hotkey_owner",
}
)
hotkey_ss58s = ["hotkey1", "hotkey2"]
amounts = [1.1, 2.2]
wait_for_inclusion = True
wait_for_finalization = True

mocked_execute_coroutine = mocker.patch.object(staking, "execute_coroutine")
mocked_add_stake_multiple_extrinsic = mocker.Mock()
staking.async_add_stake_multiple_extrinsic = mocked_add_stake_multiple_extrinsic

# Call
result = staking.add_stake_multiple_extrinsic(
subtensor=fake_subtensor,
Expand All @@ -66,16 +101,29 @@ def test_add_stake_multiple_extrinsic(mocker):
)

# Asserts
mocked_execute_coroutine.assert_called_once_with(
coroutine=mocked_add_stake_multiple_extrinsic.return_value,
event_loop=fake_subtensor.event_loop,
assert result is True
assert fake_subtensor.substrate.compose_call.call_count == 2
assert fake_subtensor.sign_and_send_extrinsic.call_count == 2

fake_subtensor.substrate.compose_call.assert_any_call(
call_module="SubtensorModule",
call_function="add_stake",
call_params={
"hotkey": "hotkey1",
"amount_staked": 1099999666,
},
)
mocked_add_stake_multiple_extrinsic.assert_called_once_with(
subtensor=fake_subtensor.async_subtensor,
wallet=fake_wallet,
hotkey_ss58s=hotkey_ss58s,
amounts=amounts,
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
fake_subtensor.substrate.compose_call.assert_any_call(
call_module="SubtensorModule",
call_function="add_stake",
call_params={
"hotkey": "hotkey2",
"amount_staked": 2199999333,
},
)
fake_subtensor.sign_and_send_extrinsic.assert_called_with(
fake_subtensor.substrate.compose_call.return_value,
fake_wallet,
True,
True,
)
assert result == mocked_execute_coroutine.return_value
Loading