Add trigger price to OpenOffersView

This commit is contained in:
chimp1984 2020-12-24 23:05:23 -05:00
parent f096351d60
commit 39893a6aaf
No known key found for this signature in database
GPG key ID: 9801B4EC591F90E3
11 changed files with 101 additions and 32 deletions

View file

@ -34,6 +34,7 @@ import bisq.core.notifications.alerts.TradeEvents;
import bisq.core.notifications.alerts.market.MarketAlerts;
import bisq.core.notifications.alerts.price.PriceAlert;
import bisq.core.offer.OpenOfferManager;
import bisq.core.offer.PriceEventHandler;
import bisq.core.payment.RevolutAccount;
import bisq.core.payment.TradeLimits;
import bisq.core.provider.fee.FeeService;
@ -106,6 +107,7 @@ public class DomainInitialisation {
private final MarketAlerts marketAlerts;
private final User user;
private final DaoStateSnapshotService daoStateSnapshotService;
private final PriceEventHandler priceEventHandler;
@Inject
public DomainInitialisation(ClockWatcher clockWatcher,
@ -141,7 +143,8 @@ public class DomainInitialisation {
PriceAlert priceAlert,
MarketAlerts marketAlerts,
User user,
DaoStateSnapshotService daoStateSnapshotService) {
DaoStateSnapshotService daoStateSnapshotService,
PriceEventHandler priceEventHandler) {
this.clockWatcher = clockWatcher;
this.tradeLimits = tradeLimits;
this.arbitrationManager = arbitrationManager;
@ -176,6 +179,7 @@ public class DomainInitialisation {
this.marketAlerts = marketAlerts;
this.user = user;
this.daoStateSnapshotService = daoStateSnapshotService;
this.priceEventHandler = priceEventHandler;
}
public void initDomainServices(Consumer<String> rejectedTxErrorMessageHandler,
@ -254,6 +258,7 @@ public class DomainInitialisation {
disputeMsgEvents.onAllServicesInitialized();
priceAlert.onAllServicesInitialized();
marketAlerts.onAllServicesInitialized();
priceEventHandler.onAllServicesInitialized();
if (revolutAccountsUpdateHandler != null) {
revolutAccountsUpdateHandler.accept(user.getPaymentAccountsAsObservable().stream()

View file

@ -92,7 +92,8 @@ public class PriceEventHandler {
}
String currencyCode = openOffer.getOffer().getCurrencyCode();
int smallestUnitExponent = CurrencyUtil.isCryptoCurrency(currencyCode) ?
boolean cryptoCurrency = CurrencyUtil.isCryptoCurrency(currencyCode);
int smallestUnitExponent = cryptoCurrency ?
Altcoin.SMALLEST_UNIT_EXPONENT :
Fiat.SMALLEST_UNIT_EXPONENT;
long marketPriceAsLong = roundDoubleToLong(
@ -100,13 +101,15 @@ public class PriceEventHandler {
long triggerPrice = openOffer.getTriggerPrice();
if (triggerPrice > 0) {
OfferPayload.Direction direction = openOffer.getOffer().getDirection();
boolean triggered = direction == OfferPayload.Direction.BUY ?
marketPriceAsLong > triggerPrice :
marketPriceAsLong < triggerPrice;
boolean isSellOffer = direction == OfferPayload.Direction.SELL;
boolean condition = isSellOffer && !cryptoCurrency || !isSellOffer && cryptoCurrency;
boolean triggered = condition ?
marketPriceAsLong < triggerPrice :
marketPriceAsLong > triggerPrice;
if (triggered) {
log.error("Market price exceeded the trigger price of the open offer. " +
"We deactivate the open offer with ID {}. Currency: {}; offer direction: {}; " +
"Market price: {}; Upper price threshold : {}",
log.info("Market price exceeded the trigger price of the open offer.\n" +
"We deactivate the open offer with ID {}.\nCurrency: {};\nOffer direction: {};\n" +
"Market price: {};\nTrigger price : {}",
openOffer.getOffer().getShortId(),
currencyCode,
direction,

View file

@ -221,6 +221,7 @@ shared.unconfirmedTransactionsLimitReached=You have too many unconfirmed transac
shared.numItemsLabel=Number of entries: {0}
shared.filter=Filter
shared.enabled=Enabled
shared.triggerPrice=Trigger price
####################################################################

View file

@ -679,7 +679,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel implements Bs
return tradeCurrencyCode;
}
String getCurrencyCode() {
public String getCurrencyCode() {
return tradeCurrencyCode.get();
}

View file

@ -106,8 +106,8 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
protected final CoinFormatter btcFormatter;
private final BsqFormatter bsqFormatter;
private final FiatVolumeValidator fiatVolumeValidator;
private final FiatPriceValidator fiatPriceValidator, fiatTriggerPriceValidator;
private final AltcoinValidator altcoinValidator, altcoinTriggerPriceValidator;
private final FiatPriceValidator fiatPriceValidator;
private final AltcoinValidator altcoinValidator;
protected final OfferUtil offerUtil;
private String amountDescription;
@ -223,9 +223,6 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
this.bsqFormatter = bsqFormatter;
this.offerUtil = offerUtil;
fiatTriggerPriceValidator = new FiatPriceValidator();
altcoinTriggerPriceValidator = new AltcoinValidator();
paymentLabel = Res.get("createOffer.fundsBox.paymentLabel", dataModel.shortOfferId);
if (dataModel.getAddressEntry() != null) {
@ -788,8 +785,13 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
}
}
void onTriggerPriceTextFieldChanged() {
public void onTriggerPriceTextFieldChanged() {
String triggerPriceAsString = triggerPrice.get();
// Error field does not update if there was an error and then another different error
// if not reset here. Not clear why...
triggerPriceValidationResult.set(new InputValidator.ValidationResult(true));
InputValidator.ValidationResult result = PriceUtil.isTriggerPriceValid(triggerPriceAsString,
dataModel.getPrice().get(),
dataModel.isSellOffer(),

View file

@ -313,7 +313,6 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
}
private void onWidthChange(double width) {
log.error("onWidthChange " + width);
txFeeColumn.setVisible(width > 1200);
tradeFeeColumn.setVisible(width > 1300);
buyerSecurityDepositColumn.setVisible(width > 1400);

View file

@ -170,7 +170,10 @@ class EditOfferDataModel extends MutableOfferDataModel {
setPrice(offer.getPrice());
setVolume(offer.getVolume());
setUseMarketBasedPrice(offer.isUseMarketBasedPrice());
if (offer.isUseMarketBasedPrice()) setMarketPriceMargin(offer.getMarketPriceMargin());
setTriggerPrice(openOffer.getTriggerPrice());
if (offer.isUseMarketBasedPrice()) {
setMarketPriceMargin(offer.getMarketPriceMargin());
}
}
public void onStartEditOffer(ErrorMessageHandler errorMessageHandler) {

View file

@ -80,15 +80,22 @@ class EditOfferViewModel extends MutableOfferViewModel<EditOfferDataModel> {
@Override
public void activate() {
super.activate();
dataModel.populateData();
long triggerPriceAsLong = dataModel.getTriggerPrice();
dataModel.setTriggerPrice(triggerPriceAsLong);
if (triggerPriceAsLong > 0) {
triggerPrice.set(PriceUtil.formatMarketPrice(triggerPriceAsLong, dataModel.getCurrencyCode()));
} else {
triggerPrice.set("");
}
onTriggerPriceTextFieldChanged();
}
public void applyOpenOffer(OpenOffer openOffer) {
dataModel.reset();
dataModel.applyOpenOffer(openOffer);
dataModel.setTriggerPrice(openOffer.getTriggerPrice());
triggerPrice.set(PriceUtil.formatMarketPrice(openOffer.getTriggerPrice(), openOffer.getOffer().getCurrencyCode()));
}
public void onStartEditOffer(ErrorMessageHandler errorMessageHandler) {

View file

@ -47,6 +47,7 @@
<TableColumn fx:id="marketColumn" minWidth="75"/>
<TableColumn fx:id="priceColumn" minWidth="100"/>
<TableColumn fx:id="deviationColumn" minWidth="70"/>
<TableColumn fx:id="triggerPriceColumn" minWidth="70"/>
<TableColumn fx:id="amountColumn" minWidth="110"/>
<TableColumn fx:id="volumeColumn" minWidth="110"/>
<TableColumn fx:id="paymentMethodColumn" minWidth="120" maxWidth="170"/>

View file

@ -89,7 +89,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
@FXML
TableColumn<OpenOfferListItem, OpenOfferListItem> priceColumn, deviationColumn, amountColumn, volumeColumn,
marketColumn, directionColumn, dateColumn, offerIdColumn, deactivateItemColumn,
removeItemColumn, editItemColumn, paymentMethodColumn;
removeItemColumn, editItemColumn, triggerPriceColumn, paymentMethodColumn;
@FXML
HBox searchBox;
@FXML
@ -113,6 +113,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
private FilteredList<OpenOfferListItem> filteredList;
private ChangeListener<String> filterTextFieldListener;
private PortfolioView.OpenOfferActionHandler openOfferActionHandler;
private ChangeListener<Number> widthListener;
@Inject
public OpenOffersView(OpenOffersViewModel model, Navigation navigation, OfferDetailsWindow offerDetailsWindow) {
@ -123,6 +124,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
@Override
public void initialize() {
widthListener = (observable, oldValue, newValue) -> onWidthChange((double) newValue);
paymentMethodColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.paymentMethod")));
priceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.price")));
deviationColumn.setGraphic(new AutoTooltipTableColumn<>(Res.get("shared.deviation"),
@ -133,6 +135,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
directionColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.offerType")));
dateColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.dateTime")));
offerIdColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.offerId")));
triggerPriceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.triggerPrice")));
deactivateItemColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.enabled")));
editItemColumn.setGraphic(new AutoTooltipLabel(""));
removeItemColumn.setGraphic(new AutoTooltipLabel(""));
@ -148,6 +151,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
setDateColumnCellFactory();
setDeactivateColumnCellFactory();
setEditColumnCellFactory();
setTriggerPriceColumnCellFactory();
setRemoveColumnCellFactory();
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
@ -159,6 +163,8 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
amountColumn.setComparator(Comparator.comparing(o -> o.getOffer().getAmount()));
priceColumn.setComparator(Comparator.comparing(o -> o.getOffer().getPrice(), Comparator.nullsFirst(Comparator.naturalOrder())));
deviationColumn.setComparator(Comparator.comparing(model::getPriceDeviationAsDouble, Comparator.nullsFirst(Comparator.naturalOrder())));
triggerPriceColumn.setComparator(Comparator.comparing(o -> o.getOpenOffer().getTriggerPrice(),
Comparator.nullsFirst(Comparator.naturalOrder())));
volumeColumn.setComparator(Comparator.comparing(o -> o.getOffer().getVolume(), Comparator.nullsFirst(Comparator.naturalOrder())));
dateColumn.setComparator(Comparator.comparing(o -> o.getOffer().getDate()));
paymentMethodColumn.setComparator(Comparator.comparing(o -> Res.get(o.getOffer().getPaymentMethod().getId())));
@ -245,6 +251,18 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
filterTextField.textProperty().addListener(filterTextFieldListener);
applyFilteredListPredicate(filterTextField.getText());
root.widthProperty().addListener(widthListener);
onWidthChange(root.getWidth());
}
@Override
protected void deactivate() {
sortedList.comparatorProperty().unbind();
exportButton.setOnAction(null);
filterTextField.textProperty().removeListener(filterTextFieldListener);
root.widthProperty().removeListener(widthListener);
}
private void updateSelectToggleButtonState() {
@ -264,14 +282,6 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
}
}
@Override
protected void deactivate() {
sortedList.comparatorProperty().unbind();
exportButton.setOnAction(null);
filterTextField.textProperty().removeListener(filterTextFieldListener);
}
private void applyFilteredListPredicate(String filterString) {
filteredList.setPredicate(item -> {
if (filterString.isEmpty())
@ -312,6 +322,10 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
});
}
private void onWidthChange(double width) {
triggerPriceColumn.setVisible(width > 1200);
}
private void onDeactivateOpenOffer(OpenOffer openOffer) {
if (model.isBootstrappedOrShowPopup()) {
model.onDeactivateOpenOffer(openOffer,
@ -514,6 +528,30 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
});
}
private void setTriggerPriceColumnCellFactory() {
triggerPriceColumn.setCellValueFactory((offerListItem) -> new ReadOnlyObjectWrapper<>(offerListItem.getValue()));
triggerPriceColumn.setCellFactory(
new Callback<>() {
@Override
public TableCell<OpenOfferListItem, OpenOfferListItem> call(
TableColumn<OpenOfferListItem, OpenOfferListItem> column) {
return new TableCell<>() {
@Override
public void updateItem(final OpenOfferListItem item, boolean empty) {
super.updateItem(item, empty);
getStyleClass().removeAll("offer-disabled");
if (item != null) {
if (model.isDeactivated(item)) getStyleClass().add("offer-disabled");
setGraphic(new AutoTooltipLabel(model.getTriggerPrice(item)));
} else {
setGraphic(null);
}
}
};
}
});
}
private void setVolumeColumnCellFactory() {
volumeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
volumeColumn.setCellFactory(
@ -660,7 +698,6 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
};
}
});
deactivateItemColumn.setSortable(false);
}
private void setRemoveColumnCellFactory() {
@ -695,7 +732,6 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
};
}
});
removeItemColumn.setSortable(false);
}
private void setEditColumnCellFactory() {
@ -729,7 +765,6 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
};
}
});
editItemColumn.setSortable(false);
}
public void setOpenOfferActionHandler(PortfolioView.OpenOfferActionHandler openOfferActionHandler) {

View file

@ -171,4 +171,17 @@ class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel>
btcFormatter.formatCoinWithCode(offer.getMakerFee()) :
bsqFormatter.formatCoinWithCode(offer.getMakerFee());
}
String getTriggerPrice(OpenOfferListItem item) {
if ((item == null))
return "";
Offer offer = item.getOffer();
if (offer.isUseMarketBasedPrice()) {
return PriceUtil.formatMarketPrice(item.getOpenOffer().getTriggerPrice(), offer.getCurrencyCode());
} else {
return Res.get("shared.na");
}
}
}