import BigNumber from 'bignumber.js' ; import CurrencyType , { AnyCurrencyType } from './CurrencyType' ; import { NetworkTokens , USDollars , DataCredits , BaseCurrencyType , TestNetworkTokens , } from './currency_types' ; import { MixedCurrencyTypeError , OraclePriceRequiredError , UnsupportedCurrencyConversionError , } from './Errors' ; const FORMAT = { decimalSeparator : '.' , groupSeparator : ',' , groupSize : 3 , secondaryGroupSize : 0 , fractionGroupSeparator : ' ' , fractionGroupSize : 0 , } ; BigNumber . config ( { EXPONENTIAL_AT : [ - 10 , 20 ] , FORMAT , } ) ; type StringFormatOptions = { decimalSeparator ? : string ; groupSeparator ? : string ; showTicker ? : boolean ; } ; const DC_TO_USD_MULTIPLIER = 0.00001 ; export default class Balance < T extends BaseCurrencyType > { public type : T ; public integerBalance : number ; public floatBalance : number ; public bigBalance : BigNumber ; public bigInteger : BigNumber ; constructor ( integerBalance , type ) { this . type = type ; this . integerBalance = integerBalance || 0 ; this . bigInteger = new BigNumber ( this . integerBalance ) ; this . bigBalance = this . bigInteger . times ( type . coefficient ) ; this . floatBalance = this . bigBalance . toNumber ( ) ; } static fromFloat ( float , currencyType ) { const bigFloat = new BigNumber ( float ) ; const integerBalance = bigFloat . dividedBy ( currencyType . coefficient ) . toNumber ( ) ; return new Balance ( integerBalance , currencyType ) ; } toString ( maxDecimalPlaces ? , options ? ) { const decimalSeparator = options ?. decimalSeparator || '.' ; const groupSeparator = options ?. groupSeparator || ',' ; const showTicker = options ?. showTicker === undefined ? true : options . showTicker ; let numberString = maxDecimalPlaces !== undefined && maxDecimalPlaces !== null ? this . bigBalance . toFormat ( maxDecimalPlaces , { decimalSeparator , groupSeparator , groupSize : 3 } ) : this . bigBalance . toFormat ( { decimalSeparator , groupSeparator , groupSize : 3 } ) ; if ( parseInt ( numberString . split ( decimalSeparator ) [ 1 ] , 10 ) === 0 ) { [ numberString ] = numberString . split ( decimalSeparator ) ; } if ( numberString === '0' ) { numberString = this . bigBalance . toFormat ( { decimalSeparator , groupSeparator } ) ; } return showTicker ? [ numberString , this . type . ticker ] . join ( ' ' ) : numberString ; } plus ( balance ) { if ( this . type . ticker !== balance . type . ticker ) throw MixedCurrencyTypeError ; return new Balance ( this . bigInteger . plus ( balance . bigInteger ) . toNumber ( ) , this . type ) ; } minus ( balance ) { if ( this . type . ticker !== balance . type . ticker ) throw MixedCurrencyTypeError ; return new Balance ( this . bigInteger . minus ( balance . bigInteger ) . toNumber ( ) , this . type ) ; } times ( n ) { return new Balance ( this . bigInteger . times ( n ) . toNumber ( ) , this . type ) ; } dividedBy ( n ) { return new Balance ( this . bigInteger . dividedBy ( n ) . toNumber ( ) , this . type ) ; } toNetworkTokens ( oraclePrice ? ) { if ( this . type instanceof NetworkTokens ) return this ; if ( ! oraclePrice ) throw OraclePriceRequiredError ; return new Balance ( this . toUsd ( ) . bigBalance . dividedBy ( oraclePrice . bigBalance ) . dividedBy ( CurrencyType . networkToken . coefficient ) . toNumber ( ) , CurrencyType . networkToken ) ; } toTestNetworkTokens ( oraclePrice ? ) { if ( this . type instanceof TestNetworkTokens ) return this ; if ( ! oraclePrice ) throw OraclePriceRequiredError ; return new Balance ( this . toUsd ( ) . bigBalance . dividedBy ( oraclePrice . bigBalance ) . dividedBy ( CurrencyType . testNetworkToken . coefficient ) . toNumber ( ) , CurrencyType . testNetworkToken ) ; } toUsd ( oraclePrice ? ) { if ( this . type instanceof USDollars ) return this ; if ( this . type instanceof DataCredits ) { return new Balance ( this . bigBalance . times ( DC_TO_USD_MULTIPLIER ) . dividedBy ( CurrencyType . usd . coefficient ) . toNumber ( ) , CurrencyType . usd ) ; } if ( this . type instanceof NetworkTokens ) { if ( ! oraclePrice ) throw OraclePriceRequiredError ; return new Balance ( this . bigBalance . times ( oraclePrice . bigBalance ) . dividedBy ( CurrencyType . usd . coefficient ) . toNumber ( ) , CurrencyType . usd ) ; } throw UnsupportedCurrencyConversionError ; } toDataCredits ( oraclePrice ? ) { if ( this . type instanceof DataCredits ) return this ; if ( this . type instanceof USDollars ) { return new Balance ( this . bigBalance . dividedBy ( DC_TO_USD_MULTIPLIER ) . toNumber ( ) , CurrencyType . dataCredit ) ; } if ( this . type instanceof NetworkTokens ) { if ( ! oraclePrice ) throw OraclePriceRequiredError ; return this . toUsd ( oraclePrice ) . toDataCredits ( ) ; } throw UnsupportedCurrencyConversionError ; } }