public static ExchangeRate getExchangeRate(@Nonnull final Cursor cursor) { final String codeId = getCurrencyCodeId(cursor); final CoinType type = CoinID.typeFromSymbol(cursor.getString(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_RATE_COIN_CODE))); final Value rateCoin = Value.valueOf(type, cursor.getLong(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_RATE_COIN))); final String fiatCode = cursor.getString(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_RATE_FIAT_CODE)); final Value rateFiat = FiatValue.valueOf(fiatCode, cursor.getLong(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_RATE_FIAT))); final String source = cursor.getString(cursor.getColumnIndexOrThrow(ExchangeRatesProvider.KEY_SOURCE)); ExchangeRateBase rate = new ExchangeRateBase(rateCoin, rateFiat); return new ExchangeRate(rate, codeId, source); }
protected Value convertValue(Value convertingValue) { checkIfValueTypeAvailable(convertingValue.type); Value rateFrom = getFromRateValue(convertingValue.type); Value rateTo = getToRateValue(convertingValue.type); // Use BigDecimal because it's much easier to maintain full precision without overflowing. final BigDecimal converted = BigDecimal.valueOf(convertingValue.value) .multiply(BigDecimal.valueOf(rateTo.value)) .divide(BigDecimal.valueOf(rateFrom.value), RoundingMode.HALF_UP); if (converted.compareTo(BigDecimal.valueOf(Long.MAX_VALUE)) > 0 || converted.compareTo(BigDecimal.valueOf(Long.MIN_VALUE)) < 0) throw new ArithmeticException("Overflow"); return Value.valueOf(rateTo.type, converted.longValue()); }
/** Construct exchange rate. This amount of coin is worth that amount of fiat. */ public ExchangeRateBase(Value value1, Value value2) { this.value1 = checkNonZero(value1); this.value2 = checkNonZero(value2); }
@Test(expected = ArithmeticException.class) public void coinToFiatTooSmall() throws Exception { ExchangeRateBase rate = new ExchangeRateBase(oneBtc, FiatValue.parse("XXX", "1000000000")); rate.convert(Value.parse(BTC, "-1000000")); } }
public void setExchangeRate(ExchangeRate exchangeRate) { if (exchangeRate != null && type != null) { Value localAmount = exchangeRate.rate.convert(type.oneCoin()); setFiatAmount(localAmount); } else { amount.setVisibility(View.GONE); } }
@Test public void canConvert() throws Exception { ExchangeRateBase rate = new ExchangeRateBase(oneBtc, oneNbt); assertTrue(rate.canConvert(BTC, NBT)); assertTrue(rate.canConvert(NBT, BTC)); assertFalse(rate.canConvert(LTC, BTC)); assertFalse(rate.canConvert(LTC, FiatType.get("USD"))); }
@Test public void getOtherType() throws Exception { ExchangeRateBase rate = new ExchangeRateBase(oneBtc, LTC.oneCoin().multiply(100)); assertEquals(BTC, rate.getOtherType(LTC)); assertEquals(LTC, rate.getOtherType(BTC)); }
@Override public boolean canConvert(ValueType type1, ValueType type2) { try { checkIfValueTypeAvailable(type1); checkIfValueTypeAvailable(type2); return true; } catch (IllegalArgumentException ignored) { return false; } }
@Override public Value convert(Value convertingValue) { return convertValue(convertingValue); }
@Test(expected = ArithmeticException.class) public void coinToFiatTooLarge() throws Exception { ExchangeRateBase rate = new ExchangeRateBase(oneBtc, FiatValue.parse("XXX", "1000000000")); rate.convert(Value.parse(BTC, "1000000")); }
private void calculateNewBalance() { currentBalance = null; for (WalletAccount w : wallet.getAllAccounts()) { ExchangeRate rate = exchangeRates.get(w.getCoinType().getSymbol()); if (rate == null) { log.info("Missing exchange rate for {}, skipping...", w.getCoinType().getName()); continue; } if (currentBalance != null) { currentBalance = currentBalance.add(rate.rate.convert(w.getBalance())); } else { currentBalance = rate.rate.convert(w.getBalance()); } } }
@Override public ValueType getOtherType(ValueType type) { checkIfValueTypeAvailable(type); if (value1.type.equals(type)) { return value2.type; } else { return value1.type; } }
@Override public Value convert(CoinType type, Coin coin) { return convertValue(type.value(coin)); }
@Test(expected = IllegalArgumentException.class) public void currencyCodeMismatch() throws Exception { ExchangeRateBase rate = new ExchangeRateBase(oneBtc, FiatValue.parse("EUR", "500")); rate.convert(FiatValue.parse("USD", "1")); }
@Override public void bindView(final View view, final Context context, final Cursor cursor) { final ExchangeRate exchangeRate = ExchangeRatesProvider.getExchangeRate(cursor); final boolean isDefaultCurrency = exchangeRate.currencyCodeId.equals(defaultCurrency); view.setBackgroundResource(isDefaultCurrency ? R.color.bg_list_selected : R.color.bg_list); final TextView currencyCodeView = (TextView) view.findViewById(R.id.exchange_rate_row_currency_code); currencyCodeView.setText(exchangeRate.currencyCodeId); final TextView currencyNameView = (TextView) view.findViewById(R.id.exchange_rate_row_currency_name); String currencyName = WalletUtils.getCurrencyName(exchangeRate.currencyCodeId); if (currencyName != null) { currencyNameView.setText(currencyName); currencyNameView.setVisibility(View.VISIBLE); } else { currencyNameView.setText(null); currencyNameView.setVisibility(View.INVISIBLE); } final Amount rateAmountUnitView = (Amount) view.findViewById(R.id.exchange_rate_row_rate_unit); rateAmountUnitView.setAmount(GenericUtils.formatCoinValue(type, rateBase, true)); rateAmountUnitView.setSymbol(type.getSymbol()); final Amount rateAmountView = (Amount) view.findViewById(R.id.exchange_rate_row_rate); Value fiatAmount = exchangeRate.rate.convert(type, rateBase); rateAmountView.setAmount(GenericUtils.formatFiatValue(fiatAmount)); rateAmountView.setSymbol(fiatAmount.type.getSymbol()); } }
final Value rateLocal = FiatValue.parse(localSymbol, rateStr); ExchangeRateBase rate = new ExchangeRateBase(rateCoin, rateLocal); rates.put(toSymbol, new ExchangeRate(rate, toSymbol, OPENWALLET_SOURCE)); } catch (final Exception x) {
public ExchangeRateBase(ValueType type1, ValueType type2, String rateString) { // Make the rate having maximum of RATE_SCALE decimal places BigDecimal rate = new BigDecimal(rateString) .setScale(RATE_SCALE, RoundingMode.HALF_UP).stripTrailingZeros(); checkState(rate.signum() >= 0); // rate cannot be negative // Check if the rate has too many decimal places or scale() for the type2 to handle. if (rate.scale() > type2.getUnitExponent()) { // If we have too many decimal places, multiply everything by a factor so that the rate // can fit in a type2 value. For example if the rate is 0.123456789 but a type2 can only // handle 4 places, then final result will be value1 = 100000 and value2 = 12345.6789 BigDecimal rateFactor = BigDecimal.TEN.pow(rate.scale() - type2.getUnitExponent()); value1 = type1.oneCoin().multiply(rateFactor.longValue()); value2 = Value.parse(type2, rate.multiply(rateFactor)); } else { value1 = type1.oneCoin(); value2 = Value.parse(type2, rate); } checkNonZero(value1); checkNonZero(value2); }
@Test public void cryptoToCryptoRateParseConstructor() throws Exception { // 1BTC = 100LTC ExchangeRateBase rate = new ExchangeRateBase(BTC, LTC, "100"); assertEquals(LTC, rate.convert(oneBtc).type); assertEquals(BTC, rate.convert(LTC.oneCoin()).type); assertEquals("1", rate.convert(oneBtc.divide(100)).toPlainString()); assertEquals("0.01", rate.convert(LTC.oneCoin()).toPlainString()); }
private void bindView(View row, WalletAccount account) { final ImageView icon = (ImageView) row.findViewById(R.id.account_icon); icon.setImageResource(Constants.COINS_ICONS.get(account.getCoinType())); final TextView rowLabel = (TextView) row.findViewById(R.id.account_description); rowLabel.setText(account.getDescriptionOrCoinName()); final Amount rowValue = (Amount) row.findViewById(R.id.account_balance); rowValue.setAmount(GenericUtils.formatFiatValue(account.getBalance(), 4, 0)); rowValue.setSymbol(account.getCoinType().getSymbol()); ExchangeRatesProvider.ExchangeRate rate = rates.get(account.getCoinType().getSymbol()); final Amount rowBalanceRateValue = (Amount) row.findViewById(R.id.account_balance_rate); if (rate != null && account.getCoinType() != null) { Value localAmount = rate.rate.convert(account.getBalance()); GenericUtils.formatCoinValue(localAmount.type, localAmount,true); rowBalanceRateValue.setAmount(GenericUtils.formatFiatValue(localAmount, 2, 0)); rowBalanceRateValue.setSymbol(localAmount.type.getSymbol()); rowBalanceRateValue.setVisibility(View.VISIBLE); } else { rowBalanceRateValue.setVisibility(View.GONE); } final Amount rowRateValue = (Amount) row.findViewById(R.id.exchange_rate_row_rate); if (rate != null && account.getCoinType() != null) { Value localAmount = rate.rate.convert(account.getCoinType().oneCoin()); GenericUtils.formatCoinValue(localAmount.type, localAmount, true); rowRateValue.setAmount(GenericUtils.formatFiatValue(localAmount, 2, 0)); rowRateValue.setSymbol(localAmount.type.getSymbol()); rowRateValue.setVisibility(View.VISIBLE); } else { rowRateValue.setVisibility(View.GONE); } }
@Test(expected = IllegalArgumentException.class) public void zeroExchangeRate() throws Exception { new ExchangeRateBase(oneBtc, LTC.value(0)); }