# The MIT License (MIT)
# Copyright © 2021-2022 Yuma Rao
# Copyright © 2022 Opentensor Foundation
# Copyright © 2023 Opentensor Technologies Inc
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
# documentation files (the “Software”), to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of
# the Software.
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
from typing import Union
import bittensor
[docs]
class Balance:
"""
Represents the bittensor balance of the wallet, stored as rao (int).
This class provides a way to interact with balances in two different units: rao and tao.
It provides methods to convert between these units, as well as to perform arithmetic and comparison operations.
Attributes:
unit: A string representing the symbol for the tao unit.
rao_unit: A string representing the symbol for the rao unit.
rao: An integer that stores the balance in rao units.
tao: A float property that gives the balance in tao units.
"""
unit: str = bittensor.__tao_symbol__ # This is the tao unit
rao_unit: str = bittensor.__rao_symbol__ # This is the rao unit
rao: int
tao: float
def __init__(self, balance: Union[int, float]):
"""
Initialize a Balance object. If balance is an int, it's assumed to be in rao.
If balance is a float, it's assumed to be in tao.
Args:
balance: The initial balance, in either rao (if an int) or tao (if a float).
"""
if isinstance(balance, int):
self.rao = balance
elif isinstance(balance, float):
# Assume tao value for the float
self.rao = int(balance * pow(10, 9))
else:
raise TypeError("balance must be an int (rao) or a float (tao)")
@property
def tao(self):
return self.rao / pow(10, 9)
def __int__(self):
"""
Convert the Balance object to an int. The resulting value is in rao.
"""
return self.rao
def __float__(self):
"""
Convert the Balance object to a float. The resulting value is in tao.
"""
return self.tao
[docs]
def __str__(self):
"""
Returns the Balance object as a string in the format "symbolvalue", where the value is in tao.
"""
return f"{self.unit}{float(self.tao):,.9f}"
[docs]
def __rich__(self):
return "[green]{}[/green][green]{}[/green][green].[/green][dim green]{}[/dim green]".format(
self.unit,
format(float(self.tao), "f").split(".")[0],
format(float(self.tao), "f").split(".")[1],
)
[docs]
def __str_rao__(self):
return f"{self.rao_unit}{int(self.rao)}"
[docs]
def __rich_rao__(self):
return f"[green]{self.rao_unit}{int(self.rao)}[/green]"
[docs]
def __repr__(self):
return self.__str__()
[docs]
def __eq__(self, other: Union[int, float, "Balance"]):
if other is None:
return False
if hasattr(other, "rao"):
return self.rao == other.rao
else:
try:
# Attempt to cast to int from rao
other_rao = int(other)
return self.rao == other_rao
except (TypeError, ValueError):
raise NotImplementedError("Unsupported type")
[docs]
def __ne__(self, other: Union[int, float, "Balance"]):
return not self == other
[docs]
def __gt__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return self.rao > other.rao
else:
try:
# Attempt to cast to int from rao
other_rao = int(other)
return self.rao > other_rao
except ValueError:
raise NotImplementedError("Unsupported type")
[docs]
def __lt__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return self.rao < other.rao
else:
try:
# Attempt to cast to int from rao
other_rao = int(other)
return self.rao < other_rao
except ValueError:
raise NotImplementedError("Unsupported type")
[docs]
def __le__(self, other: Union[int, float, "Balance"]):
try:
return self < other or self == other
except TypeError:
raise NotImplementedError("Unsupported type")
[docs]
def __ge__(self, other: Union[int, float, "Balance"]):
try:
return self > other or self == other
except TypeError:
raise NotImplementedError("Unsupported type")
[docs]
def __add__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return Balance.from_rao(int(self.rao + other.rao))
else:
try:
# Attempt to cast to int from rao
return Balance.from_rao(int(self.rao + other))
except (ValueError, TypeError):
raise NotImplementedError("Unsupported type")
[docs]
def __radd__(self, other: Union[int, float, "Balance"]):
try:
return self + other
except TypeError:
raise NotImplementedError("Unsupported type")
[docs]
def __sub__(self, other: Union[int, float, "Balance"]):
try:
return self + -other
except TypeError:
raise NotImplementedError("Unsupported type")
[docs]
def __rsub__(self, other: Union[int, float, "Balance"]):
try:
return -self + other
except TypeError:
raise NotImplementedError("Unsupported type")
[docs]
def __mul__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return Balance.from_rao(int(self.rao * other.rao))
else:
try:
# Attempt to cast to int from rao
return Balance.from_rao(int(self.rao * other))
except (ValueError, TypeError):
raise NotImplementedError("Unsupported type")
[docs]
def __rmul__(self, other: Union[int, float, "Balance"]):
return self * other
[docs]
def __truediv__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return Balance.from_rao(int(self.rao / other.rao))
else:
try:
# Attempt to cast to int from rao
return Balance.from_rao(int(self.rao / other))
except (ValueError, TypeError):
raise NotImplementedError("Unsupported type")
[docs]
def __rtruediv__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return Balance.from_rao(int(other.rao / self.rao))
else:
try:
# Attempt to cast to int from rao
return Balance.from_rao(int(other / self.rao))
except (ValueError, TypeError):
raise NotImplementedError("Unsupported type")
[docs]
def __floordiv__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return Balance.from_rao(int(self.tao // other.tao))
else:
try:
# Attempt to cast to int from rao
return Balance.from_rao(int(self.rao // other))
except (ValueError, TypeError):
raise NotImplementedError("Unsupported type")
[docs]
def __rfloordiv__(self, other: Union[int, float, "Balance"]):
if hasattr(other, "rao"):
return Balance.from_rao(int(other.rao // self.rao))
else:
try:
# Attempt to cast to int from rao
return Balance.from_rao(int(other // self.rao))
except (ValueError, TypeError):
raise NotImplementedError("Unsupported type")
[docs]
def __int__(self) -> int:
return self.rao
[docs]
def __float__(self) -> float:
return self.tao
[docs]
def __nonzero__(self) -> bool:
return bool(self.rao)
[docs]
def __neg__(self):
return Balance.from_rao(-self.rao)
[docs]
def __pos__(self):
return Balance.from_rao(self.rao)
[docs]
def __abs__(self):
return Balance.from_rao(abs(self.rao))
[docs]
@staticmethod
def from_float(amount: float):
"""
Given tao (float), return Balance object with rao(int) and tao(float), where rao = int(tao*pow(10,9))
Args:
amount: The amount in tao.
Returns:
A Balance object representing the given amount.
"""
rao = int(amount * pow(10, 9))
return Balance(rao)
[docs]
@staticmethod
def from_tao(amount: float):
"""
Given tao (float), return Balance object with rao(int) and tao(float), where rao = int(tao*pow(10,9))
Args:
amount: The amount in tao.
Returns:
A Balance object representing the given amount.
"""
rao = int(amount * pow(10, 9))
return Balance(rao)
[docs]
@staticmethod
def from_rao(amount: int):
"""
Given rao (int), return Balance object with rao(int) and tao(float), where rao = int(tao*pow(10,9))
Args:
amount: The amount in rao.
Returns:
A Balance object representing the given amount.
"""
return Balance(amount)