mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-19 23:36:00 -04:00
add percentage price (WIP)
This commit is contained in:
parent
5ba1aa0a59
commit
517ee371db
@ -106,6 +106,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
private final long date;
|
||||
private final long protocolVersion;
|
||||
private final long fiatPrice;
|
||||
private final double percentagePrice;
|
||||
private final boolean usePercentageBasedPrice;
|
||||
private final long amount;
|
||||
private final long minAmount;
|
||||
private final NodeAddress offererNodeAddress;
|
||||
@ -138,6 +140,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
PubKeyRing pubKeyRing,
|
||||
Direction direction,
|
||||
long fiatPrice,
|
||||
double percentagePrice,
|
||||
boolean usePercentageBasedPrice,
|
||||
long amount,
|
||||
long minAmount,
|
||||
String currencyCode,
|
||||
@ -153,6 +157,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
this.pubKeyRing = pubKeyRing;
|
||||
this.direction = direction;
|
||||
this.fiatPrice = fiatPrice;
|
||||
this.percentagePrice = percentagePrice;
|
||||
this.usePercentageBasedPrice = usePercentageBasedPrice;
|
||||
this.amount = amount;
|
||||
this.minAmount = minAmount;
|
||||
this.currencyCode = currencyCode;
|
||||
@ -315,6 +321,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
return Fiat.valueOf(currencyCode, fiatPrice);
|
||||
}
|
||||
|
||||
public double getPercentagePrice() {
|
||||
return percentagePrice;
|
||||
}
|
||||
|
||||
public boolean isUsePercentageBasedPrice() {
|
||||
return usePercentageBasedPrice;
|
||||
}
|
||||
|
||||
public Coin getAmount() {
|
||||
return Coin.valueOf(amount);
|
||||
}
|
||||
@ -391,11 +405,11 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Offer)) return false;
|
||||
|
||||
Offer offer = (Offer) o;
|
||||
|
||||
if (date != offer.date) return false;
|
||||
if (fiatPrice != offer.fiatPrice) return false;
|
||||
if (Double.compare(offer.percentagePrice, percentagePrice) != 0) return false;
|
||||
if (usePercentageBasedPrice != offer.usePercentageBasedPrice) return false;
|
||||
if (amount != offer.amount) return false;
|
||||
if (minAmount != offer.minAmount) return false;
|
||||
if (id != null ? !id.equals(offer.id) : offer.id != null) return false;
|
||||
@ -418,7 +432,6 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
if (arbitratorNodeAddresses != null ? !arbitratorNodeAddresses.equals(offer.arbitratorNodeAddresses) : offer.arbitratorNodeAddresses != null)
|
||||
return false;
|
||||
return !(offerFeePaymentTxID != null ? !offerFeePaymentTxID.equals(offer.offerFeePaymentTxID) : offer.offerFeePaymentTxID != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -428,6 +441,9 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
result = 31 * result + (currencyCode != null ? currencyCode.hashCode() : 0);
|
||||
result = 31 * result + (int) (date ^ (date >>> 32));
|
||||
result = 31 * result + (int) (fiatPrice ^ (fiatPrice >>> 32));
|
||||
long temp = Double.doubleToLongBits(percentagePrice);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
result = 31 * result + (usePercentageBasedPrice ? 1 : 0);
|
||||
result = 31 * result + (int) (amount ^ (amount >>> 32));
|
||||
result = 31 * result + (int) (minAmount ^ (minAmount >>> 32));
|
||||
result = 31 * result + (offererNodeAddress != null ? offererNodeAddress.hashCode() : 0);
|
||||
@ -451,6 +467,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
"\n\tcurrencyCode='" + currencyCode + '\'' +
|
||||
"\n\tdate=" + date +
|
||||
"\n\tfiatPrice=" + fiatPrice +
|
||||
"\n\tpercentagePrice=" + percentagePrice +
|
||||
"\n\tusePercentageBasedPrice=" + usePercentageBasedPrice +
|
||||
"\n\tamount=" + amount +
|
||||
"\n\tminAmount=" + minAmount +
|
||||
"\n\toffererAddress=" + offererNodeAddress +
|
||||
@ -471,5 +489,4 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||
"\n\tTAC_TAKER=" + TAC_TAKER +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -496,6 +496,26 @@ textfield */
|
||||
-fx-border-insets: 0 0 0 -2;
|
||||
}
|
||||
|
||||
#toggle-price-left {
|
||||
-fx-border-radius: 4 0 0 4;
|
||||
-fx-padding: 4 4 4 4;
|
||||
-fx-border-color: #aaa;
|
||||
-fx-border-style: solid none solid solid;
|
||||
-fx-border-insets: 0 -2 0 0;
|
||||
-fx-background-insets: 0 -2 0 0;
|
||||
-fx-background-radius: 4 0 0 4;
|
||||
}
|
||||
|
||||
#toggle-price-right {
|
||||
-fx-border-radius: 0 4 4 0;
|
||||
-fx-padding: 4 4 4 4;
|
||||
-fx-border-color: #aaa;
|
||||
-fx-border-style: solid solid solid none;
|
||||
-fx-border-insets: 0 0 0 -2;
|
||||
-fx-background-insets: 0 0 0 -2;
|
||||
-fx-background-radius: 0 4 4 0;
|
||||
}
|
||||
|
||||
#totals-separator {
|
||||
-fx-background: #AAAAAA;
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
final StringProperty btcCode = new SimpleStringProperty();
|
||||
|
||||
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
|
||||
final BooleanProperty usePercentageBasedPrice = new SimpleBooleanProperty();
|
||||
//final BooleanProperty isMainNet = new SimpleBooleanProperty();
|
||||
//final BooleanProperty isFeeFromFundingTxSufficient = new SimpleBooleanProperty();
|
||||
|
||||
@ -96,6 +97,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> minAmountAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Fiat> priceAsFiat = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Double> priceAsPercentage = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Fiat> volumeAsFiat = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> totalToPayAsCoin = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Coin> missingCoin = new SimpleObjectProperty<>(Coin.ZERO);
|
||||
@ -253,6 +255,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
|
||||
Offer createAndGetOffer() {
|
||||
long fiatPrice = priceAsFiat.get() != null ? priceAsFiat.get().getValue() : 0L;
|
||||
|
||||
double percentagePrice = 0;
|
||||
long amount = amountAsCoin.get() != null ? amountAsCoin.get().getValue() : 0L;
|
||||
long minAmount = minAmountAsCoin.get() != null ? minAmountAsCoin.get().getValue() : 0L;
|
||||
|
||||
@ -284,6 +288,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
keyRing.getPubKeyRing(),
|
||||
direction,
|
||||
fiatPrice,
|
||||
percentagePrice,
|
||||
usePercentageBasedPrice.get(),
|
||||
amount,
|
||||
minAmount,
|
||||
tradeCurrencyCode.get(),
|
||||
@ -378,6 +384,10 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||
return user.getAcceptedArbitrators().size() > 0;
|
||||
}
|
||||
|
||||
public void setUsePercentageBasedPrice(boolean usePercentageBasedPrice) {
|
||||
this.usePercentageBasedPrice.set(usePercentageBasedPrice);
|
||||
}
|
||||
|
||||
/*boolean isFeeFromFundingTxSufficient() {
|
||||
return !isMainNet.get() || feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0;
|
||||
}*/
|
||||
|
@ -88,8 +88,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
private BalanceTextField balanceTextField;
|
||||
private TitledGroupBg payFundsPane;
|
||||
private ProgressIndicator spinner;
|
||||
private Button nextButton, cancelButton1, cancelButton2, fundFromSavingsWalletButton, fundFromExternalWalletButton, placeOfferButton;
|
||||
private InputTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
|
||||
private Button nextButton, cancelButton1, cancelButton2, fundFromSavingsWalletButton, fundFromExternalWalletButton, placeOfferButton, usePercentageBasedPriceButton;
|
||||
private InputTextField amountTextField, minAmountTextField, priceTextField, priceAsPercentageTextField, volumeTextField;
|
||||
private TextField currencyTextField;
|
||||
private Label directionLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, amountBtcLabel, priceCurrencyLabel,
|
||||
volumeCurrencyLabel, minAmountBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, currencyTextFieldLabel,
|
||||
@ -98,6 +98,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
private ComboBox<PaymentAccount> paymentAccountsComboBox;
|
||||
private ComboBox<TradeCurrency> currencyComboBox;
|
||||
private PopOver totalToPayInfoPopover;
|
||||
private Label priceAsPercentageLabel;
|
||||
private ToggleButton fixedPriceButton;
|
||||
private ToggleButton percentagePriceButton;
|
||||
|
||||
private OfferView.CloseHandler closeHandler;
|
||||
|
||||
@ -175,6 +178,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
if (spinner != null && spinner.isVisible())
|
||||
spinner.setProgress(-1);
|
||||
|
||||
percentagePriceButton.setSelected(model.dataModel.usePercentageBasedPrice.get());
|
||||
fixedPriceButton.setSelected(!model.dataModel.usePercentageBasedPrice.get());
|
||||
|
||||
directionLabel.setText(model.getDirectionLabel());
|
||||
amountDescriptionLabel.setText(model.getAmountDescription());
|
||||
addressTextField.setAddress(model.getAddressAsString());
|
||||
@ -407,6 +413,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
private void addBindings() {
|
||||
amountBtcLabel.textProperty().bind(model.btcCode);
|
||||
priceCurrencyLabel.textProperty().bind(createStringBinding(() -> model.tradeCurrencyCode.get() + "/" + model.btcCode.get(), model.btcCode, model.tradeCurrencyCode));
|
||||
priceTextField.disableProperty().bind(model.dataModel.usePercentageBasedPrice);
|
||||
priceAsPercentageTextField.disableProperty().bind(model.dataModel.usePercentageBasedPrice.not());
|
||||
priceAsPercentageLabel.prefWidthProperty().bind(priceCurrencyLabel.widthProperty());
|
||||
volumeCurrencyLabel.textProperty().bind(model.tradeCurrencyCode);
|
||||
minAmountBtcLabel.textProperty().bind(model.btcCode);
|
||||
priceDescriptionLabel.textProperty().bind(createStringBinding(() -> BSResources.get("createOffer.amountPriceBox.priceDescription", model.tradeCurrencyCode.get()), model.tradeCurrencyCode));
|
||||
@ -452,6 +461,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
private void removeBindings() {
|
||||
amountBtcLabel.textProperty().unbind();
|
||||
priceCurrencyLabel.textProperty().unbind();
|
||||
priceTextField.disableProperty().unbind();
|
||||
priceAsPercentageTextField.disableProperty().unbind();
|
||||
volumeCurrencyLabel.textProperty().unbind();
|
||||
minAmountBtcLabel.textProperty().unbind();
|
||||
priceDescriptionLabel.textProperty().unbind();
|
||||
@ -459,6 +470,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
amountTextField.textProperty().unbindBidirectional(model.amount);
|
||||
minAmountTextField.textProperty().unbindBidirectional(model.minAmount);
|
||||
priceTextField.textProperty().unbindBidirectional(model.price);
|
||||
priceAsPercentageLabel.prefWidthProperty().unbind();
|
||||
volumeTextField.textProperty().unbindBidirectional(model.volume);
|
||||
volumeTextField.promptTextProperty().unbindBidirectional(model.volume);
|
||||
totalToPayTextField.textProperty().unbind();
|
||||
@ -745,8 +757,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
gridPane.getChildren().add(imageVBox);
|
||||
|
||||
addAmountPriceFields();
|
||||
|
||||
addMinAmountBox();
|
||||
addSecondRow();
|
||||
|
||||
Tuple2<Button, Button> tuple = add2ButtonsAfterGroup(gridPane, ++gridRow, BSResources.get("createOffer.amountPriceBox.next"), BSResources.get("shared.cancel"));
|
||||
nextButton = tuple.first;
|
||||
@ -897,7 +908,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
xLabel.setFont(Font.font("Helvetica-Bold", 20));
|
||||
xLabel.setPadding(new Insets(14, 3, 0, 3));
|
||||
|
||||
// price
|
||||
// price as fiat
|
||||
Tuple3<HBox, InputTextField, Label> priceValueCurrencyBoxTuple = FormBuilder.getValueCurrencyBox(BSResources.get("createOffer.price.prompt"));
|
||||
HBox priceValueCurrencyBox = priceValueCurrencyBoxTuple.first;
|
||||
priceTextField = priceValueCurrencyBoxTuple.second;
|
||||
@ -906,6 +917,26 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
priceDescriptionLabel = priceInputBoxTuple.first;
|
||||
VBox priceBox = priceInputBoxTuple.second;
|
||||
|
||||
// Fixed/Percentage toggle
|
||||
ToggleGroup toggleGroup = new ToggleGroup();
|
||||
fixedPriceButton = new ToggleButton("Fixed");
|
||||
fixedPriceButton.setId("toggle-price-left");
|
||||
fixedPriceButton.setToggleGroup(toggleGroup);
|
||||
fixedPriceButton.selectedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
model.dataModel.setUsePercentageBasedPrice(!newValue);
|
||||
});
|
||||
|
||||
percentagePriceButton = new ToggleButton("Percentage");
|
||||
percentagePriceButton.setId("toggle-price-right");
|
||||
percentagePriceButton.setToggleGroup(toggleGroup);
|
||||
percentagePriceButton.selectedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
model.dataModel.setUsePercentageBasedPrice(newValue);
|
||||
});
|
||||
|
||||
HBox toggleButtons = new HBox();
|
||||
toggleButtons.setPadding(new Insets(18, 0, 0, 0));
|
||||
toggleButtons.getChildren().addAll(fixedPriceButton, percentagePriceButton);
|
||||
|
||||
// =
|
||||
Label resultLabel = new Label("=");
|
||||
resultLabel.setFont(Font.font("Helvetica-Bold", 20));
|
||||
@ -923,7 +954,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
HBox hBox = new HBox();
|
||||
hBox.setSpacing(5);
|
||||
hBox.setAlignment(Pos.CENTER_LEFT);
|
||||
hBox.getChildren().addAll(amountBox, xLabel, priceBox, resultLabel, volumeBox);
|
||||
hBox.getChildren().addAll(amountBox, xLabel, priceBox, toggleButtons, resultLabel, volumeBox);
|
||||
GridPane.setRowIndex(hBox, gridRow);
|
||||
GridPane.setColumnIndex(hBox, 1);
|
||||
GridPane.setMargin(hBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 0, 0));
|
||||
@ -931,7 +962,20 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
gridPane.getChildren().add(hBox);
|
||||
}
|
||||
|
||||
private void addMinAmountBox() {
|
||||
private void addSecondRow() {
|
||||
Tuple3<HBox, InputTextField, Label> priceAsPercentageTuple = FormBuilder.getValueCurrencyBox(BSResources.get("createOffer.price.prompt"));
|
||||
HBox priceAsPercentageValueCurrencyBox = priceAsPercentageTuple.first;
|
||||
priceAsPercentageTextField = priceAsPercentageTuple.second;
|
||||
priceAsPercentageLabel = priceAsPercentageTuple.third;
|
||||
|
||||
Tuple2<Label, VBox> priceAsPercentageInputBoxTuple = getTradeInputBox(priceAsPercentageValueCurrencyBox, "Distance in % from market price");
|
||||
priceAsPercentageInputBoxTuple.first.setPrefWidth(200);
|
||||
VBox priceAsPercentageInputBox = priceAsPercentageInputBoxTuple.second;
|
||||
|
||||
priceAsPercentageTextField.setPromptText("Enter % value");
|
||||
priceAsPercentageLabel.setText("% dist.");
|
||||
priceAsPercentageLabel.setStyle("-fx-alignment: center;");
|
||||
|
||||
Tuple3<HBox, InputTextField, Label> amountValueCurrencyBoxTuple = getValueCurrencyBox(BSResources.get("createOffer.amount.prompt"));
|
||||
HBox amountValueCurrencyBox = amountValueCurrencyBoxTuple.first;
|
||||
minAmountTextField = amountValueCurrencyBoxTuple.second;
|
||||
@ -939,11 +983,21 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
|
||||
Tuple2<Label, VBox> amountInputBoxTuple = getTradeInputBox(amountValueCurrencyBox, BSResources.get("createOffer.amountPriceBox" +
|
||||
".minAmountDescription"));
|
||||
VBox box = amountInputBoxTuple.second;
|
||||
GridPane.setRowIndex(box, ++gridRow);
|
||||
GridPane.setColumnIndex(box, 1);
|
||||
GridPane.setMargin(box, new Insets(5, 10, 5, 0));
|
||||
gridPane.getChildren().add(box);
|
||||
|
||||
Label xLabel = new Label("x");
|
||||
xLabel.setFont(Font.font("Helvetica-Bold", 20));
|
||||
xLabel.setPadding(new Insets(14, 3, 0, 3));
|
||||
xLabel.setVisible(false); // we just use it to get the same layout as the upper row
|
||||
|
||||
HBox hBox = new HBox();
|
||||
hBox.setSpacing(5);
|
||||
hBox.setAlignment(Pos.CENTER_LEFT);
|
||||
hBox.getChildren().addAll(amountInputBoxTuple.second, xLabel, priceAsPercentageInputBox);
|
||||
GridPane.setRowIndex(hBox, ++gridRow);
|
||||
GridPane.setColumnIndex(hBox, 1);
|
||||
GridPane.setMargin(hBox, new Insets(5, 10, 5, 0));
|
||||
GridPane.setColumnSpan(hBox, 2);
|
||||
gridPane.getChildren().add(hBox);
|
||||
}
|
||||
|
||||
|
||||
|
@ -267,6 +267,8 @@ public class OfferBookViewModelTest {
|
||||
null,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
tradeCurrencyCode,
|
||||
null,
|
||||
|
Loading…
x
Reference in New Issue
Block a user