diff --git a/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java index c059249cc28..f1c9bce2c3f 100644 --- a/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java +++ b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java @@ -23,6 +23,7 @@ import java.text.DateFormat; import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Date; import java.util.Optional; @@ -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); @@ -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) { @@ -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) { @@ -205,16 +210,10 @@ 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, @@ -222,7 +221,9 @@ public static String formatAmount(Offer offer, 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); @@ -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 + *

0.01234 -> 0.0123 + *

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()); @@ -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); diff --git a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java index b46016264a5..71bc48102c5 100644 --- a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java @@ -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, @@ -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) { diff --git a/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java b/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java index e63cbf908dc..9f0c6c01edf 100644 --- a/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java +++ b/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java @@ -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; @@ -51,7 +55,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - @Ignore public class GUIUtilTest { @@ -65,7 +68,7 @@ public void setup() { @Test public void testTradeCurrencyConverter() { - Map offerCounts = new HashMap() {{ + Map offerCounts = new HashMap<>() {{ put("BTC", 11); put("EUR", 10); }}; @@ -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); @@ -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); @@ -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() {