diff --git a/core/src/main/java/io/bisq/core/offer/Offer.java b/core/src/main/java/io/bisq/core/offer/Offer.java index 542b9e018e9..fd0e9343e67 100644 --- a/core/src/main/java/io/bisq/core/offer/Offer.java +++ b/core/src/main/java/io/bisq/core/offer/Offer.java @@ -270,6 +270,10 @@ public Coin getMinAmount() { return Coin.valueOf(offerPayload.getMinAmount()); } + public boolean isRange() { + return offerPayload.getAmount() != offerPayload.getMinAmount(); + } + public Date getDate() { return new Date(offerPayload.getDate()); } diff --git a/core/src/test/java/io/bisq/core/offer/OfferTest.java b/core/src/test/java/io/bisq/core/offer/OfferTest.java new file mode 100644 index 00000000000..802809dd330 --- /dev/null +++ b/core/src/test/java/io/bisq/core/offer/OfferTest.java @@ -0,0 +1,36 @@ +package io.bisq.core.offer; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(OfferPayload.class) +public class OfferTest { + + @Test + public void testHasNoRange() { + OfferPayload payload = mock(OfferPayload.class); + when(payload.getMinAmount()).thenReturn(1000L); + when(payload.getAmount()).thenReturn(1000L); + + Offer offer = new Offer(payload); + assertFalse(offer.isRange()); + } + + @Test + public void testHasRange() { + OfferPayload payload = mock(OfferPayload.class); + when(payload.getMinAmount()).thenReturn(1000L); + when(payload.getAmount()).thenReturn(2000L); + + Offer offer = new Offer(payload); + assertTrue(offer.isRange()); + } +} diff --git a/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferView.java b/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferView.java index 34da719ae41..634c159d384 100644 --- a/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferView.java +++ b/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferView.java @@ -87,14 +87,14 @@ public class TakeOfferView extends ActivatableViewAndModel paymentAccountsComboBox; private Label directionLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, paymentAccountsLabel, paymentMethodLabel, priceCurrencyLabel, priceAsPercentageLabel, volumeCurrencyLabel, priceDescriptionLabel, volumeDescriptionLabel, - waitingForFundsLabel, offerAvailabilityLabel; + waitingForFundsLabel, offerAvailabilityLabel, amountCurrency; private InputTextField amountTextField; private TextField paymentMethodTextField, currencyTextField, priceTextField, priceAsPercentageTextField, volumeTextField, amountRangeTextField; @@ -116,7 +116,6 @@ public class TakeOfferView extends ActivatableViewAndModel { - if (DevEnv.DAO_TRADING_ACTIVATED) - showFeeOption(); - else - onShowPayFundsScreen(); + showNextStepAfterAmountIsSet(); }); cancelButton1 = new AutoTooltipButton(Res.get("shared.cancel")); @@ -741,6 +751,13 @@ private void addButtons() { }); } + private void showNextStepAfterAmountIsSet() { + if (DevEnv.DAO_TRADING_ACTIVATED) + showFeeOption(); + else + onShowPayFundsScreen(); + } + private void showFeeOption() { Coin makerFee = model.dataModel.getTakerFee(false); String missingBsq = null; @@ -892,6 +909,7 @@ private void addAmountPriceFields() { Tuple3 amountValueCurrencyBoxTuple = getAmountCurrencyBox(Res.get("takeOffer.amount.prompt")); HBox amountValueCurrencyBox = amountValueCurrencyBoxTuple.first; amountTextField = amountValueCurrencyBoxTuple.second; + amountCurrency = amountValueCurrencyBoxTuple.third; Tuple2 amountInputBoxTuple = getTradeInputBox(amountValueCurrencyBox, model.getAmountDescription()); amountDescriptionLabel = amountInputBoxTuple.first; VBox amountBox = amountInputBoxTuple.second; @@ -951,12 +969,14 @@ private void addSecondRow() { priceAsPercentageLabel.getStyleClass().add("percentage-label"); Tuple3 amountValueCurrencyBoxTuple = getNonEditableValueCurrencyBox(); - HBox amountValueCurrencyBox = amountValueCurrencyBoxTuple.first; amountRangeTextField = amountValueCurrencyBoxTuple.second; - Tuple2 amountInputBoxTuple = getTradeInputBox(amountValueCurrencyBox, + Tuple2 amountInputBoxTuple = getTradeInputBox( amountValueCurrencyBoxTuple.first, Res.get("takeOffer.amountPriceBox.amountRangeDescription")); + amountRangeBox = amountInputBoxTuple.second; + amountRangeBox.setVisible(false); + Label xLabel = new AutoTooltipLabel("x"); xLabel.setFont(Font.font("Helvetica-Bold", 20)); xLabel.setPadding(new Insets(14, 3, 0, 3)); @@ -965,7 +985,7 @@ private void addSecondRow() { HBox hBox = new HBox(); hBox.setSpacing(5); hBox.setAlignment(Pos.CENTER_LEFT); - hBox.getChildren().addAll(amountInputBoxTuple.second, xLabel, priceAsPercentageInputBox); + hBox.getChildren().addAll(amountRangeBox, xLabel, priceAsPercentageInputBox); GridPane.setRowIndex(hBox, ++gridRow); GridPane.setColumnIndex(hBox, 1); diff --git a/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferViewModel.java b/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferViewModel.java index 5286f0ea308..ba86839545d 100644 --- a/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferViewModel.java +++ b/gui/src/main/java/io/bisq/gui/main/offer/takeoffer/TakeOfferViewModel.java @@ -555,6 +555,8 @@ public Offer getOffer() { return dataModel.getOffer(); } + public boolean isRange() {return dataModel.getOffer().isRange(); } + public String getAmountRange() { return amountRange; } diff --git a/gui/src/main/java/io/bisq/gui/util/BSFormatter.java b/gui/src/main/java/io/bisq/gui/util/BSFormatter.java index 2922ad40cfc..7636a36344a 100644 --- a/gui/src/main/java/io/bisq/gui/util/BSFormatter.java +++ b/gui/src/main/java/io/bisq/gui/util/BSFormatter.java @@ -303,7 +303,7 @@ public String formatVolumeLabel(String currencyCode, String postFix) { } public String formatMinVolumeAndVolume(Offer offer) { - return formatVolume(offer.getMinVolume()) + " - " + formatVolume(offer.getVolume()); + return offer.isRange() ? formatVolume(offer.getMinVolume()) + " - " + formatVolume(offer.getVolume()) : formatVolume(offer.getVolume()); } @@ -316,7 +316,7 @@ public String formatAmount(Offer offer) { } public String formatAmountWithMinAmount(Offer offer) { - return formatCoin(offer.getMinAmount()) + " - " + formatCoin(offer.getAmount()); + return offer.isRange() ? formatCoin(offer.getMinAmount()) + " - " + formatCoin(offer.getAmount()) : formatCoin(offer.getAmount()); } diff --git a/gui/src/test/java/io/bisq/gui/util/BSFormatterTest.java b/gui/src/test/java/io/bisq/gui/util/BSFormatterTest.java index 42471714dc8..56e430574b3 100644 --- a/gui/src/test/java/io/bisq/gui/util/BSFormatterTest.java +++ b/gui/src/test/java/io/bisq/gui/util/BSFormatterTest.java @@ -18,21 +18,32 @@ package io.bisq.gui.util; import io.bisq.common.locale.Res; +import io.bisq.common.monetary.Volume; +import io.bisq.core.offer.Offer; +import io.bisq.core.offer.OfferPayload; +import org.bitcoinj.core.Coin; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import java.util.Locale; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +@RunWith(PowerMockRunner.class) +@PrepareForTest({Offer.class,OfferPayload.class}) public class BSFormatterTest { private BSFormatter formatter; @Before - public void setup() { + public void setUp() { Locale.setDefault(new Locale("en", "US")); formatter = new BSFormatter(); Res.setBaseCurrencyCode("BTC"); @@ -67,4 +78,63 @@ public void testFormatDurationAsWords() { assertEquals("", formatter.formatDurationAsWords(0)); assertTrue(formatter.formatDurationAsWords(0).isEmpty()); } + + @Test + public void testFormatSameVolume() { + Offer offer = mock(Offer.class); + Volume btc = Volume.parse("0.10", "BTC"); + when(offer.getMinVolume()).thenReturn(btc); + when(offer.getVolume()).thenReturn(btc); + + assertEquals("0.10000000", formatter.formatMinVolumeAndVolume(offer)); + } + + @Test + public void testFormatDifferentVolume() { + Offer offer = mock(Offer.class); + Volume btcMin = Volume.parse("0.10", "BTC"); + Volume btcMax = Volume.parse("0.25", "BTC"); + when(offer.isRange()).thenReturn(true); + when(offer.getMinVolume()).thenReturn(btcMin); + when(offer.getVolume()).thenReturn(btcMax); + + assertEquals("0.10000000 - 0.25000000", formatter.formatMinVolumeAndVolume(offer)); + } + + @Test + public void testFormatNullVolume() { + Offer offer = mock(Offer.class); + when(offer.getMinVolume()).thenReturn(null); + when(offer.getVolume()).thenReturn(null); + + assertEquals("", formatter.formatMinVolumeAndVolume(offer)); + } + + @Test + public void testFormatSameAmount() { + Offer offer = mock(Offer.class); + when(offer.getMinAmount()).thenReturn(Coin.valueOf(10000000)); + when(offer.getAmount()).thenReturn(Coin.valueOf(10000000)); + + assertEquals("0.10", formatter.formatAmountWithMinAmount(offer)); + } + + @Test + public void testFormatDifferentAmount() { + OfferPayload offerPayload = mock(OfferPayload.class); + Offer offer = new Offer(offerPayload); + when(offerPayload.getMinAmount()).thenReturn(10000000L); + when(offerPayload.getAmount()).thenReturn(20000000L); + + assertEquals("0.10 - 0.20", formatter.formatAmountWithMinAmount(offer)); + } + + @Test + public void testFormatNullAmount() { + Offer offer = mock(Offer.class); + when(offer.getMinAmount()).thenReturn(null); + when(offer.getAmount()).thenReturn(null); + + assertEquals("", formatter.formatAmountWithMinAmount(offer)); + } }