Skip to content
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
f62c058
update settings.py
Jan 28, 2025
7ce69cb
update balance.py
Jan 28, 2025
af9e7a9
Updates chain_data
ibraheem-abe Jan 28, 2025
54fdb25
Updates balance class
ibraheem-abe Jan 28, 2025
6734673
update `bittensor.core.chain_data` sub-package
Jan 28, 2025
2f3da87
update async/subtensor modules -> added get_metagraph_info and get_al…
Jan 28, 2025
c6d56ad
fix test
Jan 28, 2025
3f73742
Merge branch 'staging-pre-merge-port-rao' into feat/roman/brigh-chain…
Jan 28, 2025
61f0ec5
update `bittensor/core/chain_data/__init__.py`
Jan 28, 2025
40b1dea
ruff
Jan 28, 2025
f13e97e
Add alias for Subtensor.commit
Jan 28, 2025
7c72b0a
move units from settings.py to balance.py
Jan 28, 2025
f4ad1e0
ruff
Jan 28, 2025
02dcbc0
Merge pull request #2606 from opentensor/feat/add/add-alias-for-subte…
basfroman Jan 28, 2025
ba6f2f9
update requirements
Jan 28, 2025
0837148
update requirements
Jan 28, 2025
a918df1
Merge pull request #2605 from opentensor/feat/roman/brigh-chain-metag…
basfroman Jan 28, 2025
a76d8bb
add `set_commitment` to async_subtensor.Async_subtensor
Jan 28, 2025
105eaba
Updates staking
ibraheem-abe Jan 28, 2025
2cb49cf
Unstaking updated
ibraheem-abe Jan 29, 2025
64ec5a6
Adds subnet, all_subnets calls and move, transfer, swap extrinsics
ibraheem-abe Jan 29, 2025
ef3548a
Add in `tao` and `rao` factory functions.
thewhaleking Jan 29, 2025
b3616e6
Supports async + minor tweaks
ibraheem-abe Jan 29, 2025
f601e7c
ruff + mypy
Jan 29, 2025
f068774
update metagraph.py
Jan 29, 2025
85eaa90
Adds explicit type for balance inputs
ibraheem-abe Jan 29, 2025
763c8af
Merge branch 'refs/heads/staging-pre-merge-port-rao' into feat/roman/…
Jan 29, 2025
001b46c
Merge pull request #2611 from opentensor/feat/roman/update-metagraph-…
basfroman Jan 29, 2025
c2bf3ca
Improves logging statements
ibraheem-abe Jan 30, 2025
ec32d9f
Updates balance conversion unit
ibraheem-abe Jan 30, 2025
45be077
fix for unit test + refactoring
Jan 30, 2025
f475d52
typos fix
Jan 30, 2025
87b96ec
add gather + improve `async subtensor.get_stake_for_coldkey` method
Jan 30, 2025
b861606
add block_hash to subtensor.get_stake_for_coldkey call
Jan 30, 2025
6a7e322
update `subtensor.query_module` return type
Jan 30, 2025
aef096c
async-substrate-interface==`1.0.0rc5` to `1.0.0rc6`
Jan 30, 2025
8385a85
fix types for mypy
Jan 30, 2025
1a4da29
Merge pull request #2612 from opentensor/feat/roman/fix-unit-tests+re…
basfroman Jan 30, 2025
d94c518
fix integration metagraph test
Jan 30, 2025
755fa78
Merge branch 'staging-pre-merge-new-async' into staging-pre-merge-por…
Jan 30, 2025
e50a697
Merge branch 'staging-pre-merge-port-rao' into feat/roman/last-integr…
Jan 30, 2025
fc20eee
fix unit test
Jan 30, 2025
6e76992
replace sync result to async one for test. bring back `async for`
basfroman Jan 30, 2025
6ad8913
remove commented code
basfroman Jan 30, 2025
ab673a3
Merge pull request #2613 from opentensor/feat/roman/last-integration-…
basfroman Jan 30, 2025
f5caea4
Cleanups, fixes, improvements
thewhaleking Jan 30, 2025
1497be4
Flake
thewhaleking Jan 30, 2025
4b291ad
Requirements
thewhaleking Jan 30, 2025
b4c7249
PR comments
thewhaleking Jan 30, 2025
f519384
Merge pull request #2614 from opentensor/async/thewhaleking/pre-merge…
thewhaleking Jan 30, 2025
9bd155b
Adds deprecation notice for balance amounts
ibraheem-abe Jan 30, 2025
9e342ed
Update to use console
ibraheem-abe Jan 30, 2025
7224ae6
Updates method name
ibraheem-abe Jan 30, 2025
c9b7403
Updates deprecation text
ibraheem-abe Jan 30, 2025
5408b68
Updates to use warnings
ibraheem-abe Jan 30, 2025
4159cd9
Merge pull request #2615 from opentensor/staging-pre-merge-deprecatio…
ibraheem-abe Jan 30, 2025
c72d8a4
Removes balance alias
ibraheem-abe Jan 30, 2025
3320cbe
Adds warnings + fixes types
ibraheem-abe Jan 30, 2025
4d7aa10
rename deprecated.py to easy_imports.py
Jan 30, 2025
e48f55d
improve type annotations in axon.py
Jan 30, 2025
9ccf1e1
Merge remote-tracking branch 'origin/staging-pre-merge-port-rao' into…
Jan 30, 2025
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
362 changes: 333 additions & 29 deletions bittensor/core/async_subtensor.py

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions bittensor/core/chain_data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
from scalecodec.types import GenericCall

from .axon_info import AxonInfo
from .chain_identity import ChainIdentity
from .delegate_info import DelegateInfo
from .delegate_info_lite import DelegateInfoLite
from .dynamic_info import DynamicInfo
from .ip_info import IPInfo
from .metagraph_info import MetagraphInfo
from .neuron_info import NeuronInfo
from .neuron_info_lite import NeuronInfoLite
from .neuron_certificate import NeuronCertificate
Expand All @@ -17,8 +20,36 @@
from .scheduled_coldkey_swap_info import ScheduledColdkeySwapInfo
from .stake_info import StakeInfo
from .subnet_hyperparameters import SubnetHyperparameters
from .subnet_identity import SubnetIdentity
from .subnet_info import SubnetInfo
from .subnet_state import SubnetState
from .weight_commit_info import WeightCommitInfo
from .utils import custom_rpc_type_registry, decode_account_id, process_stake_data

ProposalCallData = GenericCall

__all__ = [
AxonInfo,
ChainIdentity,
DelegateInfo,
DelegateInfoLite,
DynamicInfo,
IPInfo,
MetagraphInfo,
NeuronInfo,
NeuronInfoLite,
NeuronCertificate,
PrometheusInfo,
ProposalCallData,
ProposalVoteData,
ScheduledColdkeySwapInfo,
StakeInfo,
SubnetHyperparameters,
SubnetIdentity,
SubnetInfo,
SubnetState,
WeightCommitInfo,
custom_rpc_type_registry,
decode_account_id,
process_stake_data,
]
15 changes: 15 additions & 0 deletions bittensor/core/chain_data/chain_identity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from dataclasses import dataclass


@dataclass
class ChainIdentity:
"""Dataclass for chain identity information."""

# In `bittensor.core.chain_data.utils.custom_rpc_type_registry` represents as `ChainIdentityOf` structure.

name: str
url: str
image: str
discord: str
description: str
additional: str
246 changes: 246 additions & 0 deletions bittensor/core/chain_data/dynamic_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
"""
This module defines the `DynamicInfo` data class and associated methods for handling and decoding
dynamic information in the Bittensor network.
"""

from dataclasses import dataclass
from typing import Optional, Union

from scalecodec.utils.ss58 import ss58_encode

from bittensor.core.chain_data.utils import (
ChainDataType,
from_scale_encoding,
SS58_FORMAT,
)
from bittensor.core.chain_data.subnet_identity import SubnetIdentity
from bittensor.utils.balance import Balance


@dataclass
class DynamicInfo:
netuid: int
owner_hotkey: str
owner_coldkey: str
subnet_name: str
symbol: str
tempo: int
last_step: int
blocks_since_last_step: int
emission: Balance
alpha_in: Balance
alpha_out: Balance
tao_in: Balance
price: Balance
k: float
is_dynamic: bool
alpha_out_emission: Balance
alpha_in_emission: Balance
tao_in_emission: Balance
pending_alpha_emission: Balance
pending_root_emission: Balance
network_registered_at: int
subnet_identity: Optional[SubnetIdentity]

@classmethod
def from_vec_u8(cls, vec_u8: list[int]) -> Optional["DynamicInfo"]:
if len(vec_u8) == 0:
return None
decoded = from_scale_encoding(vec_u8, ChainDataType.DynamicInfo)
if decoded is None:
return None
return DynamicInfo.fix_decoded_values(decoded)

@classmethod
def list_from_vec_u8(cls, vec_u8: Union[list[int], bytes]) -> list["DynamicInfo"]:
decoded = from_scale_encoding(
vec_u8, ChainDataType.DynamicInfo, is_vec=True, is_option=True
)
if decoded is None:
return []
decoded = [DynamicInfo.fix_decoded_values(d) for d in decoded]
return decoded

@classmethod
def fix_decoded_values(cls, decoded: dict) -> "DynamicInfo":
"""Returns a DynamicInfo object from a decoded DynamicInfo dictionary."""

netuid = int(decoded["netuid"])
symbol = bytes([int(b) for b in decoded["token_symbol"]]).decode()
subnet_name = bytes([int(b) for b in decoded["subnet_name"]]).decode()

is_dynamic = (
True if int(decoded["netuid"]) > 0 else False
) # Root is not dynamic

owner_hotkey = ss58_encode(decoded["owner_hotkey"], SS58_FORMAT)
owner_coldkey = ss58_encode(decoded["owner_coldkey"], SS58_FORMAT)

emission = Balance.from_rao(decoded["emission"]).set_unit(0)
alpha_in = Balance.from_rao(decoded["alpha_in"]).set_unit(netuid)
alpha_out = Balance.from_rao(decoded["alpha_out"]).set_unit(netuid)
tao_in = Balance.from_rao(decoded["tao_in"]).set_unit(0)
alpha_out_emission = Balance.from_rao(decoded["alpha_out_emission"]).set_unit(
netuid
)
alpha_in_emission = Balance.from_rao(decoded["alpha_in_emission"]).set_unit(
netuid
)
tao_in_emission = Balance.from_rao(decoded["tao_in_emission"]).set_unit(0)
pending_alpha_emission = Balance.from_rao(
decoded["pending_alpha_emission"]
).set_unit(netuid)
pending_root_emission = Balance.from_rao(
decoded["pending_root_emission"]
).set_unit(0)

price = (
Balance.from_tao(1.0)
if netuid == 0
else Balance.from_tao(tao_in.tao / alpha_in.tao)
if alpha_in.tao > 0
else Balance.from_tao(1)
) # Root always has 1-1 price

if decoded.get("subnet_identity"):
subnet_identity = SubnetIdentity(
subnet_name=decoded["subnet_identity"]["subnet_name"],
github_repo=decoded["subnet_identity"]["github_repo"],
subnet_contact=decoded["subnet_identity"]["subnet_contact"],
)
else:
subnet_identity = None

return cls(
netuid=netuid,
owner_hotkey=owner_hotkey,
owner_coldkey=owner_coldkey,
subnet_name=subnet_name,
symbol=symbol,
tempo=int(decoded["tempo"]),
last_step=int(decoded["last_step"]),
blocks_since_last_step=int(decoded["blocks_since_last_step"]),
emission=emission,
alpha_in=alpha_in,
alpha_out=alpha_out,
tao_in=tao_in,
k=tao_in.rao * alpha_in.rao,
is_dynamic=is_dynamic,
price=price,
alpha_out_emission=alpha_out_emission,
alpha_in_emission=alpha_in_emission,
tao_in_emission=tao_in_emission,
pending_alpha_emission=pending_alpha_emission,
pending_root_emission=pending_root_emission,
network_registered_at=int(decoded["network_registered_at"]),
subnet_identity=subnet_identity,
)

def tao_to_alpha(self, tao: Union[Balance, float, int]) -> Balance:
if isinstance(tao, (float, int)):
tao = Balance.from_tao(tao)
if self.price.tao != 0:
return Balance.from_tao(tao.tao / self.price.tao).set_unit(self.netuid)
else:
return Balance.from_tao(0)

def alpha_to_tao(self, alpha: Union[Balance, float, int]) -> Balance:
if isinstance(alpha, (float, int)):
alpha = Balance.from_tao(alpha)
return Balance.from_tao(alpha.tao * self.price.tao)

def tao_to_alpha_with_slippage(
self, tao: Union[Balance, float, int], percentage: bool = False
) -> Union[tuple[Balance, Balance], float]:
"""
Returns an estimate of how much Alpha would a staker receive if they stake their tao using the current pool state.
Args:
tao: Amount of TAO to stake.
Returns:
If percentage is False, a tuple of balances where the first part is the amount of Alpha received, and the
second part (slippage) is the difference between the estimated amount and ideal
amount as if there was no slippage. If percentage is True, a float representing the slippage percentage.
"""
if isinstance(tao, (float, int)):
tao = Balance.from_tao(tao)

if self.is_dynamic:
new_tao_in = self.tao_in + tao
if new_tao_in == 0:
return tao, Balance.from_rao(0)
new_alpha_in = self.k / new_tao_in

# Amount of alpha given to the staker
alpha_returned = Balance.from_rao(
self.alpha_in.rao - new_alpha_in.rao
).set_unit(self.netuid)

# Ideal conversion as if there is no slippage, just price
alpha_ideal = self.tao_to_alpha(tao)

if alpha_ideal.tao > alpha_returned.tao:
slippage = Balance.from_tao(
alpha_ideal.tao - alpha_returned.tao
).set_unit(self.netuid)
else:
slippage = Balance.from_tao(0)
else:
alpha_returned = tao.set_unit(self.netuid)
slippage = Balance.from_tao(0)

if percentage:
slippage_pct_float = (
100 * float(slippage) / float(slippage + alpha_returned)
if slippage + alpha_returned != 0
else 0
)
return slippage_pct_float
else:
return alpha_returned, slippage

slippage = tao_to_alpha_with_slippage
tao_slippage = tao_to_alpha_with_slippage

def alpha_to_tao_with_slippage(
self, alpha: Union[Balance, float, int], percentage: bool = False
) -> Union[tuple[Balance, Balance], float]:
"""
Returns an estimate of how much TAO would a staker receive if they unstake their alpha using the current pool state.
Args:
alpha: Amount of Alpha to stake.
Returns:
If percentage is False, a tuple of balances where the first part is the amount of TAO received, and the
second part (slippage) is the difference between the estimated amount and ideal
amount as if there was no slippage. If percentage is True, a float representing the slippage percentage.
"""
if isinstance(alpha, (float, int)):
alpha = Balance.from_tao(alpha)

if self.is_dynamic:
new_alpha_in = self.alpha_in + alpha
new_tao_reserve = self.k / new_alpha_in
# Amount of TAO given to the unstaker
tao_returned = Balance.from_rao(self.tao_in.rao - new_tao_reserve.rao)

# Ideal conversion as if there is no slippage, just price
tao_ideal = self.alpha_to_tao(alpha)

if tao_ideal > tao_returned:
slippage = Balance.from_tao(tao_ideal.tao - tao_returned.tao)
else:
slippage = Balance.from_tao(0)
else:
tao_returned = alpha.set_unit(0)
slippage = Balance.from_tao(0)

if percentage:
slippage_pct_float = (
100 * float(slippage) / float(slippage + tao_returned)
if slippage + tao_returned != 0
else 0
)
return slippage_pct_float
else:
return tao_returned, slippage

alpha_slippage = alpha_to_tao_with_slippage
Loading