Skip to content

Commit 535b37f

Browse files
authored
Merge pull request #2683 from opentensor/feat/update-delegate-info
Updates DelegateInfo chain data
2 parents e408df2 + 830e5f2 commit 535b37f

File tree

3 files changed

+91
-44
lines changed

3 files changed

+91
-44
lines changed

bittensor/core/chain_data/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from .axon_info import AxonInfo
99
from .chain_identity import ChainIdentity
10-
from .delegate_info import DelegateInfo
10+
from .delegate_info import DelegateInfo, DelegatedInfo
1111
from .delegate_info_lite import DelegateInfoLite
1212
from .dynamic_info import DynamicInfo
1313
from .ip_info import IPInfo
@@ -36,6 +36,7 @@
3636
AxonInfo,
3737
ChainIdentity,
3838
DelegateInfo,
39+
DelegatedInfo,
3940
DelegateInfoLite,
4041
DynamicInfo,
4142
IPInfo,
Lines changed: 87 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from dataclasses import dataclass
2-
from typing import Any, Optional
2+
from typing import Optional
33

44
from bittensor.core.chain_data.info_base import InfoBase
55
from bittensor.core.chain_data.utils import decode_account_id
@@ -8,27 +8,20 @@
88

99

1010
@dataclass
11-
class DelegateInfo(InfoBase):
12-
"""
13-
Dataclass for delegate information. For a lighter version of this class, see ``DelegateInfoLite``.
11+
class DelegateInfoBase(InfoBase):
12+
"""Base class containing common delegate information fields.
1413
15-
Args:
16-
hotkey_ss58 (str): Hotkey of the delegate for which the information is being fetched.
17-
total_stake (int): Total stake of the delegate.
18-
nominators (list[tuple[str, int]]): List of nominators of the delegate and their stake.
14+
Attributes:
15+
hotkey_ss58 (str): Hotkey of delegate.
16+
owner_ss58 (str): Coldkey of owner.
1917
take (float): Take of the delegate as a percentage.
20-
owner_ss58 (str): Coldkey of the owner.
21-
registrations (list[int]): List of subnets that the delegate is registered on.
2218
validator_permits (list[int]): List of subnets that the delegate is allowed to validate on.
23-
return_per_1000 (int): Return per 1000 TAO, for the delegate over a day.
24-
total_daily_return (int): Total daily return of the delegate.
19+
registrations (list[int]): List of subnets that the delegate is registered on.
20+
return_per_1000 (Balance): Return per 1000 tao of the delegate over a day.
21+
total_daily_return (Balance): Total daily return of the delegate.
2522
"""
2623

2724
hotkey_ss58: str # Hotkey of delegate
28-
total_stake: Balance # Total stake of the delegate
29-
nominators: list[
30-
tuple[str, Balance]
31-
] # List of nominators of the delegate and their stake
3225
owner_ss58: str # Coldkey of owner
3326
take: float # Take of the delegate as a percentage
3427
validator_permits: list[
@@ -38,35 +31,87 @@ class DelegateInfo(InfoBase):
3831
return_per_1000: Balance # Return per 1000 tao of the delegate over a day
3932
total_daily_return: Balance # Total daily return of the delegate
4033

34+
35+
@dataclass
36+
class DelegateInfo(DelegateInfoBase):
37+
"""
38+
Dataclass for delegate information.
39+
40+
Additional Attributes:
41+
total_stake (dict[int, Balance]): Total stake of the delegate mapped by netuid.
42+
nominators (dict[str, dict[int, Balance]]): Mapping of nominator SS58 addresses to their stakes per subnet.
43+
"""
44+
45+
total_stake: dict[int, Balance] # Total stake of the delegate by netuid and stake
46+
nominators: dict[
47+
str, dict[int, Balance]
48+
] # Mapping of nominator addresses to their stakes per subnet
49+
4150
@classmethod
4251
def _from_dict(cls, decoded: dict) -> Optional["DelegateInfo"]:
43-
"""Returns a DelegateInfo object from decoded chain data."""
44-
nominators = [
45-
(decode_account_id(x), Balance.from_rao(y))
46-
for x, y in decoded["nominators"]
47-
]
48-
total_stake = sum((x[1] for x in nominators)) if nominators else Balance(0)
49-
50-
return DelegateInfo(
51-
hotkey_ss58=decode_account_id(decoded["delegate_ss58"]),
52+
hotkey = decode_account_id(decoded.get("delegate_ss58"))
53+
owner = decode_account_id(decoded.get("owner_ss58"))
54+
55+
nominators = {}
56+
total_stake_by_netuid = {}
57+
58+
for raw_nominator, raw_stakes in decoded.get("nominators", []):
59+
nominator_ss58 = decode_account_id(raw_nominator)
60+
stakes = {
61+
int(netuid): Balance.from_rao(stake_amt).set_unit(int(netuid))
62+
for (netuid, stake_amt) in raw_stakes
63+
}
64+
nominators[nominator_ss58] = stakes
65+
66+
for netuid, stake in stakes.items():
67+
if netuid not in total_stake_by_netuid:
68+
total_stake_by_netuid[netuid] = Balance(0).set_unit(netuid)
69+
total_stake_by_netuid[netuid] += stake
70+
71+
return cls(
72+
hotkey_ss58=hotkey,
73+
total_stake=total_stake_by_netuid,
5274
nominators=nominators,
53-
owner_ss58=decode_account_id(decoded["owner_ss58"]),
54-
registrations=decoded["registrations"],
55-
return_per_1000=Balance.from_rao(decoded["return_per_1000"]),
56-
take=u16_normalized_float(decoded["take"]),
57-
total_daily_return=Balance.from_rao(decoded["total_daily_return"]),
58-
total_stake=total_stake,
59-
validator_permits=decoded["validator_permits"],
75+
owner_ss58=owner,
76+
take=u16_normalized_float(decoded.get("take")),
77+
validator_permits=list(decoded.get("validator_permits", [])),
78+
registrations=list(decoded.get("registrations", [])),
79+
return_per_1000=Balance.from_rao(decoded.get("return_per_1000")),
80+
total_daily_return=Balance.from_rao(decoded.get("total_daily_return")),
6081
)
6182

83+
84+
@dataclass
85+
class DelegatedInfo(DelegateInfoBase):
86+
"""
87+
Dataclass for delegated information. This class represents a delegate's information
88+
specific to a particular subnet.
89+
90+
Additional Attributes:
91+
netuid (int): Network ID of the subnet.
92+
stake (Balance): Stake amount for this specific delegation.
93+
"""
94+
95+
netuid: int
96+
stake: Balance
97+
6298
@classmethod
63-
def delegated_list_from_dicts(
64-
cls, delegates: list[Any]
65-
) -> list[tuple["DelegateInfo", Balance]]:
66-
return [
67-
(
68-
DelegateInfo.from_dict(delegate),
69-
Balance.from_rao(balance),
70-
)
71-
for delegate, balance in delegates
72-
]
99+
def _from_dict(
100+
cls, decoded: tuple[dict, tuple[int, int]]
101+
) -> Optional["DelegatedInfo"]:
102+
delegate_info, (netuid, stake) = decoded
103+
hotkey = decode_account_id(delegate_info.get("delegate_ss58"))
104+
owner = decode_account_id(delegate_info.get("owner_ss58"))
105+
return cls(
106+
hotkey_ss58=hotkey,
107+
owner_ss58=owner,
108+
take=u16_normalized_float(delegate_info.get("take")),
109+
validator_permits=list(delegate_info.get("validator_permits", [])),
110+
registrations=list(delegate_info.get("registrations", [])),
111+
return_per_1000=Balance.from_rao(delegate_info.get("return_per_1000")),
112+
total_daily_return=Balance.from_rao(
113+
delegate_info.get("total_daily_return")
114+
),
115+
netuid=int(netuid),
116+
stake=Balance.from_rao(int(stake)).set_unit(int(netuid)),
117+
)

bittensor/core/subtensor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
WeightCommitInfo,
2525
SubnetIdentity,
2626
SubnetInfo,
27+
DelegatedInfo,
2728
decode_account_id,
2829
)
2930
from bittensor.core.chain_data.utils import decode_metadata
@@ -925,7 +926,7 @@ def get_delegated(
925926
if not result:
926927
return []
927928

928-
return DelegateInfo.delegated_list_from_dicts(result)
929+
return DelegatedInfo.list_from_dicts(result)
929930

930931
def get_delegates(self, block: Optional[int] = None) -> list["DelegateInfo"]:
931932
"""

0 commit comments

Comments
 (0)