Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
36 changes: 36 additions & 0 deletions bittensor/core/async_subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1921,6 +1921,42 @@ async def get_stake_add_fee(
)
return Balance.from_rao(result)

async def get_subnet_info(
self,
netuid: int,
block: Optional[int] = None,
block_hash: Optional[str] = None,
reuse_block: bool = False,
) -> Optional["SubnetInfo"]:
"""
Retrieves detailed information about subnet within the Bittensor network.
This function provides comprehensive data on subnet, including its characteristics and operational parameters.

Arguments:
netuid: The unique identifier of the subnet.
block: The blockchain block number for the query.
block_hash (Optional[str]): The hash of the block to retrieve the stake from. Do not specify if using block
or reuse_block
reuse_block (bool): Whether to use the last-used block. Do not set if using block_hash or block.

Returns:
SubnetInfo: A SubnetInfo objects, each containing detailed information about a subnet.

Gaining insights into the subnet's details assists in understanding the network's composition, the roles of
different subnets, and their unique features.
"""
result = await self.query_runtime_api(
runtime_api="SubnetInfoRuntimeApi",
method="get_subnet_info_v2",
params=[netuid],
block=block,
block_hash=block_hash,
reuse_block=reuse_block,
)
if not result:
return None
return SubnetInfo.from_dict(result)

async def get_unstake_fee(
self,
amount: Balance,
Expand Down
27 changes: 27 additions & 0 deletions bittensor/core/subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1507,6 +1507,33 @@ def get_stake_add_fee(
)
return Balance.from_rao(result)

def get_subnet_info(
self, netuid: int, block: Optional[int] = None
) -> Optional["SubnetInfo"]:
"""
Retrieves detailed information about subnet within the Bittensor network.
This function provides comprehensive data on subnet, including its characteristics and operational parameters.

Arguments:
netuid: The unique identifier of the subnet.
block: The blockchain block number for the query.

Returns:
SubnetInfo: A SubnetInfo objects, each containing detailed information about a subnet.

Gaining insights into the subnet's details assists in understanding the network's composition, the roles of
different subnets, and their unique features.
"""
result = self.query_runtime_api(
runtime_api="SubnetInfoRuntimeApi",
method="get_subnet_info_v2",
params=[netuid],
block=block,
)
if not result:
return None
return SubnetInfo.from_dict(result)

def get_unstake_fee(
self,
amount: Balance,
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/subtensor_api/subnets.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def __init__(self, subtensor: Union["_Subtensor", "_AsyncSubtensor"]):
self.get_next_epoch_start_block = subtensor.get_next_epoch_start_block
self.get_subnet_burn_cost = subtensor.get_subnet_burn_cost
self.get_subnet_hyperparameters = subtensor.get_subnet_hyperparameters
self.get_subnet_info = subtensor.get_subnet_info
self.get_subnet_owner_hotkey = subtensor.get_subnet_owner_hotkey
self.get_subnet_reveal_period_epochs = subtensor.get_subnet_reveal_period_epochs
self.get_subnet_validator_permits = subtensor.get_subnet_validator_permits
Expand Down
1 change: 1 addition & 0 deletions bittensor/core/subtensor_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def add_legacy_methods(subtensor: "SubtensorApi"):
subtensor.get_subnet_hyperparameters = (
subtensor._subtensor.get_subnet_hyperparameters
)
subtensor.get_subnet_info = subtensor._subtensor.get_subnet_info
subtensor.get_subnet_owner_hotkey = subtensor._subtensor.get_subnet_owner_hotkey
subtensor.get_subnet_reveal_period_epochs = (
subtensor._subtensor.get_subnet_reveal_period_epochs
Expand Down
56 changes: 56 additions & 0 deletions tests/unit_tests/test_async_subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3314,3 +3314,59 @@ async def test_get_subnet_validator_permits_is_none(subtensor, mocker):
)

assert result is None


@pytest.mark.asyncio
async def test_get_subnet_info_success(mocker, subtensor):
"""Test get_subnet_info returns correct data when subnet information is found."""
# Prep
netuid = mocker.Mock()
block = mocker.Mock()

mocker.patch.object(subtensor, "query_runtime_api")
mocker.patch.object(
async_subtensor.SubnetInfo,
"from_dict",
)

# Call
result = await subtensor.get_subnet_info(netuid=netuid, block=block)

# Asserts
subtensor.query_runtime_api.assert_awaited_once_with(
runtime_api="SubnetInfoRuntimeApi",
method="get_subnet_info_v2",
params=[netuid],
block=block,
block_hash=None,
reuse_block=False,
)
async_subtensor.SubnetInfo.from_dict.assert_called_once_with(
subtensor.query_runtime_api.return_value,
)
assert result == async_subtensor.SubnetInfo.from_dict.return_value


@pytest.mark.asyncio
async def test_get_subnet_info_no_data(mocker, subtensor):
"""Test get_subnet_info returns None."""
# Prep
netuid = mocker.Mock()
block = mocker.Mock()
mocker.patch.object(async_subtensor.SubnetInfo, "from_dict")
mocker.patch.object(subtensor, "query_runtime_api", return_value=None)

# Call
result = await subtensor.get_subnet_info(netuid=netuid, block=block)

# Asserts
subtensor.query_runtime_api.assert_awaited_once_with(
runtime_api="SubnetInfoRuntimeApi",
method="get_subnet_info_v2",
params=[netuid],
block=block,
block_hash=None,
reuse_block=False,
)
async_subtensor.SubnetInfo.from_dict.assert_not_called()
assert result is None
51 changes: 51 additions & 0 deletions tests/unit_tests/test_subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3668,3 +3668,54 @@ def test_is_subnet_active(subtensor, mocker, query_return, expected):
)

assert result == expected


# `geg_l_subnet_info` tests
def test_get_subnet_info_success(mocker, subtensor):
"""Test get_subnet_info returns correct data when subnet information is found."""
# Prep
netuid = mocker.Mock()
block = mocker.Mock()

mocker.patch.object(subtensor, "query_runtime_api")
mocker.patch.object(
subtensor_module.SubnetInfo,
"from_dict",
)

# Call
result = subtensor.get_subnet_info(netuid=netuid, block=block)

# Asserts
subtensor.query_runtime_api.assert_called_once_with(
runtime_api="SubnetInfoRuntimeApi",
method="get_subnet_info_v2",
params=[netuid],
block=block,
)
subtensor_module.SubnetInfo.from_dict.assert_called_once_with(
subtensor.query_runtime_api.return_value,
)
assert result == subtensor_module.SubnetInfo.from_dict.return_value


def test_get_subnet_info_no_data(mocker, subtensor):
"""Test get_subnet_info returns None."""
# Prep
netuid = mocker.Mock()
block = mocker.Mock()
mocker.patch.object(subtensor_module.SubnetInfo, "from_dict")
mocker.patch.object(subtensor, "query_runtime_api", return_value=None)

# Call
result = subtensor.get_subnet_info(netuid=netuid, block=block)

# Asserts
subtensor.query_runtime_api.assert_called_once_with(
runtime_api="SubnetInfoRuntimeApi",
method="get_subnet_info_v2",
params=[netuid],
block=block,
)
subtensor_module.SubnetInfo.from_dict.assert_not_called()
assert result is None
Loading