Source code for helium_py.currency.balance

"""Balance class for converting between currency types."""
from decimal import Decimal
from typing import Optional, Union

from ..api import OraclePrices
from .exceptions import (
    MixedCurrencyTypeError,
    UnsupportedCurrencyConversionError,
    UnsupportedCurrencyError,
)
from .types import (
    ALL_CURRENCY_TYPES,
    DATA_CREDITS,
    NETWORK_TOKENS,
    TEST_NETWORK_TOKENS,
    US_DOLLARS,
)

DC_TO_USD_MULTIPLIER = Decimal('0.00001')


[docs]class Balance: """Represents a balance in a particular currency.""" currency_type: str balance_in_currency: Decimal
[docs] def __init__(self, balance_in_currency: Union[int, float, Decimal], currency_type: str): """Initialize balance with a currency type and amount.""" if currency_type not in ALL_CURRENCY_TYPES: raise UnsupportedCurrencyError() if not isinstance(balance_in_currency, Decimal): balance_in_currency = Decimal(str(balance_in_currency)) self.balance_in_currency = balance_in_currency self.currency_type = currency_type
def __eq__(self, other): """Compare to see if two balances are equal.""" return self.currency_type == other.currency_type and self.balance_in_currency == other.balance_in_currency
[docs] def to_string(self, max_decimal_places: Optional[int] = None, show_ticker: Optional[bool] = True) -> str: """Convert Balance objects to a string.""" number_string = f'{self.balance_in_currency:,.{max_decimal_places}f}' if max_decimal_places \ else f'{self.balance_in_currency:,}' return ' '.join([number_string, self.currency_type]) if show_ticker else number_string
[docs] def plus(self, balance: 'Balance') -> 'Balance': """Add two Balances of the same type together.""" if self.currency_type != balance.currency_type: raise MixedCurrencyTypeError() return Balance((self.balance_in_currency + balance.balance_in_currency), self.currency_type)
[docs] def minus(self, balance: 'Balance') -> 'Balance': """Subtract two Balances of the same type together.""" if self.currency_type != balance.currency_type: raise MixedCurrencyTypeError() return Balance((self.balance_in_currency - balance.balance_in_currency), self.currency_type)
[docs] def times(self, balance: 'Balance') -> 'Balance': """Multiply two Balances of the same type together.""" if self.currency_type != balance.currency_type: raise MixedCurrencyTypeError() return Balance((self.balance_in_currency * balance.balance_in_currency), self.currency_type)
[docs] def divided_by(self, balance: 'Balance') -> 'Balance': """Divide two Balances of the same type together.""" if self.currency_type != balance.currency_type: raise MixedCurrencyTypeError() return Balance((self.balance_in_currency / balance.balance_in_currency), self.currency_type)
[docs] def to_usd(self, oracle_price: Optional['Balance'] = None) -> 'Balance': """Convert a balance to US_DOLLARS.""" if self.currency_type == US_DOLLARS: return self if oracle_price is None: oracle_price = Balance(OraclePrices().get_current()['price'], US_DOLLARS) if self.currency_type == DATA_CREDITS: return Balance(self.balance_in_currency * DC_TO_USD_MULTIPLIER, US_DOLLARS) if self.currency_type == NETWORK_TOKENS: return Balance(self.balance_in_currency * oracle_price.balance_in_currency, US_DOLLARS) if self.currency_type == TEST_NETWORK_TOKENS: return Balance(self.balance_in_currency * oracle_price.balance_in_currency, US_DOLLARS) raise UnsupportedCurrencyConversionError()
[docs] def to_network_tokens(self, oracle_price: Optional['Balance'] = None) -> 'Balance': """Convert a balance to NETWORK_TOKENS.""" if self.currency_type == NETWORK_TOKENS: return self if oracle_price is None: oracle_price = Balance(OraclePrices().get_current()['price'], US_DOLLARS) return Balance(self.to_usd(oracle_price).balance_in_currency / oracle_price.balance_in_currency, NETWORK_TOKENS)
[docs] def to_test_network_tokens(self, oracle_price: Optional['Balance'] = None) -> 'Balance': """Convert a balance to TEST_NETWORK_TOKENS.""" if self.currency_type == TEST_NETWORK_TOKENS: return self if oracle_price is None: # TODO: This should go to testnet oracle_price = Balance(OraclePrices().get_current()['price'], US_DOLLARS) return Balance(self.to_usd( oracle_price).balance_in_currency / oracle_price.balance_in_currency, TEST_NETWORK_TOKENS)
[docs] def to_data_credits(self, oracle_price: Optional['Balance'] = None) -> 'Balance': """Convert a balance to DATA_CREDITS.""" if self.currency_type == DATA_CREDITS: return self if self.currency_type == US_DOLLARS: return Balance(self.balance_in_currency / DC_TO_USD_MULTIPLIER, DATA_CREDITS) if oracle_price is None: oracle_price = Balance(OraclePrices().get_current()['price'], US_DOLLARS) if self.currency_type == NETWORK_TOKENS: return self.to_usd(oracle_price).to_data_credits(oracle_price) raise UnsupportedCurrencyConversionError()