changed formatter to use CoinFormat instead of BtcFormat

This commit is contained in:
Manfred Karrer 2014-08-29 23:15:14 +02:00
parent 096f4c01e7
commit c87a9a3acc
6 changed files with 139 additions and 119 deletions

View file

@ -52,7 +52,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkArgument;
import static io.bitsquare.gui.util.BSFormatter.reduceto4Dezimals;
import static io.bitsquare.gui.util.BSFormatter.reduceTo4Decimals;
/**
* Domain for that UI element.
@ -132,16 +132,20 @@ class CreateOfferModel extends UIModel {
super.activate();
// might be changed after screen change
if (settings != null) {
collateralAsLong.set(settings.getCollateral());
acceptedCountries.setAll(settings.getAcceptedCountries());
acceptedLanguages.setAll(settings.getAcceptedLanguageLocales());
}
if (user != null) {
BankAccount bankAccount = user.getCurrentBankAccount();
if (bankAccount != null) {
bankAccountType.set(bankAccount.getBankAccountType().toString());
bankAccountCurrency.set(bankAccount.getCurrency().getCurrencyCode());
bankAccountCounty.set(bankAccount.getCountry().getName());
}
acceptedCountries.setAll(settings.getAcceptedCountries());
acceptedLanguages.setAll(settings.getAcceptedLanguageLocales());
}
}
@Override
@ -178,34 +182,54 @@ class CreateOfferModel extends UIModel {
}
void calculateVolume() {
if (priceAsFiat.get() != null && amountAsCoin.get() != null /*&& !amountAsCoin.get().isZero()*/) {
try {
if (priceAsFiat.get() != null && amountAsCoin.get() != null && !amountAsCoin.get().isZero() && !priceAsFiat
.get().isZero()) {
volumeAsFiat.set(new ExchangeRate(priceAsFiat.get()).coinToFiat(amountAsCoin.get()));
}
} catch (Throwable t) {
// Should be never reached
log.error(t.toString());
}
}
void calculateAmount() {
if (volumeAsFiat.get() != null && priceAsFiat.get() != null/* && !volumeAsFiat.get().isZero() && !priceAsFiat
.get().isZero()*/) {
try {
if (volumeAsFiat.get() != null && priceAsFiat.get() != null && !volumeAsFiat.get().isZero() && !priceAsFiat
.get().isZero()) {
amountAsCoin.set(new ExchangeRate(priceAsFiat.get()).fiatToCoin(volumeAsFiat.get()));
// If we got a btc value with more then 4 decimals we convert it to max 4 decimals
amountAsCoin.set(reduceto4Dezimals(amountAsCoin.get()));
amountAsCoin.set(reduceTo4Decimals(amountAsCoin.get()));
calculateTotalToPay();
calculateCollateral();
}
} catch (Throwable t) {
// Should be never reached
log.error(t.toString());
}
}
void calculateTotalToPay() {
calculateCollateral();
try {
if (collateralAsCoin.get() != null)
totalToPayAsCoin.set(collateralAsCoin.get().add(totalFeesAsCoin.get()));
} catch (Throwable t) {
// Should be never reached
log.error(t.toString());
}
}
void calculateCollateral() {
try {
if (amountAsCoin.get() != null)
collateralAsCoin.set(amountAsCoin.get().multiply(collateralAsLong.get()).divide(1000));
collateralAsCoin.set(amountAsCoin.get().multiply(collateralAsLong.get()).divide(1000L));
} catch (Throwable t) {
// The multiply might lead to too large numbers, we don't handle it but it should not break the app
log.error(t.toString());
}
}

View file

@ -282,7 +282,7 @@ class CreateOfferPM extends PresentationModel<CreateOfferModel> {
// We do volume/amount calculation during input, so user has immediate feedback
amount.addListener((ov, oldValue, newValue) -> {
if (isBtcInputValid(newValue).isValid) {
setMinAmountToModel();
setAmountToModel();
calculateVolume();
model.calculateTotalToPay();
model.calculateCollateral();

View file

@ -23,7 +23,6 @@ import io.bitsquare.locale.Localisation;
import io.bitsquare.trade.Direction;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.utils.BtcFormat;
import com.google.bitcoin.utils.CoinFormat;
import com.google.bitcoin.utils.Fiat;
@ -55,10 +54,15 @@ public class BSFormatter {
private static Locale locale = Locale.getDefault();
private static boolean useMilliBit;
private static String code = "BTC";
private static int scale = 3;
// format is like: 1,00 or 1,0010 never more then 4 decimals
// Format use 2 min decimal places and 2 more optional: 1.00 or 1.0010
// There are not more then 4 decimals allowed.
// We don't support localized formatting. Format is always using "." as decimal mark and no grouping separator.
// Input of "," as decimal mark (like in german locale) will be replaced with ".".
// Input of a group separator (1,123,45) lead to an validation error.
// Note: BtcFormat was intended to be used, but it lead to many problems (automatic format to mBit,
// no way to remove grouping separator). It seems to be not optimal for user input formatting.
private static CoinFormat coinFormat = CoinFormat.BTC.repeatOptionalDecimals(2, 1);
// format is like: 1,00 never more then 2 decimals
@ -66,11 +70,9 @@ public class BSFormatter {
private static String currencyCode = Currency.getInstance(Locale.getDefault()).getCurrencyCode();
private static BtcFormat btcFormat = getBtcFormat();
static {
//useMilliBitFormat(true);
setLocale(Locale.US);
// setLocale(Locale.US);
}
@ -81,8 +83,7 @@ public class BSFormatter {
public static void useMilliBitFormat(boolean useMilliBit) {
BSFormatter.useMilliBit = useMilliBit;
code = useMilliBit ? "mBTC" : "BTC";
btcFormat = getBtcFormat();
coinFormat = getCoinFormat();
scale = useMilliBit ? 0 : 3;
}
@ -91,11 +92,13 @@ public class BSFormatter {
*/
public static void setLocale(Locale locale) {
BSFormatter.locale = locale;
btcFormat = getBtcFormat();
}
private static BtcFormat getBtcFormat() {
return BtcFormat.getInstance(useMilliBit ? BtcFormat.MILLICOIN_SCALE : BtcFormat.COIN_SCALE, locale, 2, 2);
private static CoinFormat getCoinFormat() {
if (useMilliBit)
return CoinFormat.MBTC.repeatOptionalDecimals(2, 1);
else
return CoinFormat.BTC.repeatOptionalDecimals(2, 1);
}
public static void setFiatCurrencyCode(String currencyCode) {
@ -109,7 +112,7 @@ public class BSFormatter {
public static String formatCoin(Coin coin) {
try {
return btcFormat.format(coin);
return coinFormat.noCode().format(coin).toString();
} catch (Throwable t) {
log.warn("Exception at formatBtc: " + t.toString());
return "";
@ -118,18 +121,19 @@ public class BSFormatter {
public static String formatCoinWithCode(Coin coin) {
try {
// we don't use the code feature from btcFormat as it does automatic switching between mBTC and BTC and
// we don't use the code feature from coinFormat as it does automatic switching between mBTC and BTC and
// pre and post fixing
return btcFormat.format(coin) + " " + code;
return coinFormat.postfixCode().format(coin).toString();
} catch (Throwable t) {
log.warn("Exception at formatBtcWithCode: " + t.toString());
return "";
}
}
public static Coin parseToCoin(String input) {
try {
return btcFormat.parse(input);
return coinFormat.parse(cleanedInput(input));
} catch (Throwable t) {
log.warn("Exception at parseToBtc: " + t.toString());
return Coin.ZERO;
@ -146,7 +150,7 @@ public class BSFormatter {
*/
public static Coin parseToCoinWith4Decimals(String input) {
try {
return Coin.valueOf(new BigDecimal(parseToCoin(input).value).setScale(-scale - 1,
return Coin.valueOf(new BigDecimal(parseToCoin(cleanedInput(input)).value).setScale(-scale - 1,
BigDecimal.ROUND_HALF_UP).setScale(scale + 1).toBigInteger().longValue());
} catch (Throwable t) {
log.warn("Exception at parseToCoinWith4Decimals: " + t.toString());
@ -164,7 +168,7 @@ public class BSFormatter {
* @param coin The coin which should be transformed
* @return The transformed coin
*/
public static Coin reduceto4Dezimals(Coin coin) {
public static Coin reduceTo4Decimals(Coin coin) {
return parseToCoin(formatCoin(coin));
}
@ -193,9 +197,7 @@ public class BSFormatter {
public static Fiat parseToFiat(String input) {
try {
input = input.replace(",", ".");
Double.parseDouble(input); // test if valid double
return Fiat.parseFiat(currencyCode, input);
return Fiat.parseFiat(currencyCode, cleanedInput(input));
} catch (Exception e) {
return Fiat.valueOf(currencyCode, 0);
}
@ -211,9 +213,7 @@ public class BSFormatter {
*/
public static Fiat parseToFiatWith2Decimals(String input) {
try {
input = input.replace(",", ".");
Double.parseDouble(input); // test if valid double
return parseToFiat(new BigDecimal(input).setScale(2, BigDecimal.ROUND_HALF_UP).toString());
return parseToFiat(new BigDecimal(cleanedInput(input)).setScale(2, BigDecimal.ROUND_HALF_UP).toString());
} catch (Throwable t) {
log.warn("Exception at parseCoinTo4Decimals: " + t.toString());
return Fiat.valueOf(currencyCode, 0);
@ -358,4 +358,12 @@ public class BSFormatter {
public static String formatCoinWithCode(Coin coin) {
return coin != null ? coin.toFriendlyString() : "";
}*/
private static String cleanedInput(String input) {
input = input.replace(",", ".");
// don't use String.valueOf(Double.parseDouble(input)) as return value as it gives scientific
// notation (1.0E-6) which screw up coinFormat.parse
Double.parseDouble(input);
return input;
}
}

View file

@ -22,6 +22,7 @@ import io.bitsquare.gui.trade.createoffer.CreateOfferPMTest;
import io.bitsquare.gui.util.BSFormatterTest;
import io.bitsquare.gui.util.BitSquareConverterTest;
import io.bitsquare.gui.util.BitSquareNumberValidatorTest;
import io.bitsquare.gui.util.BtcValidatorTest;
import io.bitsquare.gui.util.FiatValidatorTest;
import io.bitsquare.msg.P2PNodeTest;
@ -37,7 +38,8 @@ import org.junit.runners.Suite;
FiatValidatorTest.class,
RestrictionsTest.class,
CreateOfferPMTest.class,
BSFormatterTest.class
BSFormatterTest.class,
BtcValidatorTest.class
})
public class BitSquareTestSuite {

View file

@ -58,38 +58,38 @@ public class CreateOfferPMTest {
presenter.price.set("500");
presenter.amount.set("1");
assertEquals("500.00", presenter.volume.get());
assertEquals(Coin.COIN, model.amountAsCoin);
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.priceAsFiat);
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.volumeAsFiat);
assertEquals(Coin.COIN, model.amountAsCoin.get());
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.priceAsFiat.get());
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.volumeAsFiat.get());
assertEquals(Coin.parseCoin("0.1011"), model.totalToPayAsCoin.get());
presenter.price.set("500");
presenter.volume.set("500");
assertEquals("1.00", presenter.amount.get());
assertEquals(Coin.COIN, model.amountAsCoin);
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.priceAsFiat);
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.volumeAsFiat);
assertEquals(Coin.COIN, model.amountAsCoin.get());
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.priceAsFiat.get());
assertEquals(Fiat.valueOf("USD", 500 * 10000), model.volumeAsFiat.get());
presenter.price.set("300");
presenter.volume.set("1000");
assertEquals("3.3333", presenter.amount.get());
assertEquals(Coin.parseCoin("3.3333"), model.amountAsCoin);
assertEquals(Fiat.valueOf("USD", 300 * 10000), model.priceAsFiat);
assertEquals(Fiat.valueOf("USD", 9999900), model.volumeAsFiat);
assertEquals(Coin.parseCoin("3.3333"), model.amountAsCoin.get());
assertEquals(Fiat.valueOf("USD", 300 * 10000), model.priceAsFiat.get());
assertEquals(Fiat.valueOf("USD", 9999900), model.volumeAsFiat.get());
presenter.price.set("300");
presenter.amount.set("3.3333");
assertEquals("999.99", presenter.volume.get());
assertEquals(Coin.parseCoin("3.3333"), model.amountAsCoin);
assertEquals(Fiat.valueOf("USD", 300 * 10000), model.priceAsFiat);
assertEquals(Fiat.valueOf("USD", 9999900), model.volumeAsFiat);
assertEquals(Coin.parseCoin("3.3333"), model.amountAsCoin.get());
assertEquals(Fiat.valueOf("USD", 300 * 10000), model.priceAsFiat.get());
assertEquals(Fiat.valueOf("USD", 9999900), model.volumeAsFiat.get());
presenter.price.set("300");
presenter.amount.set("3.33333333");
assertEquals("999.99", presenter.volume.get());
assertEquals(Coin.parseCoin("3.3333"), model.amountAsCoin);
assertEquals(Fiat.valueOf("USD", 300 * 10000), model.priceAsFiat);
assertEquals(Fiat.valueOf("USD", 9999900), model.volumeAsFiat);
assertEquals(Coin.parseCoin("3.3333"), model.amountAsCoin.get());
assertEquals(Fiat.valueOf("USD", 300 * 10000), model.priceAsFiat.get());
assertEquals(Fiat.valueOf("USD", 9999900), model.volumeAsFiat.get());
model.collateralAsLong.set(100);

View file

@ -35,29 +35,20 @@ public class BSFormatterTest {
@Test
public void testParseToBtc() {
useMilliBitFormat(false);
setLocale(Locale.GERMAN);
assertEquals(Coin.ZERO, parseToCoin("0"));
assertEquals(Coin.COIN, parseToCoin("1"));
assertEquals(Coin.SATOSHI, parseToCoin("0,00000001"));
assertEquals(Coin.parseCoin("-1"), parseToCoin("-1"));
assertEquals(Coin.parseCoin("1.1"), parseToCoin("1,1"));
assertEquals(Coin.parseCoin("11"), parseToCoin("1.1"));
assertEquals(Coin.parseCoin("1123.45"), parseToCoin("1.123,45"));
assertEquals(Coin.parseCoin("1.123"), parseToCoin("1,123.45"));
assertEquals(Coin.parseCoin("1.1"), parseToCoin("1.1"));
assertEquals(Coin.parseCoin("0"), parseToCoin("1.123,45"));
assertEquals(Coin.parseCoin("0"), parseToCoin("1,123.45"));
assertEquals(Coin.parseCoin("1.1234"), parseToCoinWith4Decimals("1,12342"));
assertEquals(Coin.parseCoin("1.1235"), parseToCoinWith4Decimals("1,12345"));
assertEquals(Coin.parseCoin("1.1230"), parseToCoinWith4Decimals("1,123"));
// change locale
setLocale(Locale.US);
assertEquals(Coin.parseCoin("1.1"), parseToCoin("1.1"));
assertEquals(Coin.parseCoin("11"), parseToCoin("1,1"));
assertEquals(Coin.parseCoin("1.123"), parseToCoin("1.123,45"));
assertEquals(Coin.parseCoin("1123.45"), parseToCoin("1,123.45"));
// change to mBTC
useMilliBitFormat(true);
assertEquals(Coin.parseCoin("1"), parseToCoin("1000"));
@ -65,7 +56,7 @@ public class BSFormatterTest {
assertEquals(Coin.parseCoin("0.1234"), parseToCoin("123.4"));
assertEquals(Coin.parseCoin("0.12345"), parseToCoin("123.45"));
assertEquals(Coin.parseCoin("0.123456"), parseToCoin("123.456"));
assertEquals(Coin.parseCoin("123.4567"), parseToCoin("123,456.7"));
assertEquals(Coin.parseCoin("0"), parseToCoin("123,456.7"));
assertEquals(Coin.parseCoin("0.001123"), parseToCoinWith4Decimals("1.123"));
assertEquals(Coin.parseCoin("0.0011234"), parseToCoinWith4Decimals("1.1234"));
@ -76,25 +67,23 @@ public class BSFormatterTest {
@Test
public void testFormatCoin() {
useMilliBitFormat(false);
setLocale(Locale.GERMAN);
assertEquals("1,00", formatCoin(Coin.COIN));
assertEquals("1,0120", formatCoin(Coin.parseCoin("1.012")));
assertEquals("1.012,30", formatCoin(Coin.parseCoin("1012.3")));
assertEquals("1,0120", formatCoin(Coin.parseCoin("1.01200")));
assertEquals("1,0123", formatCoin(Coin.parseCoin("1.01234")));
assertEquals("1,2345", formatCoin(Coin.parseCoin("1.2345")));
assertEquals("1,2346", formatCoin(Coin.parseCoin("1.23456")));
assertEquals("1,2346", formatCoin(Coin.parseCoin("1.234567")));
assertEquals("1,2345", formatCoin(Coin.parseCoin("1.23448")));
setLocale(Locale.US);
assertEquals("1.00", formatCoin(Coin.COIN));
assertEquals("1,012.30", formatCoin(Coin.parseCoin("1012.3")));
assertEquals("1.0120", formatCoin(Coin.parseCoin("1.012")));
assertEquals("1012.30", formatCoin(Coin.parseCoin("1012.3")));
assertEquals("1.0120", formatCoin(Coin.parseCoin("1.01200")));
assertEquals("1.0123", formatCoin(Coin.parseCoin("1.01234")));
assertEquals("1.2345", formatCoin(Coin.parseCoin("1.2345")));
assertEquals("1.2346", formatCoin(Coin.parseCoin("1.23456")));
assertEquals("1.2346", formatCoin(Coin.parseCoin("1.234567")));
assertEquals("1.2345", formatCoin(Coin.parseCoin("1.23448")));
assertEquals("1.00", formatCoin(Coin.COIN));
assertEquals("1012.30", formatCoin(Coin.parseCoin("1012.3")));
// change to mBTC
useMilliBitFormat(true);
assertEquals("1,000.00", formatCoin(Coin.COIN));
assertEquals("1000.00", formatCoin(Coin.COIN));
assertEquals("1.00", formatCoin(Coin.MILLICOIN));
assertEquals("0.0010", formatCoin(Coin.MICROCOIN));
}
@ -102,26 +91,24 @@ public class BSFormatterTest {
@Test
public void testFormatCoinWithCode() {
useMilliBitFormat(false);
setLocale(Locale.GERMAN);
assertEquals("1,00 BTC", formatCoinWithCode(Coin.COIN));
assertEquals("1,01 BTC", formatCoinWithCode(Coin.parseCoin("1.01")));
assertEquals("1,0120 BTC", formatCoinWithCode(Coin.parseCoin("1.012")));
assertEquals("1.012,30 BTC", formatCoinWithCode(Coin.parseCoin("1012.3")));
assertEquals("1,0120 BTC", formatCoinWithCode(Coin.parseCoin("1.01200")));
assertEquals("1,0123 BTC", formatCoinWithCode(Coin.parseCoin("1.01234")));
assertEquals("1,2345 BTC", formatCoinWithCode(Coin.parseCoin("1.2345")));
assertEquals("1,2346 BTC", formatCoinWithCode(Coin.parseCoin("1.23456")));
assertEquals("1,2346 BTC", formatCoinWithCode(Coin.parseCoin("1.234567")));
assertEquals("1,2345 BTC", formatCoinWithCode(Coin.parseCoin("1.23448")));
setLocale(Locale.US);
assertEquals("1.00 BTC", formatCoinWithCode(Coin.COIN));
assertEquals("1,012.30 BTC", formatCoinWithCode(Coin.parseCoin("1012.3")));
assertEquals("1.01 BTC", formatCoinWithCode(Coin.parseCoin("1.01")));
assertEquals("1.0120 BTC", formatCoinWithCode(Coin.parseCoin("1.012")));
assertEquals("1012.30 BTC", formatCoinWithCode(Coin.parseCoin("1012.3")));
assertEquals("1.0120 BTC", formatCoinWithCode(Coin.parseCoin("1.01200")));
assertEquals("1.0123 BTC", formatCoinWithCode(Coin.parseCoin("1.01234")));
assertEquals("1.2345 BTC", formatCoinWithCode(Coin.parseCoin("1.2345")));
assertEquals("1.2346 BTC", formatCoinWithCode(Coin.parseCoin("1.23456")));
assertEquals("1.2346 BTC", formatCoinWithCode(Coin.parseCoin("1.234567")));
assertEquals("1.2345 BTC", formatCoinWithCode(Coin.parseCoin("1.23448")));
assertEquals("1.00 BTC", formatCoinWithCode(Coin.COIN));
assertEquals("1012.30 BTC", formatCoinWithCode(Coin.parseCoin("1012.3")));
// change to mBTC
useMilliBitFormat(true);
assertEquals("1,000.00 mBTC", formatCoinWithCode(Coin.COIN));
assertEquals("1000.00 mBTC", formatCoinWithCode(Coin.COIN));
assertEquals("1.00 mBTC", formatCoinWithCode(Coin.MILLICOIN));
assertEquals("0.0010 mBTC", formatCoinWithCode(Coin.MICROCOIN));
}
@ -130,14 +117,13 @@ public class BSFormatterTest {
@Test
public void testParseToBtcWith4Decimals() {
useMilliBitFormat(false);
setLocale(Locale.GERMAN);
assertEquals(Coin.parseCoin("0"), parseToCoinWith4Decimals("0"));
assertEquals(Coin.parseCoin("0"), parseToCoinWith4Decimals(null));
assertEquals(Coin.parseCoin("0"), parseToCoinWith4Decimals("s"));
assertEquals(Coin.parseCoin("0.0012"), parseToCoinWith4Decimals("0,00123"));
assertEquals(Coin.parseCoin("0.0013"), parseToCoinWith4Decimals("0,00125"));
}
/*
@Test
public void testHasBtcValidDecimals() {
useMilliBitFormat(false);
@ -157,12 +143,12 @@ public class BSFormatterTest {
public void testParseToFiatWith2Decimals() {
useMilliBitFormat(false);
setLocale(Locale.GERMAN);
assertEquals("0", parseToFiatWith2Decimals("0"));
assertEquals("0", parseToFiatWith2Decimals(null));
assertEquals("0", parseToFiatWith2Decimals("s"));
assertEquals("0.12", parseToFiatWith2Decimals("0.123"));
assertEquals("0.13", parseToFiatWith2Decimals("0.125"));
assertEquals("0.13", parseToFiatWith2Decimals("0,125"));
assertEquals("0", parseToFiatWith2Decimals("0").toPlainString());
assertEquals("0", parseToFiatWith2Decimals(null).toPlainString());
assertEquals("0", parseToFiatWith2Decimals("s").toPlainString());
assertEquals("0.12", parseToFiatWith2Decimals("0.123").toPlainString());
assertEquals("0.13", parseToFiatWith2Decimals("0.125").toPlainString());
assertEquals("0.13", parseToFiatWith2Decimals("0,125").toPlainString());
}
@Test
@ -178,6 +164,6 @@ public class BSFormatterTest {
assertFalse(hasFiatValidDecimals("20000000.0123"));
assertFalse(hasFiatValidDecimals("0.012"));
assertFalse(hasFiatValidDecimals("0.01222312312312313"));
}*/
}
}