Skip to content

Commit

Permalink
Merge pull request #3953 from stejbac/fix-bsq-avg-dollar-price
Browse files Browse the repository at this point in the history
Fix incorrect rounding of BSQ dollar price to whole number
  • Loading branch information
ripcurlx authored Feb 11, 2020
2 parents d166e08 + c2b519a commit f400298
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 31 deletions.
55 changes: 30 additions & 25 deletions desktop/src/main/java/bisq/desktop/util/DisplayUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.text.DateFormat;

import java.math.BigDecimal;
import java.math.RoundingMode;

import java.util.Date;
import java.util.Optional;
Expand All @@ -31,8 +32,8 @@

@Slf4j
public class DisplayUtils {
private final static int scale = 3;
private static final MonetaryFormat fiatVolumeFormat = new MonetaryFormat().shift(0).minDecimals(0).repeatOptionalDecimals(0, 0);
private static final int SCALE = 3;
private static final MonetaryFormat FIAT_VOLUME_FORMAT = new MonetaryFormat().shift(0).minDecimals(0).repeatOptionalDecimals(0, 0);

public static String formatDateTime(Date date) {
return FormattingUtils.formatDateTime(date, true);
Expand Down Expand Up @@ -96,7 +97,7 @@ public static String formatVolume(Offer offer, Boolean decimalAligned, int maxNu
}

public static String formatVolume(Volume volume) {
return formatVolume(volume, fiatVolumeFormat, false);
return formatVolume(volume, FIAT_VOLUME_FORMAT, false);
}

private static String formatVolume(Volume volume, MonetaryFormat fiatVolumeFormat, boolean appendCurrencyCode) {
Expand All @@ -112,7 +113,11 @@ private static String formatVolume(Volume volume, MonetaryFormat fiatVolumeForma
}

public static String formatVolumeWithCode(Volume volume) {
return formatVolume(volume, fiatVolumeFormat, true);
return formatVolume(volume, FIAT_VOLUME_FORMAT, true);
}

static String formatAverageVolumeWithCode(Volume volume) {
return formatVolume(volume, FIAT_VOLUME_FORMAT.minDecimals(2), true);
}

public static String formatVolumeLabel(String currencyCode) {
Expand Down Expand Up @@ -205,24 +210,20 @@ public static String getOfferDirectionForCreateOffer(OfferPayload.Direction dire
// Amount
///////////////////////////////////////////////////////////////////////////////////////////

public static String formatAmount(Offer offer, CoinFormatter formatter) {
return formatAmount(offer, false, formatter);
}

private static String formatAmount(Offer offer, boolean decimalAligned, CoinFormatter coinFormatter) {
String formattedAmount = offer.isRange() ? coinFormatter.formatCoin(offer.getMinAmount()) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount()) : coinFormatter.formatCoin(offer.getAmount());
if (decimalAligned) {
formattedAmount = FormattingUtils.fillUpPlacesWithEmptyStrings(formattedAmount, 15);
}
return formattedAmount;
public static String formatAmount(Offer offer, CoinFormatter coinFormatter) {
return offer.isRange()
? coinFormatter.formatCoin(offer.getMinAmount()) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount())
: coinFormatter.formatCoin(offer.getAmount());
}

public static String formatAmount(Offer offer,
int decimalPlaces,
boolean decimalAligned,
int maxPlaces,
CoinFormatter coinFormatter) {
String formattedAmount = offer.isRange() ? coinFormatter.formatCoin(offer.getMinAmount(), decimalPlaces) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount(), decimalPlaces) : coinFormatter.formatCoin(offer.getAmount(), decimalPlaces);
String formattedAmount = offer.isRange()
? coinFormatter.formatCoin(offer.getMinAmount(), decimalPlaces) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount(), decimalPlaces)
: coinFormatter.formatCoin(offer.getAmount(), decimalPlaces);

if (decimalAligned) {
formattedAmount = FormattingUtils.fillUpPlacesWithEmptyStrings(formattedAmount, maxPlaces);
Expand Down Expand Up @@ -258,17 +259,21 @@ public static String getFeeWithFiatAmount(Coin makerFeeAsCoin,

/**
* Converts to a coin with max. 4 decimal places. Last place gets rounded.
* 0.01234 -> 0.0123
* 0.01235 -> 0.0124
* <p>0.01234 -> 0.0123
* <p>0.01235 -> 0.0124
*
* @param input
* @param coinFormatter
* @return
* @param input the decimal coin value to parse and round
* @param coinFormatter the coin formatter instance
* @return the converted coin
*/
public static Coin parseToCoinWith4Decimals(String input, CoinFormatter coinFormatter) {
try {
return Coin.valueOf(new BigDecimal(ParsingUtils.parseToCoin(ParsingUtils.cleanDoubleInput(input), coinFormatter).value).setScale(-scale - 1,
BigDecimal.ROUND_HALF_UP).setScale(scale + 1, BigDecimal.ROUND_HALF_UP).toBigInteger().longValue());
return Coin.valueOf(
new BigDecimal(ParsingUtils.parseToCoin(ParsingUtils.cleanDoubleInput(input), coinFormatter).value)
.setScale(-SCALE - 1, RoundingMode.HALF_UP)
.setScale(SCALE + 1, RoundingMode.HALF_UP)
.toBigInteger().longValue()
);
} catch (Throwable t) {
if (input != null && input.length() > 0)
log.warn("Exception at parseToCoinWith4Decimals: " + t.toString());
Expand All @@ -283,9 +288,9 @@ public static boolean hasBtcValidDecimals(String input, CoinFormatter coinFormat
/**
* Transform a coin with the properties defined in the format (used to reduce decimal places)
*
* @param coin The coin which should be transformed
* @param coinFormatter
* @return The transformed coin
* @param coin the coin which should be transformed
* @param coinFormatter the coin formatter instance
* @return the transformed coin
*/
public static Coin reduceTo4Decimals(Coin coin, CoinFormatter coinFormatter) {
return ParsingUtils.parseToCoin(coinFormatter.formatCoin(coin), coinFormatter);
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/main/java/bisq/desktop/util/GUIUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ public static void showBsqFeeInfoPopup(Coin fee, Coin miningFee, int txSize, Bsq
showBsqFeeInfoPopup(fee, miningFee, null, txSize, bsqFormatter, btcFormatter, type, actionHandler);
}

public static void setFitToRowsForTableView(TableView tableView,
public static void setFitToRowsForTableView(TableView<?> tableView,
int rowHeight,
int headerHeight,
int minNumRows,
Expand Down Expand Up @@ -1100,7 +1100,7 @@ public static String getBsqInUsd(Price bsqPrice,
Volume bsqAmountAsVolume = Volume.parse(bsqAmountAsString, "BSQ");
Coin requiredBtc = bsqPrice.getAmountByVolume(bsqAmountAsVolume);
Volume volumeByAmount = usdPrice.getVolumeByAmount(requiredBtc);
return DisplayUtils.formatVolumeWithCode(volumeByAmount);
return DisplayUtils.formatAverageVolumeWithCode(volumeByAmount);
}

public static MaterialDesignIcon getIconForSignState(AccountAgeWitnessService.SignState state) {
Expand Down
23 changes: 19 additions & 4 deletions desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@
import bisq.core.locale.GlobalSettings;
import bisq.core.locale.Res;
import bisq.core.locale.TradeCurrency;
import bisq.core.monetary.Price;
import bisq.core.provider.price.MarketPrice;
import bisq.core.provider.price.PriceFeedService;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.user.Preferences;
import bisq.core.util.coin.BsqFormatter;

import org.bitcoinj.core.Coin;
import org.bitcoinj.core.CoinMaker;
Expand Down Expand Up @@ -51,7 +55,6 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;


@Ignore
public class GUIUtilTest {

Expand All @@ -65,7 +68,7 @@ public void setup() {

@Test
public void testTradeCurrencyConverter() {
Map<String, Integer> offerCounts = new HashMap<String, Integer>() {{
Map<String, Integer> offerCounts = new HashMap<>() {{
put("BTC", 11);
put("EUR", 10);
}};
Expand All @@ -80,7 +83,7 @@ public void testTradeCurrencyConverter() {
}

@Test
public void testOpenURLWithCampaignParameters() throws Exception {
public void testOpenURLWithCampaignParameters() {
Preferences preferences = mock(Preferences.class);
DontShowAgainLookup.setPreferences(preferences);
GUIUtil.setPreferences(preferences);
Expand All @@ -101,7 +104,7 @@ public void testOpenURLWithCampaignParameters() throws Exception {
}

@Test
public void testOpenURLWithoutCampaignParameters() throws Exception {
public void testOpenURLWithoutCampaignParameters() {
Preferences preferences = mock(Preferences.class);
DontShowAgainLookup.setPreferences(preferences);
GUIUtil.setPreferences(preferences);
Expand Down Expand Up @@ -143,6 +146,18 @@ public void testAddressRegexValidator() {
assertFalse(regexValidator.validate("12.34.56.78:").isValid);
}

@Test
public void testGetBsqInUsd() {
PriceFeedService priceFeedService = mock(PriceFeedService.class);
when(priceFeedService.getMarketPrice("USD"))
.thenReturn(new MarketPrice("USD", 12345.6789, 0, true));

Coin oneBsq = Coin.valueOf(100);
Price avgPrice = Price.valueOf("BSQ", 10000);

assertEquals("1.23 USD", GUIUtil.getBsqInUsd(avgPrice, oneBsq, priceFeedService, new BsqFormatter()));
}

@Test
public void percentageOfTradeAmount_higherFeeAsMin() {

Expand Down

0 comments on commit f400298

Please sign in to comment.