meshtensor-cli 9.18.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.
- meshtensor_cli/__init__.py +22 -0
- meshtensor_cli/cli.py +10742 -0
- meshtensor_cli/doc_generation_helper.py +4 -0
- meshtensor_cli/src/__init__.py +1085 -0
- meshtensor_cli/src/commands/__init__.py +0 -0
- meshtensor_cli/src/commands/axon/__init__.py +0 -0
- meshtensor_cli/src/commands/axon/axon.py +132 -0
- meshtensor_cli/src/commands/crowd/__init__.py +0 -0
- meshtensor_cli/src/commands/crowd/contribute.py +621 -0
- meshtensor_cli/src/commands/crowd/contributors.py +200 -0
- meshtensor_cli/src/commands/crowd/create.py +783 -0
- meshtensor_cli/src/commands/crowd/dissolve.py +219 -0
- meshtensor_cli/src/commands/crowd/refund.py +233 -0
- meshtensor_cli/src/commands/crowd/update.py +418 -0
- meshtensor_cli/src/commands/crowd/utils.py +124 -0
- meshtensor_cli/src/commands/crowd/view.py +991 -0
- meshtensor_cli/src/commands/governance/__init__.py +0 -0
- meshtensor_cli/src/commands/governance/governance.py +794 -0
- meshtensor_cli/src/commands/liquidity/__init__.py +0 -0
- meshtensor_cli/src/commands/liquidity/liquidity.py +699 -0
- meshtensor_cli/src/commands/liquidity/utils.py +202 -0
- meshtensor_cli/src/commands/proxy.py +700 -0
- meshtensor_cli/src/commands/stake/__init__.py +0 -0
- meshtensor_cli/src/commands/stake/add.py +799 -0
- meshtensor_cli/src/commands/stake/auto_staking.py +306 -0
- meshtensor_cli/src/commands/stake/children_hotkeys.py +865 -0
- meshtensor_cli/src/commands/stake/claim.py +770 -0
- meshtensor_cli/src/commands/stake/list.py +738 -0
- meshtensor_cli/src/commands/stake/move.py +1211 -0
- meshtensor_cli/src/commands/stake/remove.py +1466 -0
- meshtensor_cli/src/commands/stake/wizard.py +323 -0
- meshtensor_cli/src/commands/subnets/__init__.py +0 -0
- meshtensor_cli/src/commands/subnets/mechanisms.py +515 -0
- meshtensor_cli/src/commands/subnets/price.py +733 -0
- meshtensor_cli/src/commands/subnets/subnets.py +2908 -0
- meshtensor_cli/src/commands/sudo.py +1294 -0
- meshtensor_cli/src/commands/tc/__init__.py +0 -0
- meshtensor_cli/src/commands/tc/tc.py +190 -0
- meshtensor_cli/src/commands/treasury/__init__.py +0 -0
- meshtensor_cli/src/commands/treasury/treasury.py +194 -0
- meshtensor_cli/src/commands/view.py +354 -0
- meshtensor_cli/src/commands/wallets.py +2311 -0
- meshtensor_cli/src/commands/weights.py +467 -0
- meshtensor_cli/src/meshtensor/__init__.py +0 -0
- meshtensor_cli/src/meshtensor/balances.py +313 -0
- meshtensor_cli/src/meshtensor/chain_data.py +1263 -0
- meshtensor_cli/src/meshtensor/extrinsics/__init__.py +0 -0
- meshtensor_cli/src/meshtensor/extrinsics/mev_shield.py +174 -0
- meshtensor_cli/src/meshtensor/extrinsics/registration.py +1861 -0
- meshtensor_cli/src/meshtensor/extrinsics/root.py +550 -0
- meshtensor_cli/src/meshtensor/extrinsics/serving.py +255 -0
- meshtensor_cli/src/meshtensor/extrinsics/transfer.py +239 -0
- meshtensor_cli/src/meshtensor/meshtensor_interface.py +2598 -0
- meshtensor_cli/src/meshtensor/minigraph.py +254 -0
- meshtensor_cli/src/meshtensor/networking.py +12 -0
- meshtensor_cli/src/meshtensor/templates/main-filters.j2 +24 -0
- meshtensor_cli/src/meshtensor/templates/main-header.j2 +36 -0
- meshtensor_cli/src/meshtensor/templates/neuron-details.j2 +111 -0
- meshtensor_cli/src/meshtensor/templates/price-multi.j2 +113 -0
- meshtensor_cli/src/meshtensor/templates/price-single.j2 +99 -0
- meshtensor_cli/src/meshtensor/templates/subnet-details-header.j2 +49 -0
- meshtensor_cli/src/meshtensor/templates/subnet-details.j2 +32 -0
- meshtensor_cli/src/meshtensor/templates/subnet-metrics.j2 +57 -0
- meshtensor_cli/src/meshtensor/templates/subnets-table.j2 +28 -0
- meshtensor_cli/src/meshtensor/templates/table.j2 +267 -0
- meshtensor_cli/src/meshtensor/templates/view.css +1058 -0
- meshtensor_cli/src/meshtensor/templates/view.j2 +43 -0
- meshtensor_cli/src/meshtensor/templates/view.js +1053 -0
- meshtensor_cli/src/meshtensor/utils.py +2007 -0
- meshtensor_cli/version.py +23 -0
- meshtensor_cli-9.18.1.dist-info/METADATA +261 -0
- meshtensor_cli-9.18.1.dist-info/RECORD +74 -0
- meshtensor_cli-9.18.1.dist-info/WHEEL +4 -0
- meshtensor_cli-9.18.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,1263 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Optional, Any, Union
|
|
5
|
+
|
|
6
|
+
import netaddr
|
|
7
|
+
from scalecodec.utils.ss58 import ss58_encode
|
|
8
|
+
|
|
9
|
+
from meshtensor_cli.src.meshtensor.balances import Balance, fixed_to_float
|
|
10
|
+
from meshtensor_cli.src.meshtensor.networking import int_to_ip
|
|
11
|
+
from meshtensor_cli.src.meshtensor.utils import (
|
|
12
|
+
SS58_FORMAT,
|
|
13
|
+
u16_normalized_float as u16tf,
|
|
14
|
+
u64_normalized_float as u64tf,
|
|
15
|
+
decode_account_id,
|
|
16
|
+
get_netuid_and_subuid_by_storage_index,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ChainDataType(Enum):
|
|
21
|
+
NeuronInfo = 1
|
|
22
|
+
DelegateInfo = 2
|
|
23
|
+
NeuronInfoLite = 3
|
|
24
|
+
StakeInfo = 4
|
|
25
|
+
SubnetHyperparameters = 5
|
|
26
|
+
DelegateInfoLite = 6
|
|
27
|
+
DynamicInfo = 7
|
|
28
|
+
ScheduledColdkeySwapInfo = 8
|
|
29
|
+
SubnetInfo = 9
|
|
30
|
+
SubnetState = 10
|
|
31
|
+
SubnetIdentity = 11
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def decode_hex_identity(info_dictionary):
|
|
35
|
+
decoded_info = {}
|
|
36
|
+
for k, v in info_dictionary.items():
|
|
37
|
+
if isinstance(v, dict):
|
|
38
|
+
item = next(iter(v.values()))
|
|
39
|
+
else:
|
|
40
|
+
item = v
|
|
41
|
+
|
|
42
|
+
if isinstance(item, tuple):
|
|
43
|
+
try:
|
|
44
|
+
decoded_info[k] = bytes(item).decode()
|
|
45
|
+
except UnicodeDecodeError:
|
|
46
|
+
print(f"Could not decode: {k}: {item}")
|
|
47
|
+
else:
|
|
48
|
+
decoded_info[k] = item
|
|
49
|
+
return decoded_info
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def process_stake_data(stake_data, netuid):
|
|
53
|
+
decoded_stake_data = {}
|
|
54
|
+
for account_id_bytes, stake_ in stake_data:
|
|
55
|
+
account_id = decode_account_id(account_id_bytes)
|
|
56
|
+
decoded_stake_data.update(
|
|
57
|
+
{account_id: Balance.from_meshlet(stake_).set_unit(netuid)}
|
|
58
|
+
)
|
|
59
|
+
return decoded_stake_data
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _tbwu(val: int, netuid: Optional[int] = 0) -> Balance:
|
|
63
|
+
"""Returns a Balance object from a value and unit."""
|
|
64
|
+
return Balance.from_meshlet(val).set_unit(netuid)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _chr_str(codes: tuple[int]) -> str:
|
|
68
|
+
"""Converts a tuple of integer Unicode code points into a string."""
|
|
69
|
+
return "".join(map(chr, codes))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def process_nested(data: Union[tuple, dict], chr_transform):
|
|
73
|
+
"""Processes nested data structures by applying a transformation function to their elements."""
|
|
74
|
+
if isinstance(data, (list, tuple)):
|
|
75
|
+
if len(data) > 0 and isinstance(data[0], dict):
|
|
76
|
+
return [
|
|
77
|
+
{k: chr_transform(v) for k, v in item.items()}
|
|
78
|
+
if item is not None
|
|
79
|
+
else None
|
|
80
|
+
for item in data
|
|
81
|
+
]
|
|
82
|
+
return {}
|
|
83
|
+
elif isinstance(data, dict):
|
|
84
|
+
return {k: chr_transform(v) for k, v in data.items()}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class AxonInfo:
|
|
89
|
+
version: int
|
|
90
|
+
ip: str
|
|
91
|
+
port: int
|
|
92
|
+
ip_type: int
|
|
93
|
+
hotkey: str
|
|
94
|
+
coldkey: str
|
|
95
|
+
protocol: int = 4
|
|
96
|
+
placeholder1: int = 0
|
|
97
|
+
placeholder2: int = 0
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def is_serving(self) -> bool:
|
|
101
|
+
"""True if the endpoint is serving."""
|
|
102
|
+
return self.ip != "0.0.0.0"
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def from_neuron_info(cls, neuron_info: dict) -> "AxonInfo":
|
|
106
|
+
"""
|
|
107
|
+
Converts a dictionary to an AxonInfo object.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
neuron_info (dict): A dictionary containing the neuron information.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
instance (AxonInfo): An instance of AxonInfo created from the dictionary.
|
|
114
|
+
"""
|
|
115
|
+
return cls(
|
|
116
|
+
version=neuron_info["axon_info"]["version"],
|
|
117
|
+
ip=int_to_ip(int(neuron_info["axon_info"]["ip"])),
|
|
118
|
+
port=neuron_info["axon_info"]["port"],
|
|
119
|
+
ip_type=neuron_info["axon_info"]["ip_type"],
|
|
120
|
+
hotkey=neuron_info["hotkey"],
|
|
121
|
+
coldkey=neuron_info["coldkey"],
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass
|
|
126
|
+
class InfoBase:
|
|
127
|
+
"""Base dataclass for info objects."""
|
|
128
|
+
|
|
129
|
+
@abstractmethod
|
|
130
|
+
def _fix_decoded(self, decoded: Any) -> "InfoBase":
|
|
131
|
+
raise NotImplementedError(
|
|
132
|
+
"This is an abstract method and must be implemented in a subclass."
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
@classmethod
|
|
136
|
+
def from_any(cls, data: Any) -> "InfoBase":
|
|
137
|
+
return cls._fix_decoded(data)
|
|
138
|
+
|
|
139
|
+
@classmethod
|
|
140
|
+
def list_from_any(cls, data_list: list[Any]) -> list["InfoBase"]:
|
|
141
|
+
return [cls.from_any(data) for data in data_list]
|
|
142
|
+
|
|
143
|
+
def __getitem__(self, item):
|
|
144
|
+
return getattr(self, item)
|
|
145
|
+
|
|
146
|
+
def get(self, item, default=None):
|
|
147
|
+
return getattr(self, item, default)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclass
|
|
151
|
+
class SubnetHyperparameters(InfoBase):
|
|
152
|
+
"""
|
|
153
|
+
This class represents the hyperparameters for a subnet.
|
|
154
|
+
Attributes:
|
|
155
|
+
rho (int): The rate of decay of some value.
|
|
156
|
+
kappa (int): A constant multiplier used in calculations.
|
|
157
|
+
immunity_period (int): The period during which immunity is active.
|
|
158
|
+
min_allowed_weights (int): Minimum allowed weights.
|
|
159
|
+
max_weight_limit (float): Maximum weight limit.
|
|
160
|
+
tempo (int): The tempo or rate of operation.
|
|
161
|
+
min_difficulty (int): Minimum difficulty for some operations.
|
|
162
|
+
max_difficulty (int): Maximum difficulty for some operations.
|
|
163
|
+
weights_version (int): The version number of the weights used.
|
|
164
|
+
weights_rate_limit (int): Rate limit for processing weights.
|
|
165
|
+
adjustment_interval (int): Interval at which adjustments are made.
|
|
166
|
+
activity_cutoff (int): Activity cutoff threshold.
|
|
167
|
+
registration_allowed (bool): Indicates if registration is allowed.
|
|
168
|
+
target_regs_per_interval (int): Target number of registrations per interval.
|
|
169
|
+
min_burn (int): Minimum burn value.
|
|
170
|
+
max_burn (int): Maximum burn value.
|
|
171
|
+
bonds_moving_avg (int): Moving average of bonds.
|
|
172
|
+
max_regs_per_block (int): Maximum number of registrations per block.
|
|
173
|
+
serving_rate_limit (int): Limit on the rate of service.
|
|
174
|
+
max_validators (int): Maximum number of validators.
|
|
175
|
+
adjustment_alpha (int): Alpha value for adjustments.
|
|
176
|
+
difficulty (int): Difficulty level.
|
|
177
|
+
commit_reveal_period (int): Interval for commit-reveal weights.
|
|
178
|
+
commit_reveal_weights_enabled (bool): Flag indicating if commit-reveal weights are enabled.
|
|
179
|
+
alpha_high (int): High value of alpha.
|
|
180
|
+
alpha_low (int): Low value of alpha.
|
|
181
|
+
liquid_alpha_enabled (bool): Flag indicating if liquid alpha is enabled.
|
|
182
|
+
alpha_sigmoid_steepness (float):
|
|
183
|
+
yuma_version (int): Version of yuma.
|
|
184
|
+
subnet_is_active (bool): Indicates if subnet is active after START CALL.
|
|
185
|
+
transfers_enabled (bool): Flag indicating if transfers are enabled.
|
|
186
|
+
bonds_reset_enabled (bool): Flag indicating if bonds are reset enabled.
|
|
187
|
+
user_liquidity_enabled (bool): Flag indicating if user liquidity is enabled.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
rho: int
|
|
191
|
+
kappa: int
|
|
192
|
+
immunity_period: int
|
|
193
|
+
min_allowed_weights: int
|
|
194
|
+
max_weight_limit: float
|
|
195
|
+
tempo: int
|
|
196
|
+
min_difficulty: int
|
|
197
|
+
max_difficulty: int
|
|
198
|
+
weights_version: int
|
|
199
|
+
weights_rate_limit: int
|
|
200
|
+
adjustment_interval: int
|
|
201
|
+
activity_cutoff: int
|
|
202
|
+
registration_allowed: bool
|
|
203
|
+
target_regs_per_interval: int
|
|
204
|
+
min_burn: int
|
|
205
|
+
max_burn: int
|
|
206
|
+
bonds_moving_avg: int
|
|
207
|
+
max_regs_per_block: int
|
|
208
|
+
serving_rate_limit: int
|
|
209
|
+
max_validators: int
|
|
210
|
+
adjustment_alpha: int
|
|
211
|
+
difficulty: int
|
|
212
|
+
commit_reveal_period: int
|
|
213
|
+
commit_reveal_weights_enabled: bool
|
|
214
|
+
alpha_high: int
|
|
215
|
+
alpha_low: int
|
|
216
|
+
liquid_alpha_enabled: bool
|
|
217
|
+
alpha_sigmoid_steepness: float
|
|
218
|
+
yuma_version: int
|
|
219
|
+
subnet_is_active: bool
|
|
220
|
+
transfers_enabled: bool
|
|
221
|
+
bonds_reset_enabled: bool
|
|
222
|
+
user_liquidity_enabled: bool
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
def _fix_decoded(
|
|
226
|
+
cls, decoded: Union[dict, "SubnetHyperparameters"]
|
|
227
|
+
) -> "SubnetHyperparameters":
|
|
228
|
+
return cls(
|
|
229
|
+
activity_cutoff=decoded["activity_cutoff"],
|
|
230
|
+
adjustment_alpha=decoded["adjustment_alpha"],
|
|
231
|
+
adjustment_interval=decoded["adjustment_interval"],
|
|
232
|
+
alpha_high=decoded["alpha_high"],
|
|
233
|
+
alpha_low=decoded["alpha_low"],
|
|
234
|
+
alpha_sigmoid_steepness=fixed_to_float(
|
|
235
|
+
decoded["alpha_sigmoid_steepness"], frac_bits=32
|
|
236
|
+
),
|
|
237
|
+
bonds_moving_avg=decoded["bonds_moving_avg"],
|
|
238
|
+
bonds_reset_enabled=decoded["bonds_reset_enabled"],
|
|
239
|
+
commit_reveal_weights_enabled=decoded["commit_reveal_weights_enabled"],
|
|
240
|
+
commit_reveal_period=decoded["commit_reveal_period"],
|
|
241
|
+
difficulty=decoded["difficulty"],
|
|
242
|
+
immunity_period=decoded["immunity_period"],
|
|
243
|
+
kappa=decoded["kappa"],
|
|
244
|
+
liquid_alpha_enabled=decoded["liquid_alpha_enabled"],
|
|
245
|
+
max_burn=decoded["max_burn"],
|
|
246
|
+
max_difficulty=decoded["max_difficulty"],
|
|
247
|
+
max_regs_per_block=decoded["max_regs_per_block"],
|
|
248
|
+
max_validators=decoded["max_validators"],
|
|
249
|
+
max_weight_limit=decoded["max_weights_limit"],
|
|
250
|
+
min_allowed_weights=decoded["min_allowed_weights"],
|
|
251
|
+
min_burn=decoded["min_burn"],
|
|
252
|
+
min_difficulty=decoded["min_difficulty"],
|
|
253
|
+
registration_allowed=decoded["registration_allowed"],
|
|
254
|
+
rho=decoded["rho"],
|
|
255
|
+
serving_rate_limit=decoded["serving_rate_limit"],
|
|
256
|
+
subnet_is_active=decoded["subnet_is_active"],
|
|
257
|
+
target_regs_per_interval=decoded["target_regs_per_interval"],
|
|
258
|
+
tempo=decoded["tempo"],
|
|
259
|
+
transfers_enabled=decoded["transfers_enabled"],
|
|
260
|
+
user_liquidity_enabled=decoded["user_liquidity_enabled"],
|
|
261
|
+
weights_rate_limit=decoded["weights_rate_limit"],
|
|
262
|
+
weights_version=decoded["weights_version"],
|
|
263
|
+
yuma_version=decoded["yuma_version"],
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@dataclass
|
|
268
|
+
class StakeInfo(InfoBase):
|
|
269
|
+
"""Dataclass for stake info."""
|
|
270
|
+
|
|
271
|
+
hotkey_ss58: str # Hotkey address
|
|
272
|
+
coldkey_ss58: str # Coldkey address
|
|
273
|
+
netuid: int
|
|
274
|
+
stake: Balance # Stake for the hotkey-coldkey pair
|
|
275
|
+
locked: Balance # Stake which is locked.
|
|
276
|
+
emission: Balance # Emission for the hotkey-coldkey pair
|
|
277
|
+
tao_emission: Balance # MESH emission for the hotkey-coldkey pair
|
|
278
|
+
drain: int
|
|
279
|
+
is_registered: bool
|
|
280
|
+
|
|
281
|
+
@classmethod
|
|
282
|
+
def _fix_decoded(cls, decoded: Any) -> "StakeInfo":
|
|
283
|
+
hotkey = decode_account_id(decoded.get("hotkey"))
|
|
284
|
+
coldkey = decode_account_id(decoded.get("coldkey"))
|
|
285
|
+
netuid = int(decoded.get("netuid"))
|
|
286
|
+
stake = Balance.from_meshlet(decoded.get("stake")).set_unit(netuid)
|
|
287
|
+
locked = Balance.from_meshlet(decoded.get("locked")).set_unit(netuid)
|
|
288
|
+
emission = Balance.from_meshlet(decoded.get("emission")).set_unit(netuid)
|
|
289
|
+
tao_emission = Balance.from_meshlet(decoded.get("tao_emission"))
|
|
290
|
+
drain = int(decoded.get("drain"))
|
|
291
|
+
is_registered = bool(decoded.get("is_registered"))
|
|
292
|
+
|
|
293
|
+
return cls(
|
|
294
|
+
hotkey,
|
|
295
|
+
coldkey,
|
|
296
|
+
netuid,
|
|
297
|
+
stake,
|
|
298
|
+
locked,
|
|
299
|
+
emission,
|
|
300
|
+
tao_emission,
|
|
301
|
+
drain,
|
|
302
|
+
is_registered,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
@dataclass
|
|
307
|
+
class NeuronInfo(InfoBase):
|
|
308
|
+
"""Dataclass for neuron metadata."""
|
|
309
|
+
|
|
310
|
+
hotkey: str
|
|
311
|
+
coldkey: str
|
|
312
|
+
uid: int
|
|
313
|
+
netuid: int
|
|
314
|
+
active: int
|
|
315
|
+
stake: Balance
|
|
316
|
+
# mapping of coldkey to amount staked to this Neuron
|
|
317
|
+
stake_dict: dict[str, Balance]
|
|
318
|
+
total_stake: Balance
|
|
319
|
+
rank: float
|
|
320
|
+
emission: float
|
|
321
|
+
incentive: float
|
|
322
|
+
consensus: float
|
|
323
|
+
trust: float
|
|
324
|
+
validator_trust: float
|
|
325
|
+
dividends: float
|
|
326
|
+
last_update: int
|
|
327
|
+
validator_permit: bool
|
|
328
|
+
weights: list[list[int]]
|
|
329
|
+
bonds: list[list[int]]
|
|
330
|
+
pruning_score: int
|
|
331
|
+
axon_info: Optional[AxonInfo] = None
|
|
332
|
+
is_null: bool = False
|
|
333
|
+
|
|
334
|
+
@classmethod
|
|
335
|
+
def from_weights_bonds_and_neuron_lite(
|
|
336
|
+
cls,
|
|
337
|
+
neuron_lite: "NeuronInfoLite",
|
|
338
|
+
weights_as_dict: dict[int, list[tuple[int, int]]],
|
|
339
|
+
bonds_as_dict: dict[int, list[tuple[int, int]]],
|
|
340
|
+
) -> "NeuronInfo":
|
|
341
|
+
n_dict = neuron_lite.__dict__
|
|
342
|
+
n_dict["weights"] = weights_as_dict.get(neuron_lite.uid, [])
|
|
343
|
+
n_dict["bonds"] = bonds_as_dict.get(neuron_lite.uid, [])
|
|
344
|
+
|
|
345
|
+
return cls(**n_dict)
|
|
346
|
+
|
|
347
|
+
@staticmethod
|
|
348
|
+
def get_null_neuron() -> "NeuronInfo":
|
|
349
|
+
neuron = NeuronInfo(
|
|
350
|
+
uid=0,
|
|
351
|
+
netuid=0,
|
|
352
|
+
active=0,
|
|
353
|
+
stake=Balance.from_meshlet(0),
|
|
354
|
+
stake_dict={},
|
|
355
|
+
total_stake=Balance.from_meshlet(0),
|
|
356
|
+
rank=0,
|
|
357
|
+
emission=0,
|
|
358
|
+
incentive=0,
|
|
359
|
+
consensus=0,
|
|
360
|
+
trust=0,
|
|
361
|
+
validator_trust=0,
|
|
362
|
+
dividends=0,
|
|
363
|
+
last_update=0,
|
|
364
|
+
validator_permit=False,
|
|
365
|
+
weights=[],
|
|
366
|
+
bonds=[],
|
|
367
|
+
axon_info=None,
|
|
368
|
+
is_null=True,
|
|
369
|
+
coldkey="000000000000000000000000000000000000000000000000",
|
|
370
|
+
hotkey="000000000000000000000000000000000000000000000000",
|
|
371
|
+
pruning_score=0,
|
|
372
|
+
)
|
|
373
|
+
return neuron
|
|
374
|
+
|
|
375
|
+
@classmethod
|
|
376
|
+
def _fix_decoded(cls, decoded: Any) -> "NeuronInfo":
|
|
377
|
+
netuid = decoded.get("netuid")
|
|
378
|
+
stake_dict = process_stake_data(decoded.get("stake"), netuid=netuid)
|
|
379
|
+
total_stake = sum(stake_dict.values()) if stake_dict else Balance(0)
|
|
380
|
+
axon_info = decoded.get("axon_info", {})
|
|
381
|
+
coldkey = decode_account_id(decoded.get("coldkey"))
|
|
382
|
+
hotkey = decode_account_id(decoded.get("hotkey"))
|
|
383
|
+
return cls(
|
|
384
|
+
hotkey=hotkey,
|
|
385
|
+
coldkey=coldkey,
|
|
386
|
+
uid=decoded.get("uid"),
|
|
387
|
+
netuid=netuid,
|
|
388
|
+
active=decoded.get("active"),
|
|
389
|
+
stake=total_stake,
|
|
390
|
+
stake_dict=stake_dict,
|
|
391
|
+
total_stake=total_stake,
|
|
392
|
+
rank=u16tf(decoded.get("rank")),
|
|
393
|
+
emission=decoded.get("emission") / 1e9,
|
|
394
|
+
incentive=u16tf(decoded.get("incentive")),
|
|
395
|
+
consensus=u16tf(decoded.get("consensus")),
|
|
396
|
+
trust=u16tf(decoded.get("trust")),
|
|
397
|
+
validator_trust=u16tf(decoded.get("validator_trust")),
|
|
398
|
+
dividends=u16tf(decoded.get("dividends")),
|
|
399
|
+
last_update=decoded.get("last_update"),
|
|
400
|
+
validator_permit=decoded.get("validator_permit"),
|
|
401
|
+
weights=[[e[0], e[1]] for e in decoded.get("weights")],
|
|
402
|
+
bonds=[[e[0], e[1]] for e in decoded.get("bonds")],
|
|
403
|
+
pruning_score=decoded.get("pruning_score"),
|
|
404
|
+
axon_info=AxonInfo(
|
|
405
|
+
version=axon_info.get("version"),
|
|
406
|
+
ip=str(netaddr.IPAddress(axon_info.get("ip"))),
|
|
407
|
+
port=axon_info.get("port"),
|
|
408
|
+
ip_type=axon_info.get("ip_type"),
|
|
409
|
+
placeholder1=axon_info.get("placeholder1"),
|
|
410
|
+
placeholder2=axon_info.get("placeholder2"),
|
|
411
|
+
protocol=axon_info.get("protocol"),
|
|
412
|
+
hotkey=hotkey,
|
|
413
|
+
coldkey=coldkey,
|
|
414
|
+
),
|
|
415
|
+
is_null=False,
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@dataclass
|
|
420
|
+
class NeuronInfoLite(InfoBase):
|
|
421
|
+
"""Dataclass for neuron metadata, but without the weights and bonds."""
|
|
422
|
+
|
|
423
|
+
hotkey: str
|
|
424
|
+
coldkey: str
|
|
425
|
+
uid: int
|
|
426
|
+
netuid: int
|
|
427
|
+
active: int
|
|
428
|
+
stake: Balance
|
|
429
|
+
# mapping of coldkey to amount staked to this Neuron
|
|
430
|
+
stake_dict: dict[str, Balance]
|
|
431
|
+
total_stake: Balance
|
|
432
|
+
rank: float
|
|
433
|
+
emission: float
|
|
434
|
+
incentive: float
|
|
435
|
+
consensus: float
|
|
436
|
+
trust: float
|
|
437
|
+
validator_trust: float
|
|
438
|
+
dividends: float
|
|
439
|
+
last_update: int
|
|
440
|
+
validator_permit: bool
|
|
441
|
+
axon_info: AxonInfo
|
|
442
|
+
pruning_score: int
|
|
443
|
+
is_null: bool = False
|
|
444
|
+
|
|
445
|
+
@staticmethod
|
|
446
|
+
def get_null_neuron() -> "NeuronInfoLite":
|
|
447
|
+
neuron = NeuronInfoLite(
|
|
448
|
+
uid=0,
|
|
449
|
+
netuid=0,
|
|
450
|
+
active=0,
|
|
451
|
+
stake=Balance.from_meshlet(0),
|
|
452
|
+
stake_dict={},
|
|
453
|
+
total_stake=Balance.from_meshlet(0),
|
|
454
|
+
rank=0,
|
|
455
|
+
emission=0,
|
|
456
|
+
incentive=0,
|
|
457
|
+
consensus=0,
|
|
458
|
+
trust=0,
|
|
459
|
+
validator_trust=0,
|
|
460
|
+
dividends=0,
|
|
461
|
+
last_update=0,
|
|
462
|
+
validator_permit=False,
|
|
463
|
+
axon_info=None,
|
|
464
|
+
is_null=True,
|
|
465
|
+
coldkey="000000000000000000000000000000000000000000000000",
|
|
466
|
+
hotkey="000000000000000000000000000000000000000000000000",
|
|
467
|
+
pruning_score=0,
|
|
468
|
+
)
|
|
469
|
+
return neuron
|
|
470
|
+
|
|
471
|
+
@classmethod
|
|
472
|
+
def _fix_decoded(cls, decoded: Union[dict, "NeuronInfoLite"]) -> "NeuronInfoLite":
|
|
473
|
+
active = decoded.get("active")
|
|
474
|
+
axon_info = decoded.get("axon_info", {})
|
|
475
|
+
coldkey = decode_account_id(decoded.get("coldkey"))
|
|
476
|
+
consensus = decoded.get("consensus")
|
|
477
|
+
dividends = decoded.get("dividends")
|
|
478
|
+
emission = decoded.get("emission")
|
|
479
|
+
hotkey = decode_account_id(decoded.get("hotkey"))
|
|
480
|
+
incentive = decoded.get("incentive")
|
|
481
|
+
last_update = decoded.get("last_update")
|
|
482
|
+
netuid = decoded.get("netuid")
|
|
483
|
+
pruning_score = decoded.get("pruning_score")
|
|
484
|
+
rank = decoded.get("rank")
|
|
485
|
+
stake_dict = process_stake_data(decoded.get("stake"), netuid)
|
|
486
|
+
stake = sum(stake_dict.values()) if stake_dict else Balance(0)
|
|
487
|
+
trust = decoded.get("trust")
|
|
488
|
+
uid = decoded.get("uid")
|
|
489
|
+
validator_permit = decoded.get("validator_permit")
|
|
490
|
+
validator_trust = decoded.get("validator_trust")
|
|
491
|
+
|
|
492
|
+
neuron = cls(
|
|
493
|
+
active=active,
|
|
494
|
+
axon_info=AxonInfo(
|
|
495
|
+
version=axon_info.get("version"),
|
|
496
|
+
ip=str(netaddr.IPAddress(axon_info.get("ip"))),
|
|
497
|
+
port=axon_info.get("port"),
|
|
498
|
+
ip_type=axon_info.get("ip_type"),
|
|
499
|
+
placeholder1=axon_info.get("placeholder1"),
|
|
500
|
+
placeholder2=axon_info.get("placeholder2"),
|
|
501
|
+
protocol=axon_info.get("protocol"),
|
|
502
|
+
hotkey=hotkey,
|
|
503
|
+
coldkey=coldkey,
|
|
504
|
+
),
|
|
505
|
+
coldkey=coldkey,
|
|
506
|
+
consensus=u16tf(consensus),
|
|
507
|
+
dividends=u16tf(dividends),
|
|
508
|
+
emission=emission / 1e9,
|
|
509
|
+
hotkey=hotkey,
|
|
510
|
+
incentive=u16tf(incentive),
|
|
511
|
+
last_update=last_update,
|
|
512
|
+
netuid=netuid,
|
|
513
|
+
pruning_score=pruning_score,
|
|
514
|
+
rank=u16tf(rank),
|
|
515
|
+
stake_dict=stake_dict,
|
|
516
|
+
stake=stake,
|
|
517
|
+
total_stake=stake,
|
|
518
|
+
trust=u16tf(trust),
|
|
519
|
+
uid=uid,
|
|
520
|
+
validator_permit=validator_permit,
|
|
521
|
+
validator_trust=u16tf(validator_trust),
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
return neuron
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
@dataclass
|
|
528
|
+
class DelegateInfo(InfoBase):
|
|
529
|
+
"""
|
|
530
|
+
Dataclass for delegate information. For a lighter version of this class, see :func:`DelegateInfoLite`.
|
|
531
|
+
|
|
532
|
+
:param hotkey_ss58: Hotkey of the delegate for which the information is being fetched.
|
|
533
|
+
:param total_stake: Total stake of the delegate.
|
|
534
|
+
:param nominators: list of nominators of the delegate and their stake.
|
|
535
|
+
:param take: Take of the delegate as a percentage.
|
|
536
|
+
:param owner_ss58: Coldkey of the owner.
|
|
537
|
+
:param registrations: list of subnets that the delegate is registered on.
|
|
538
|
+
:param validator_permits: list of subnets that the delegate is allowed to validate on.
|
|
539
|
+
:param return_per_1000: Return per 1000 MESH, for the delegate over a day.
|
|
540
|
+
:param total_daily_return: Total daily return of the delegate.
|
|
541
|
+
|
|
542
|
+
"""
|
|
543
|
+
|
|
544
|
+
hotkey_ss58: str # Hotkey of delegate
|
|
545
|
+
total_stake: Balance # Total stake of the delegate
|
|
546
|
+
nominators: list[
|
|
547
|
+
tuple[str, Balance]
|
|
548
|
+
] # list of nominators of the delegate and their stake
|
|
549
|
+
owner_ss58: str # Coldkey of owner
|
|
550
|
+
take: float # Take of the delegate as a percentage
|
|
551
|
+
validator_permits: list[
|
|
552
|
+
int
|
|
553
|
+
] # list of subnets that the delegate is allowed to validate on
|
|
554
|
+
registrations: list[int] # list of subnets that the delegate is registered on
|
|
555
|
+
return_per_1000: Balance # Return per 1000 mesh of the delegate over a day
|
|
556
|
+
total_daily_return: Balance # Total daily return of the delegate
|
|
557
|
+
|
|
558
|
+
@classmethod
|
|
559
|
+
def _fix_decoded(cls, decoded: "DelegateInfo") -> "DelegateInfo":
|
|
560
|
+
hotkey = decode_account_id(decoded.get("hotkey_ss58"))
|
|
561
|
+
owner = decode_account_id(decoded.get("owner_ss58"))
|
|
562
|
+
nominators = [
|
|
563
|
+
(decode_account_id(x), Balance.from_meshlet(y))
|
|
564
|
+
for x, y in decoded.get("nominators")
|
|
565
|
+
]
|
|
566
|
+
total_stake = sum((x[1] for x in nominators)) if nominators else Balance(0)
|
|
567
|
+
return cls(
|
|
568
|
+
hotkey_ss58=hotkey,
|
|
569
|
+
total_stake=total_stake,
|
|
570
|
+
nominators=nominators,
|
|
571
|
+
owner_ss58=owner,
|
|
572
|
+
take=u16tf(decoded.get("take")),
|
|
573
|
+
validator_permits=decoded.get("validator_permits"),
|
|
574
|
+
registrations=decoded.get("registrations"),
|
|
575
|
+
return_per_1000=Balance.from_meshlet(decoded.get("return_per_1000")),
|
|
576
|
+
total_daily_return=Balance.from_meshlet(decoded.get("total_daily_return")),
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
@dataclass
|
|
581
|
+
class DelegateInfoLite(InfoBase):
|
|
582
|
+
"""
|
|
583
|
+
Dataclass for light delegate information.
|
|
584
|
+
|
|
585
|
+
Args:
|
|
586
|
+
hotkey_ss58 (str): Hotkey of the delegate for which the information is being fetched.
|
|
587
|
+
owner_ss58 (str): Coldkey of the owner.
|
|
588
|
+
total_stake (int): Total stake of the delegate.
|
|
589
|
+
owner_stake (int): Own stake of the delegate.
|
|
590
|
+
take (float): Take of the delegate as a percentage. None if custom
|
|
591
|
+
"""
|
|
592
|
+
|
|
593
|
+
hotkey_ss58: str # Hotkey of delegate
|
|
594
|
+
owner_ss58: str # Coldkey of owner
|
|
595
|
+
take: Optional[float]
|
|
596
|
+
total_stake: Balance # Total stake of the delegate
|
|
597
|
+
previous_total_stake: Optional[Balance] # Total stake of the delegate
|
|
598
|
+
owner_stake: Balance # Own stake of the delegate
|
|
599
|
+
|
|
600
|
+
@classmethod
|
|
601
|
+
def _fix_decoded(cls, decoded: Any) -> "DelegateInfoLite":
|
|
602
|
+
"""Fixes the decoded values."""
|
|
603
|
+
decoded_take = decoded.get("take")
|
|
604
|
+
|
|
605
|
+
if decoded_take == 65535:
|
|
606
|
+
fixed_take = None
|
|
607
|
+
else:
|
|
608
|
+
fixed_take = u16tf(decoded_take)
|
|
609
|
+
|
|
610
|
+
return cls(
|
|
611
|
+
hotkey_ss58=ss58_encode(decoded.get("delegate_ss58"), SS58_FORMAT),
|
|
612
|
+
owner_ss58=ss58_encode(decoded.get("owner_ss58"), SS58_FORMAT),
|
|
613
|
+
take=fixed_take,
|
|
614
|
+
total_stake=Balance.from_meshlet(decoded.get("total_stake")),
|
|
615
|
+
owner_stake=Balance.from_meshlet(decoded.get("owner_stake")),
|
|
616
|
+
previous_total_stake=None,
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
@dataclass
|
|
621
|
+
class SubnetInfo(InfoBase):
|
|
622
|
+
"""Dataclass for subnet info."""
|
|
623
|
+
|
|
624
|
+
netuid: int
|
|
625
|
+
rho: int
|
|
626
|
+
kappa: int
|
|
627
|
+
difficulty: int
|
|
628
|
+
immunity_period: int
|
|
629
|
+
max_allowed_validators: int
|
|
630
|
+
min_allowed_weights: int
|
|
631
|
+
max_weights_limit: float
|
|
632
|
+
scaling_law_power: float
|
|
633
|
+
subnetwork_n: int
|
|
634
|
+
max_n: int
|
|
635
|
+
blocks_since_epoch: int
|
|
636
|
+
tempo: int
|
|
637
|
+
modality: int
|
|
638
|
+
connection_requirements: dict[str, float]
|
|
639
|
+
emission_value: float
|
|
640
|
+
burn: Balance
|
|
641
|
+
owner_ss58: str
|
|
642
|
+
|
|
643
|
+
@classmethod
|
|
644
|
+
def _fix_decoded(cls, decoded: "SubnetInfo") -> "SubnetInfo":
|
|
645
|
+
return cls(
|
|
646
|
+
netuid=decoded.get("netuid"),
|
|
647
|
+
rho=decoded.get("rho"),
|
|
648
|
+
kappa=decoded.get("kappa"),
|
|
649
|
+
difficulty=decoded.get("difficulty"),
|
|
650
|
+
immunity_period=decoded.get("immunity_period"),
|
|
651
|
+
max_allowed_validators=decoded.get("max_allowed_validators"),
|
|
652
|
+
min_allowed_weights=decoded.get("min_allowed_weights"),
|
|
653
|
+
max_weights_limit=decoded.get("max_weights_limit"),
|
|
654
|
+
scaling_law_power=decoded.get("scaling_law_power"),
|
|
655
|
+
subnetwork_n=decoded.get("subnetwork_n"),
|
|
656
|
+
max_n=decoded.get("max_allowed_uids"),
|
|
657
|
+
blocks_since_epoch=decoded.get("blocks_since_last_step"),
|
|
658
|
+
tempo=decoded.get("tempo"),
|
|
659
|
+
modality=decoded.get("network_modality"),
|
|
660
|
+
connection_requirements={
|
|
661
|
+
str(int(netuid)): u16tf(int(req))
|
|
662
|
+
for (netuid, req) in decoded.get("network_connect")
|
|
663
|
+
},
|
|
664
|
+
emission_value=decoded.get("emission_value"),
|
|
665
|
+
burn=Balance.from_meshlet(decoded.get("burn")),
|
|
666
|
+
owner_ss58=decode_account_id(decoded.get("owner")),
|
|
667
|
+
)
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
@dataclass
|
|
671
|
+
class SubnetIdentity(InfoBase):
|
|
672
|
+
"""Dataclass for subnet identity information."""
|
|
673
|
+
|
|
674
|
+
subnet_name: str
|
|
675
|
+
github_repo: str
|
|
676
|
+
subnet_contact: str
|
|
677
|
+
subnet_url: str
|
|
678
|
+
discord: str
|
|
679
|
+
description: str
|
|
680
|
+
logo_url: str
|
|
681
|
+
additional: str
|
|
682
|
+
|
|
683
|
+
@classmethod
|
|
684
|
+
def _fix_decoded(cls, decoded: dict) -> "SubnetIdentity":
|
|
685
|
+
return cls(
|
|
686
|
+
subnet_name=bytes(decoded["subnet_name"]).decode(),
|
|
687
|
+
github_repo=bytes(decoded["github_repo"]).decode(),
|
|
688
|
+
subnet_contact=bytes(decoded["subnet_contact"]).decode(),
|
|
689
|
+
subnet_url=bytes(decoded["subnet_url"]).decode(),
|
|
690
|
+
discord=bytes(decoded["discord"]).decode(),
|
|
691
|
+
description=bytes(decoded["description"]).decode(),
|
|
692
|
+
logo_url=bytes(decoded["logo_url"]).decode(),
|
|
693
|
+
additional=bytes(decoded["additional"]).decode(),
|
|
694
|
+
)
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
@dataclass
|
|
698
|
+
class DynamicInfo(InfoBase):
|
|
699
|
+
netuid: int
|
|
700
|
+
owner_hotkey: str
|
|
701
|
+
owner_coldkey: str
|
|
702
|
+
subnet_name: str
|
|
703
|
+
symbol: str
|
|
704
|
+
tempo: int
|
|
705
|
+
last_step: int
|
|
706
|
+
blocks_since_last_step: int
|
|
707
|
+
emission: Balance
|
|
708
|
+
alpha_in: Balance
|
|
709
|
+
alpha_out: Balance
|
|
710
|
+
tao_in: Balance
|
|
711
|
+
price: Balance
|
|
712
|
+
k: float
|
|
713
|
+
is_dynamic: bool
|
|
714
|
+
alpha_out_emission: Balance
|
|
715
|
+
alpha_in_emission: Balance
|
|
716
|
+
tao_in_emission: Balance
|
|
717
|
+
pending_alpha_emission: Balance
|
|
718
|
+
pending_root_emission: Balance
|
|
719
|
+
network_registered_at: int
|
|
720
|
+
subnet_identity: Optional[SubnetIdentity]
|
|
721
|
+
subnet_volume: Balance
|
|
722
|
+
moving_price: float
|
|
723
|
+
|
|
724
|
+
@classmethod
|
|
725
|
+
def _fix_decoded(cls, decoded: Any) -> "DynamicInfo":
|
|
726
|
+
"""Returns a DynamicInfo object from a decoded DynamicInfo dictionary."""
|
|
727
|
+
|
|
728
|
+
netuid = int(decoded.get("netuid"))
|
|
729
|
+
symbol = bytes([int(b) for b in decoded.get("token_symbol")]).decode()
|
|
730
|
+
subnet_name = bytes([int(b) for b in decoded.get("subnet_name")]).decode()
|
|
731
|
+
is_dynamic = True if netuid > 0 else False # Patching for netuid 0
|
|
732
|
+
|
|
733
|
+
owner_hotkey = decode_account_id(decoded.get("owner_hotkey"))
|
|
734
|
+
owner_coldkey = decode_account_id(decoded.get("owner_coldkey"))
|
|
735
|
+
|
|
736
|
+
emission = Balance.from_meshlet(decoded.get("emission")).set_unit(0)
|
|
737
|
+
alpha_in = Balance.from_meshlet(decoded.get("alpha_in")).set_unit(netuid)
|
|
738
|
+
alpha_out = Balance.from_meshlet(decoded.get("alpha_out")).set_unit(netuid)
|
|
739
|
+
tao_in = Balance.from_meshlet(decoded.get("tao_in")).set_unit(0)
|
|
740
|
+
alpha_out_emission = Balance.from_meshlet(
|
|
741
|
+
decoded.get("alpha_out_emission")
|
|
742
|
+
).set_unit(netuid)
|
|
743
|
+
alpha_in_emission = Balance.from_meshlet(decoded.get("alpha_in_emission")).set_unit(
|
|
744
|
+
netuid
|
|
745
|
+
)
|
|
746
|
+
subnet_volume = Balance.from_meshlet(decoded.get("subnet_volume")).set_unit(netuid)
|
|
747
|
+
tao_in_emission = Balance.from_meshlet(decoded.get("tao_in_emission")).set_unit(0)
|
|
748
|
+
pending_alpha_emission = Balance.from_meshlet(
|
|
749
|
+
decoded.get("pending_alpha_emission")
|
|
750
|
+
).set_unit(netuid)
|
|
751
|
+
pending_root_emission = Balance.from_meshlet(
|
|
752
|
+
decoded.get("pending_root_emission")
|
|
753
|
+
).set_unit(0)
|
|
754
|
+
price = (
|
|
755
|
+
Balance.from_tao(1.0)
|
|
756
|
+
if netuid == 0
|
|
757
|
+
else Balance.from_tao(tao_in.tao / alpha_in.tao)
|
|
758
|
+
if alpha_in.tao > 0
|
|
759
|
+
else Balance.from_tao(1)
|
|
760
|
+
) # TODO: Patching this temporarily for netuid 0
|
|
761
|
+
|
|
762
|
+
if decoded.get("subnet_identity"):
|
|
763
|
+
subnet_identity = SubnetIdentity.from_any(decoded.get("subnet_identity"))
|
|
764
|
+
else:
|
|
765
|
+
subnet_identity = None
|
|
766
|
+
|
|
767
|
+
return cls(
|
|
768
|
+
netuid=netuid,
|
|
769
|
+
owner_hotkey=owner_hotkey,
|
|
770
|
+
owner_coldkey=owner_coldkey,
|
|
771
|
+
subnet_name=subnet_name,
|
|
772
|
+
symbol=symbol,
|
|
773
|
+
tempo=int(decoded.get("tempo")),
|
|
774
|
+
last_step=int(decoded.get("last_step")),
|
|
775
|
+
blocks_since_last_step=int(decoded.get("blocks_since_last_step")),
|
|
776
|
+
emission=emission,
|
|
777
|
+
alpha_in=alpha_in,
|
|
778
|
+
alpha_out=alpha_out,
|
|
779
|
+
tao_in=tao_in,
|
|
780
|
+
k=tao_in.meshlet * alpha_in.meshlet,
|
|
781
|
+
is_dynamic=is_dynamic,
|
|
782
|
+
price=price,
|
|
783
|
+
alpha_out_emission=alpha_out_emission,
|
|
784
|
+
alpha_in_emission=alpha_in_emission,
|
|
785
|
+
tao_in_emission=tao_in_emission,
|
|
786
|
+
pending_alpha_emission=pending_alpha_emission,
|
|
787
|
+
pending_root_emission=pending_root_emission,
|
|
788
|
+
network_registered_at=int(decoded.get("network_registered_at")),
|
|
789
|
+
subnet_identity=subnet_identity,
|
|
790
|
+
subnet_volume=subnet_volume,
|
|
791
|
+
moving_price=fixed_to_float(decoded["moving_price"], 32),
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
def tao_to_alpha(self, tao: Balance) -> Balance:
|
|
795
|
+
if self.price.tao != 0:
|
|
796
|
+
return Balance.from_tao(tao.tao / self.price.tao).set_unit(self.netuid)
|
|
797
|
+
else:
|
|
798
|
+
return Balance.from_tao(0)
|
|
799
|
+
|
|
800
|
+
def alpha_to_tao(self, alpha: Balance) -> Balance:
|
|
801
|
+
return Balance.from_tao(alpha.tao * self.price.tao)
|
|
802
|
+
|
|
803
|
+
def tao_to_alpha_with_slippage(
|
|
804
|
+
self, tao: Balance
|
|
805
|
+
) -> tuple[Balance, Balance, float]:
|
|
806
|
+
"""
|
|
807
|
+
Returns an estimate of how much Alpha a staker would receive if they stake their mesh using the current pool
|
|
808
|
+
state.
|
|
809
|
+
|
|
810
|
+
Args:
|
|
811
|
+
tao: Amount of MESH to stake.
|
|
812
|
+
Returns:
|
|
813
|
+
Tuple of balances where the first part is the amount of Alpha received, and the
|
|
814
|
+
second part (slippage) is the difference between the estimated amount and ideal
|
|
815
|
+
amount as if there was no slippage
|
|
816
|
+
"""
|
|
817
|
+
if self.is_dynamic:
|
|
818
|
+
new_tao_in = self.tao_in + tao
|
|
819
|
+
if new_tao_in == 0:
|
|
820
|
+
return tao, Balance.from_meshlet(0)
|
|
821
|
+
new_alpha_in = self.k / new_tao_in
|
|
822
|
+
|
|
823
|
+
# Amount of alpha given to the staker
|
|
824
|
+
alpha_returned = Balance.from_meshlet(
|
|
825
|
+
self.alpha_in.meshlet - new_alpha_in.meshlet
|
|
826
|
+
).set_unit(self.netuid)
|
|
827
|
+
|
|
828
|
+
# Ideal conversion as if there is no slippage, just price
|
|
829
|
+
alpha_ideal = self.tao_to_alpha(tao)
|
|
830
|
+
|
|
831
|
+
if alpha_ideal.tao > alpha_returned.tao:
|
|
832
|
+
slippage = Balance.from_tao(
|
|
833
|
+
alpha_ideal.tao - alpha_returned.tao
|
|
834
|
+
).set_unit(self.netuid)
|
|
835
|
+
else:
|
|
836
|
+
slippage = Balance.from_tao(0)
|
|
837
|
+
else:
|
|
838
|
+
alpha_returned = tao.set_unit(self.netuid)
|
|
839
|
+
slippage = Balance.from_tao(0)
|
|
840
|
+
|
|
841
|
+
slippage_pct_float = (
|
|
842
|
+
100 * float(slippage) / float(slippage + alpha_returned)
|
|
843
|
+
if slippage + alpha_returned != 0
|
|
844
|
+
else 0
|
|
845
|
+
)
|
|
846
|
+
return alpha_returned, slippage, slippage_pct_float
|
|
847
|
+
|
|
848
|
+
def alpha_to_tao_with_slippage(
|
|
849
|
+
self, alpha: Balance
|
|
850
|
+
) -> tuple[Balance, Balance, float]:
|
|
851
|
+
"""
|
|
852
|
+
Returns an estimate of how much MESH a staker would receive if they unstake their alpha using the current pool
|
|
853
|
+
state.
|
|
854
|
+
|
|
855
|
+
Args:
|
|
856
|
+
alpha: Amount of Alpha to stake.
|
|
857
|
+
Returns:
|
|
858
|
+
Tuple of balances where the first part is the amount of MESH received, and the
|
|
859
|
+
second part (slippage) is the difference between the estimated amount and ideal
|
|
860
|
+
amount as if there was no slippage
|
|
861
|
+
"""
|
|
862
|
+
if self.is_dynamic:
|
|
863
|
+
new_alpha_in = self.alpha_in + alpha
|
|
864
|
+
new_tao_reserve = self.k / new_alpha_in
|
|
865
|
+
# Amount of MESH given to the unstaker
|
|
866
|
+
tao_returned = Balance.from_meshlet(self.tao_in - new_tao_reserve)
|
|
867
|
+
|
|
868
|
+
# Ideal conversion as if there is no slippage, just price
|
|
869
|
+
tao_ideal = self.alpha_to_tao(alpha)
|
|
870
|
+
|
|
871
|
+
if tao_ideal > tao_returned:
|
|
872
|
+
slippage = Balance.from_tao(tao_ideal.tao - tao_returned.tao)
|
|
873
|
+
else:
|
|
874
|
+
slippage = Balance.from_tao(0)
|
|
875
|
+
else:
|
|
876
|
+
tao_returned = alpha.set_unit(0)
|
|
877
|
+
slippage = Balance.from_tao(0)
|
|
878
|
+
slippage_pct_float = (
|
|
879
|
+
100 * float(slippage) / float(slippage + tao_returned)
|
|
880
|
+
if slippage + tao_returned != 0
|
|
881
|
+
else 0
|
|
882
|
+
)
|
|
883
|
+
return tao_returned, slippage, slippage_pct_float
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
@dataclass
|
|
887
|
+
class ScheduledColdkeySwapInfo(InfoBase):
|
|
888
|
+
"""Dataclass for scheduled coldkey swap information."""
|
|
889
|
+
|
|
890
|
+
old_coldkey: str
|
|
891
|
+
new_coldkey: str
|
|
892
|
+
arbitration_block: int
|
|
893
|
+
|
|
894
|
+
@classmethod
|
|
895
|
+
def _fix_decoded(cls, decoded: Any) -> "ScheduledColdkeySwapInfo":
|
|
896
|
+
"""Fixes the decoded values."""
|
|
897
|
+
return cls(
|
|
898
|
+
old_coldkey=decode_account_id(decoded.get("old_coldkey")),
|
|
899
|
+
new_coldkey=decode_account_id(decoded.get("new_coldkey")),
|
|
900
|
+
arbitration_block=decoded.get("arbitration_block"),
|
|
901
|
+
)
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
@dataclass
|
|
905
|
+
class SubnetState(InfoBase):
|
|
906
|
+
netuid: int
|
|
907
|
+
hotkeys: list[str]
|
|
908
|
+
coldkeys: list[str]
|
|
909
|
+
active: list[bool]
|
|
910
|
+
validator_permit: list[bool]
|
|
911
|
+
pruning_score: list[float]
|
|
912
|
+
last_update: list[int]
|
|
913
|
+
emission: list[Balance]
|
|
914
|
+
dividends: list[float]
|
|
915
|
+
incentives: list[float]
|
|
916
|
+
consensus: list[float]
|
|
917
|
+
trust: list[float]
|
|
918
|
+
rank: list[float]
|
|
919
|
+
block_at_registration: list[int]
|
|
920
|
+
alpha_stake: list[Balance]
|
|
921
|
+
tao_stake: list[Balance]
|
|
922
|
+
total_stake: list[Balance]
|
|
923
|
+
emission_history: list[list[int]]
|
|
924
|
+
|
|
925
|
+
@classmethod
|
|
926
|
+
def _fix_decoded(cls, decoded: Any) -> "SubnetState":
|
|
927
|
+
netuid = decoded.get("netuid")
|
|
928
|
+
return cls(
|
|
929
|
+
netuid=netuid,
|
|
930
|
+
hotkeys=[decode_account_id(val) for val in decoded.get("hotkeys")],
|
|
931
|
+
coldkeys=[decode_account_id(val) for val in decoded.get("coldkeys")],
|
|
932
|
+
active=decoded.get("active"),
|
|
933
|
+
validator_permit=decoded.get("validator_permit"),
|
|
934
|
+
pruning_score=[u16tf(val) for val in decoded.get("pruning_score")],
|
|
935
|
+
last_update=decoded.get("last_update"),
|
|
936
|
+
emission=[
|
|
937
|
+
Balance.from_meshlet(val).set_unit(netuid)
|
|
938
|
+
for val in decoded.get("emission")
|
|
939
|
+
],
|
|
940
|
+
dividends=[u16tf(val) for val in decoded.get("dividends")],
|
|
941
|
+
incentives=[u16tf(val) for val in decoded.get("incentives")],
|
|
942
|
+
consensus=[u16tf(val) for val in decoded.get("consensus")],
|
|
943
|
+
trust=[u16tf(val) for val in decoded.get("trust")],
|
|
944
|
+
rank=[u16tf(val) for val in decoded.get("rank")],
|
|
945
|
+
block_at_registration=decoded.get("block_at_registration"),
|
|
946
|
+
alpha_stake=[
|
|
947
|
+
Balance.from_meshlet(val).set_unit(netuid)
|
|
948
|
+
for val in decoded.get("alpha_stake")
|
|
949
|
+
],
|
|
950
|
+
tao_stake=[
|
|
951
|
+
Balance.from_meshlet(val).set_unit(0) for val in decoded.get("tao_stake")
|
|
952
|
+
],
|
|
953
|
+
total_stake=[
|
|
954
|
+
Balance.from_meshlet(val).set_unit(netuid)
|
|
955
|
+
for val in decoded.get("total_stake")
|
|
956
|
+
],
|
|
957
|
+
emission_history=decoded.get("emission_history"),
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
|
|
961
|
+
@dataclass
|
|
962
|
+
class ChainIdentity(InfoBase):
|
|
963
|
+
"""Dataclass for chain identity information."""
|
|
964
|
+
|
|
965
|
+
name: str
|
|
966
|
+
url: str
|
|
967
|
+
github: str
|
|
968
|
+
image: str
|
|
969
|
+
discord: str
|
|
970
|
+
description: str
|
|
971
|
+
additional: str
|
|
972
|
+
|
|
973
|
+
@classmethod
|
|
974
|
+
def _from_dict(cls, decoded: dict) -> "ChainIdentity":
|
|
975
|
+
"""Returns a ChainIdentity object from decoded chain data."""
|
|
976
|
+
return cls(
|
|
977
|
+
name=decoded["name"],
|
|
978
|
+
url=decoded["url"],
|
|
979
|
+
github=decoded["github_repo"],
|
|
980
|
+
image=decoded["image"],
|
|
981
|
+
discord=decoded["discord"],
|
|
982
|
+
description=decoded["description"],
|
|
983
|
+
additional=decoded["additional"],
|
|
984
|
+
)
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
@dataclass
|
|
988
|
+
class MetagraphInfo(InfoBase):
|
|
989
|
+
# Subnet index
|
|
990
|
+
netuid: int
|
|
991
|
+
|
|
992
|
+
# Name and symbol
|
|
993
|
+
name: str
|
|
994
|
+
symbol: str
|
|
995
|
+
identity: Optional[SubnetIdentity]
|
|
996
|
+
network_registered_at: int
|
|
997
|
+
|
|
998
|
+
# Keys for owner.
|
|
999
|
+
owner_hotkey: str # hotkey
|
|
1000
|
+
owner_coldkey: str # coldkey
|
|
1001
|
+
|
|
1002
|
+
# Tempo terms.
|
|
1003
|
+
block: int # block at call.
|
|
1004
|
+
tempo: int # epoch tempo
|
|
1005
|
+
last_step: int
|
|
1006
|
+
blocks_since_last_step: int
|
|
1007
|
+
|
|
1008
|
+
# Subnet emission terms
|
|
1009
|
+
subnet_emission: Balance # subnet emission via tao
|
|
1010
|
+
alpha_in: Balance # amount of alpha in reserve
|
|
1011
|
+
alpha_out: Balance # amount of alpha outstanding
|
|
1012
|
+
tao_in: Balance # amount of mesh injected per block
|
|
1013
|
+
alpha_out_emission: Balance # amount injected in alpha reserves per block
|
|
1014
|
+
alpha_in_emission: Balance # amount injected outstanding per block
|
|
1015
|
+
tao_in_emission: Balance # amount of mesh injected per block
|
|
1016
|
+
pending_alpha_emission: Balance # pending alpha to be distributed
|
|
1017
|
+
pending_root_emission: Balance # pending mesh for root divs to be distributed
|
|
1018
|
+
subnet_volume: Balance # volume of the subnet in MESH
|
|
1019
|
+
moving_price: Balance # subnet moving price.
|
|
1020
|
+
|
|
1021
|
+
# Hparams for epoch
|
|
1022
|
+
rho: int # subnet rho param
|
|
1023
|
+
kappa: float # subnet kappa param
|
|
1024
|
+
|
|
1025
|
+
# Validator params
|
|
1026
|
+
min_allowed_weights: float # min allowed weights per val
|
|
1027
|
+
max_weights_limit: float # max allowed weights per val
|
|
1028
|
+
weights_version: int # allowed weights version
|
|
1029
|
+
weights_rate_limit: int # rate limit on weights.
|
|
1030
|
+
activity_cutoff: int # validator weights cut off period in blocks
|
|
1031
|
+
max_validators: int # max allowed validators.
|
|
1032
|
+
|
|
1033
|
+
# Registration
|
|
1034
|
+
num_uids: int
|
|
1035
|
+
max_uids: int
|
|
1036
|
+
burn: Balance # current burn cost.
|
|
1037
|
+
difficulty: float # current difficulty.
|
|
1038
|
+
registration_allowed: bool # allows registrations.
|
|
1039
|
+
pow_registration_allowed: bool # pow registration enabled.
|
|
1040
|
+
immunity_period: int # subnet miner immunity period
|
|
1041
|
+
min_difficulty: float # min pow difficulty
|
|
1042
|
+
max_difficulty: float # max pow difficulty
|
|
1043
|
+
min_burn: Balance # min mesh burn
|
|
1044
|
+
max_burn: Balance # max mesh burn
|
|
1045
|
+
adjustment_alpha: float # adjustment speed for registration params.
|
|
1046
|
+
adjustment_interval: int # pow and burn adjustment interval
|
|
1047
|
+
target_regs_per_interval: int # target registrations per interval
|
|
1048
|
+
max_regs_per_block: int # max registrations per block.
|
|
1049
|
+
serving_rate_limit: int # axon serving rate limit
|
|
1050
|
+
|
|
1051
|
+
# CR
|
|
1052
|
+
commit_reveal_weights_enabled: bool # Is CR enabled.
|
|
1053
|
+
commit_reveal_period: int # Commit reveal interval
|
|
1054
|
+
|
|
1055
|
+
# Bonds
|
|
1056
|
+
liquid_alpha_enabled: bool # Bonds liquid enabled.
|
|
1057
|
+
alpha_high: float # Alpha param high
|
|
1058
|
+
alpha_low: float # Alpha param low
|
|
1059
|
+
bonds_moving_avg: float # Bonds moving avg
|
|
1060
|
+
|
|
1061
|
+
# Metagraph info.
|
|
1062
|
+
hotkeys: list[str] # hotkey per UID
|
|
1063
|
+
coldkeys: list[str] # coldkey per UID
|
|
1064
|
+
identities: list[Optional[ChainIdentity]] # coldkeys identities
|
|
1065
|
+
axons: list[AxonInfo] # UID axons.
|
|
1066
|
+
active: list[bool] # Active per UID
|
|
1067
|
+
validator_permit: list[bool] # Val permit per UID
|
|
1068
|
+
pruning_score: list[float] # Pruning per UID
|
|
1069
|
+
last_update: list[int] # Last update per UID
|
|
1070
|
+
emission: list[Balance] # Emission per UID
|
|
1071
|
+
dividends: list[float] # Dividends per UID
|
|
1072
|
+
incentives: list[float] # Mining incentives per UID
|
|
1073
|
+
consensus: list[float] # Consensus per UID
|
|
1074
|
+
trust: list[float] # Trust per UID
|
|
1075
|
+
rank: list[float] # Rank per UID
|
|
1076
|
+
block_at_registration: list[int] # Reg block per UID
|
|
1077
|
+
alpha_stake: list[Balance] # Alpha staked per UID
|
|
1078
|
+
tao_stake: list[Balance] # MESH staked per UID
|
|
1079
|
+
total_stake: list[Balance] # Total stake per UID
|
|
1080
|
+
|
|
1081
|
+
# Dividend break down.
|
|
1082
|
+
tao_dividends_per_hotkey: list[
|
|
1083
|
+
tuple[str, Balance]
|
|
1084
|
+
] # List of dividend payouts in mesh via root.
|
|
1085
|
+
alpha_dividends_per_hotkey: list[
|
|
1086
|
+
tuple[str, Balance]
|
|
1087
|
+
] # List of dividend payout in alpha via subnet.
|
|
1088
|
+
subuid: int = 0
|
|
1089
|
+
|
|
1090
|
+
@classmethod
|
|
1091
|
+
def _fix_decoded(cls, decoded: dict) -> "MetagraphInfo":
|
|
1092
|
+
"""Returns a MetagraphInfo object from decoded chain data."""
|
|
1093
|
+
# Subnet index
|
|
1094
|
+
_netuid, _subuid = get_netuid_and_subuid_by_storage_index(decoded["netuid"])
|
|
1095
|
+
|
|
1096
|
+
# Name and symbol
|
|
1097
|
+
decoded.update({"name": bytes(decoded.get("name")).decode()})
|
|
1098
|
+
decoded.update({"symbol": bytes(decoded.get("symbol")).decode()})
|
|
1099
|
+
for key in ["identities", "identity"]:
|
|
1100
|
+
raw_data = decoded.get(key)
|
|
1101
|
+
processed = process_nested(raw_data, _chr_str)
|
|
1102
|
+
decoded.update({key: processed})
|
|
1103
|
+
|
|
1104
|
+
return cls(
|
|
1105
|
+
# Subnet index
|
|
1106
|
+
netuid=_netuid,
|
|
1107
|
+
subuid=_subuid,
|
|
1108
|
+
# Name and symbol
|
|
1109
|
+
name=decoded["name"],
|
|
1110
|
+
symbol=decoded["symbol"],
|
|
1111
|
+
identity=decoded["identity"],
|
|
1112
|
+
network_registered_at=decoded["network_registered_at"],
|
|
1113
|
+
# Keys for owner.
|
|
1114
|
+
owner_hotkey=decoded["owner_hotkey"],
|
|
1115
|
+
owner_coldkey=decoded["owner_coldkey"],
|
|
1116
|
+
# Tempo terms.
|
|
1117
|
+
block=decoded["block"],
|
|
1118
|
+
tempo=decoded["tempo"],
|
|
1119
|
+
last_step=decoded["last_step"],
|
|
1120
|
+
blocks_since_last_step=decoded["blocks_since_last_step"],
|
|
1121
|
+
# Subnet emission terms
|
|
1122
|
+
subnet_emission=_tbwu(decoded["subnet_emission"]),
|
|
1123
|
+
alpha_in=_tbwu(decoded["alpha_in"], _netuid),
|
|
1124
|
+
alpha_out=_tbwu(decoded["alpha_out"], _netuid),
|
|
1125
|
+
tao_in=_tbwu(decoded["tao_in"]),
|
|
1126
|
+
alpha_out_emission=_tbwu(decoded["alpha_out_emission"], _netuid),
|
|
1127
|
+
alpha_in_emission=_tbwu(decoded["alpha_in_emission"], _netuid),
|
|
1128
|
+
tao_in_emission=_tbwu(decoded["tao_in_emission"]),
|
|
1129
|
+
pending_alpha_emission=_tbwu(decoded["pending_alpha_emission"], _netuid),
|
|
1130
|
+
pending_root_emission=_tbwu(decoded["pending_root_emission"]),
|
|
1131
|
+
subnet_volume=_tbwu(decoded["subnet_volume"], _netuid),
|
|
1132
|
+
moving_price=Balance.from_tao(
|
|
1133
|
+
fixed_to_float(decoded.get("moving_price"), 32)
|
|
1134
|
+
),
|
|
1135
|
+
# Hparams for epoch
|
|
1136
|
+
rho=decoded["rho"],
|
|
1137
|
+
kappa=decoded["kappa"],
|
|
1138
|
+
# Validator params
|
|
1139
|
+
min_allowed_weights=u16tf(decoded["min_allowed_weights"]),
|
|
1140
|
+
max_weights_limit=u16tf(decoded["max_weights_limit"]),
|
|
1141
|
+
weights_version=decoded["weights_version"],
|
|
1142
|
+
weights_rate_limit=decoded["weights_rate_limit"],
|
|
1143
|
+
activity_cutoff=decoded["activity_cutoff"],
|
|
1144
|
+
max_validators=decoded["max_validators"],
|
|
1145
|
+
# Registration
|
|
1146
|
+
num_uids=decoded["num_uids"],
|
|
1147
|
+
max_uids=decoded["max_uids"],
|
|
1148
|
+
burn=_tbwu(decoded["burn"]),
|
|
1149
|
+
difficulty=u64tf(decoded["difficulty"]),
|
|
1150
|
+
registration_allowed=decoded["registration_allowed"],
|
|
1151
|
+
pow_registration_allowed=decoded["pow_registration_allowed"],
|
|
1152
|
+
immunity_period=decoded["immunity_period"],
|
|
1153
|
+
min_difficulty=u64tf(decoded["min_difficulty"]),
|
|
1154
|
+
max_difficulty=u64tf(decoded["max_difficulty"]),
|
|
1155
|
+
min_burn=_tbwu(decoded["min_burn"]),
|
|
1156
|
+
max_burn=_tbwu(decoded["max_burn"]),
|
|
1157
|
+
adjustment_alpha=u64tf(decoded["adjustment_alpha"]),
|
|
1158
|
+
adjustment_interval=decoded["adjustment_interval"],
|
|
1159
|
+
target_regs_per_interval=decoded["target_regs_per_interval"],
|
|
1160
|
+
max_regs_per_block=decoded["max_regs_per_block"],
|
|
1161
|
+
serving_rate_limit=decoded["serving_rate_limit"],
|
|
1162
|
+
# CR
|
|
1163
|
+
commit_reveal_weights_enabled=decoded["commit_reveal_weights_enabled"],
|
|
1164
|
+
commit_reveal_period=decoded["commit_reveal_period"],
|
|
1165
|
+
# Bonds
|
|
1166
|
+
liquid_alpha_enabled=decoded["liquid_alpha_enabled"],
|
|
1167
|
+
alpha_high=u16tf(decoded["alpha_high"]),
|
|
1168
|
+
alpha_low=u16tf(decoded["alpha_low"]),
|
|
1169
|
+
bonds_moving_avg=u64tf(decoded["bonds_moving_avg"]),
|
|
1170
|
+
# Metagraph info.
|
|
1171
|
+
hotkeys=[decode_account_id(ck) for ck in decoded.get("hotkeys", [])],
|
|
1172
|
+
coldkeys=[decode_account_id(hk) for hk in decoded.get("coldkeys", [])],
|
|
1173
|
+
identities=decoded["identities"],
|
|
1174
|
+
axons=decoded.get("axons", []),
|
|
1175
|
+
active=decoded["active"],
|
|
1176
|
+
validator_permit=decoded["validator_permit"],
|
|
1177
|
+
pruning_score=[u16tf(ps) for ps in decoded.get("pruning_score", [])],
|
|
1178
|
+
last_update=decoded["last_update"],
|
|
1179
|
+
emission=[_tbwu(em, _netuid) for em in decoded.get("emission", [])],
|
|
1180
|
+
dividends=[u16tf(dv) for dv in decoded.get("dividends", [])],
|
|
1181
|
+
incentives=[u16tf(ic) for ic in decoded.get("incentives", [])],
|
|
1182
|
+
consensus=[u16tf(cs) for cs in decoded.get("consensus", [])],
|
|
1183
|
+
trust=[u16tf(tr) for tr in decoded.get("trust", [])],
|
|
1184
|
+
rank=[u16tf(rk) for rk in decoded.get("rank", [])],
|
|
1185
|
+
block_at_registration=decoded["block_at_registration"],
|
|
1186
|
+
alpha_stake=[_tbwu(ast, _netuid) for ast in decoded["alpha_stake"]],
|
|
1187
|
+
tao_stake=[_tbwu(ts) for ts in decoded["tao_stake"]],
|
|
1188
|
+
total_stake=[_tbwu(ts, _netuid) for ts in decoded["total_stake"]],
|
|
1189
|
+
# Dividend break down
|
|
1190
|
+
tao_dividends_per_hotkey=[
|
|
1191
|
+
(decode_account_id(alpha[0]), _tbwu(alpha[1]))
|
|
1192
|
+
for alpha in decoded["tao_dividends_per_hotkey"]
|
|
1193
|
+
],
|
|
1194
|
+
alpha_dividends_per_hotkey=[
|
|
1195
|
+
(decode_account_id(adphk[0]), _tbwu(adphk[1], _netuid))
|
|
1196
|
+
for adphk in decoded["alpha_dividends_per_hotkey"]
|
|
1197
|
+
],
|
|
1198
|
+
)
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
@dataclass
|
|
1202
|
+
class SimSwapResult:
|
|
1203
|
+
tao_amount: Balance
|
|
1204
|
+
alpha_amount: Balance
|
|
1205
|
+
tao_fee: Balance
|
|
1206
|
+
alpha_fee: Balance
|
|
1207
|
+
|
|
1208
|
+
@classmethod
|
|
1209
|
+
def from_dict(cls, d: dict, netuid: int) -> "SimSwapResult":
|
|
1210
|
+
return cls(
|
|
1211
|
+
tao_amount=Balance.from_meshlet(d["tao_amount"]).set_unit(0),
|
|
1212
|
+
alpha_amount=Balance.from_meshlet(d["alpha_amount"]).set_unit(netuid),
|
|
1213
|
+
tao_fee=Balance.from_meshlet(d["tao_fee"]).set_unit(0),
|
|
1214
|
+
alpha_fee=Balance.from_meshlet(d["alpha_fee"]).set_unit(netuid),
|
|
1215
|
+
)
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
@dataclass
|
|
1219
|
+
class CrowdloanData(InfoBase):
|
|
1220
|
+
creator: Optional[str]
|
|
1221
|
+
funds_account: Optional[str]
|
|
1222
|
+
deposit: Balance
|
|
1223
|
+
min_contribution: Balance
|
|
1224
|
+
cap: Balance
|
|
1225
|
+
raised: Balance
|
|
1226
|
+
end: int
|
|
1227
|
+
finalized: bool
|
|
1228
|
+
contributors_count: int
|
|
1229
|
+
target_address: Optional[str]
|
|
1230
|
+
has_call: bool
|
|
1231
|
+
call_details: Optional[dict] = None
|
|
1232
|
+
|
|
1233
|
+
@classmethod
|
|
1234
|
+
def _fix_decoded(cls, decoded: dict[str, Any]) -> "CrowdloanData":
|
|
1235
|
+
creator = (
|
|
1236
|
+
decode_account_id(creator_raw)
|
|
1237
|
+
if (creator_raw := decoded.get("creator"))
|
|
1238
|
+
else None
|
|
1239
|
+
)
|
|
1240
|
+
funds_account = (
|
|
1241
|
+
decode_account_id(funds_raw)
|
|
1242
|
+
if (funds_raw := decoded.get("funds_account"))
|
|
1243
|
+
else None
|
|
1244
|
+
)
|
|
1245
|
+
target_address = (
|
|
1246
|
+
decode_account_id(target_raw)
|
|
1247
|
+
if (target_raw := decoded.get("target_address"))
|
|
1248
|
+
else None
|
|
1249
|
+
)
|
|
1250
|
+
return cls(
|
|
1251
|
+
creator=creator,
|
|
1252
|
+
funds_account=funds_account,
|
|
1253
|
+
deposit=Balance.from_meshlet(int(decoded["deposit"])),
|
|
1254
|
+
min_contribution=Balance.from_meshlet(int(decoded["min_contribution"])),
|
|
1255
|
+
cap=Balance.from_meshlet(int(decoded["cap"])),
|
|
1256
|
+
raised=Balance.from_meshlet(int(decoded["raised"])),
|
|
1257
|
+
end=int(decoded["end"]),
|
|
1258
|
+
finalized=bool(decoded["finalized"]),
|
|
1259
|
+
contributors_count=int(decoded["contributors_count"]),
|
|
1260
|
+
target_address=target_address,
|
|
1261
|
+
has_call=bool(decoded["call"]),
|
|
1262
|
+
call_details=decoded["call_details"],
|
|
1263
|
+
)
|