package io.bitsquare.trade.offer; import io.bitsquare.common.util.MathUtils; import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.payment.PaymentMethod; import org.bitcoinj.core.Coin; import org.bitcoinj.utils.ExchangeRate; import org.bitcoinj.utils.Fiat; import org.bitcoinj.utils.MonetaryFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.text.DecimalFormat; import java.util.Date; public class OfferForJson { private static final Logger log = LoggerFactory.getLogger(OfferForJson.class); public final Offer.Direction direction; public final String currencyCode; public final long minAmount; public final long amount; public final long price; public final long date; public final boolean useMarketBasedPrice; public final double marketPriceMargin; public final String paymentMethod; public final String id; public final String offerFeeTxID; // primaryMarket fields are based on industry standard where primaryMarket is always in the focus (in the app BTC is always in the focus - will be changed in a larger refactoring once) public String currencyPair; public Offer.Direction primaryMarketDirection; public String priceDisplayString; public String primaryMarketAmountDisplayString; public String primaryMarketMinAmountDisplayString; public String primaryMarketVolumeDisplayString; public String primaryMarketMinVolumeDisplayString; public long primaryMarketPrice; public long primaryMarketAmount; public long primaryMarketMinAmount; public long primaryMarketVolume; public long primaryMarketMinVolume; public OfferForJson(Offer.Direction direction, String currencyCode, Coin minAmount, Coin amount, Fiat price, Date date, String id, boolean useMarketBasedPrice, double marketPriceMargin, PaymentMethod paymentMethod, String offerFeeTxID) { this.direction = direction; this.currencyCode = currencyCode; this.minAmount = minAmount.value; this.amount = amount.value; this.price = price.value; this.date = date.getTime(); this.id = id; this.useMarketBasedPrice = useMarketBasedPrice; this.marketPriceMargin = marketPriceMargin; this.paymentMethod = paymentMethod.getId(); this.offerFeeTxID = offerFeeTxID; setDisplayStrings(); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { try { in.defaultReadObject(); setDisplayStrings(); } catch (Throwable t) { log.warn("Cannot be deserialized." + t.getMessage()); } } private void setDisplayStrings() { try { MonetaryFormat fiatFormat = MonetaryFormat.FIAT.repeatOptionalDecimals(0, 0); MonetaryFormat coinFormat = MonetaryFormat.BTC.minDecimals(2).repeatOptionalDecimals(1, 6); final Fiat priceAsFiat = getPriceAsFiat(); if (CurrencyUtil.isCryptoCurrency(currencyCode)) { primaryMarketDirection = direction == Offer.Direction.BUY ? Offer.Direction.SELL : Offer.Direction.BUY; currencyPair = currencyCode + "/" + "BTC"; DecimalFormat decimalFormat = new DecimalFormat("#.#"); decimalFormat.setMaximumFractionDigits(8); final double value = priceAsFiat.value != 0 ? 10000D / priceAsFiat.value : 0; priceDisplayString = decimalFormat.format(MathUtils.roundDouble(value, 8)).replace(",", "."); primaryMarketMinAmountDisplayString = fiatFormat.noCode().format(getMinVolumeAsFiat()).toString(); primaryMarketAmountDisplayString = fiatFormat.noCode().format(getVolumeAsFiat()).toString(); primaryMarketMinVolumeDisplayString = coinFormat.noCode().format(getMinAmountAsCoin()).toString(); primaryMarketVolumeDisplayString = coinFormat.noCode().format(getAmountAsCoin()).toString(); primaryMarketPrice = MathUtils.roundDoubleToLong(MathUtils.scaleUpByPowerOf10(value, 8)); primaryMarketMinAmount = (long) MathUtils.scaleUpByPowerOf10(getMinVolumeAsFiat().longValue(), 4); primaryMarketAmount = (long) MathUtils.scaleUpByPowerOf10(getVolumeAsFiat().longValue(), 4); primaryMarketMinVolume = getMinAmountAsCoin().longValue(); primaryMarketVolume = getAmountAsCoin().longValue(); } else { primaryMarketDirection = direction; currencyPair = "BTC/" + currencyCode; priceDisplayString = fiatFormat.noCode().format(priceAsFiat).toString(); primaryMarketMinAmountDisplayString = coinFormat.noCode().format(getMinAmountAsCoin()).toString(); primaryMarketAmountDisplayString = coinFormat.noCode().format(getAmountAsCoin()).toString(); primaryMarketMinVolumeDisplayString = fiatFormat.noCode().format(getMinVolumeAsFiat()).toString(); primaryMarketVolumeDisplayString = fiatFormat.noCode().format(getVolumeAsFiat()).toString(); primaryMarketPrice = (long) MathUtils.scaleUpByPowerOf10(priceAsFiat.longValue(), 4); primaryMarketMinAmount = getMinAmountAsCoin().longValue(); primaryMarketAmount = getAmountAsCoin().longValue(); primaryMarketMinVolume = (long) MathUtils.scaleUpByPowerOf10(getMinVolumeAsFiat().longValue(), 4); primaryMarketVolume = (long) MathUtils.scaleUpByPowerOf10(getVolumeAsFiat().longValue(), 4); } } catch (Throwable t) { log.error("Error at setDisplayStrings: " + t.getMessage()); } } private Fiat getPriceAsFiat() { return Fiat.valueOf(currencyCode, price); } private Coin getAmountAsCoin() { return Coin.valueOf(amount); } private Coin getMinAmountAsCoin() { return Coin.valueOf(minAmount); } private Fiat getVolumeAsFiat() { return new ExchangeRate(getPriceAsFiat()).coinToFiat(getAmountAsCoin()); } private Fiat getMinVolumeAsFiat() { return new ExchangeRate(getPriceAsFiat()).coinToFiat(getMinAmountAsCoin()); } }