mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-02-26 17:31:27 -05:00
re-enable triggered offers if within trigger price again
This commit is contained in:
parent
4a82c69507
commit
290a3738b7
@ -110,6 +110,10 @@ public final class OpenOffer implements Tradable {
|
|||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
transient int numProcessingAttempts = 0;
|
transient int numProcessingAttempts = 0;
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private boolean deactivatedByTrigger;
|
||||||
|
|
||||||
public OpenOffer(Offer offer) {
|
public OpenOffer(Offer offer) {
|
||||||
this(offer, 0, false);
|
this(offer, 0, false);
|
||||||
}
|
}
|
||||||
@ -141,6 +145,7 @@ public final class OpenOffer implements Tradable {
|
|||||||
this.reserveTxHex = openOffer.reserveTxHex;
|
this.reserveTxHex = openOffer.reserveTxHex;
|
||||||
this.reserveTxKey = openOffer.reserveTxKey;
|
this.reserveTxKey = openOffer.reserveTxKey;
|
||||||
this.challenge = openOffer.challenge;
|
this.challenge = openOffer.challenge;
|
||||||
|
this.deactivatedByTrigger = openOffer.deactivatedByTrigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -158,7 +163,8 @@ public final class OpenOffer implements Tradable {
|
|||||||
@Nullable String reserveTxHash,
|
@Nullable String reserveTxHash,
|
||||||
@Nullable String reserveTxHex,
|
@Nullable String reserveTxHex,
|
||||||
@Nullable String reserveTxKey,
|
@Nullable String reserveTxKey,
|
||||||
@Nullable String challenge) {
|
@Nullable String challenge,
|
||||||
|
boolean deactivatedByTrigger) {
|
||||||
this.offer = offer;
|
this.offer = offer;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.triggerPrice = triggerPrice;
|
this.triggerPrice = triggerPrice;
|
||||||
@ -170,6 +176,7 @@ public final class OpenOffer implements Tradable {
|
|||||||
this.reserveTxHex = reserveTxHex;
|
this.reserveTxHex = reserveTxHex;
|
||||||
this.reserveTxKey = reserveTxKey;
|
this.reserveTxKey = reserveTxKey;
|
||||||
this.challenge = challenge;
|
this.challenge = challenge;
|
||||||
|
this.deactivatedByTrigger = deactivatedByTrigger;
|
||||||
|
|
||||||
// reset reserved state to available
|
// reset reserved state to available
|
||||||
if (this.state == State.RESERVED) setState(State.AVAILABLE);
|
if (this.state == State.RESERVED) setState(State.AVAILABLE);
|
||||||
@ -182,7 +189,8 @@ public final class OpenOffer implements Tradable {
|
|||||||
.setTriggerPrice(triggerPrice)
|
.setTriggerPrice(triggerPrice)
|
||||||
.setState(protobuf.OpenOffer.State.valueOf(state.name()))
|
.setState(protobuf.OpenOffer.State.valueOf(state.name()))
|
||||||
.setSplitOutputTxFee(splitOutputTxFee)
|
.setSplitOutputTxFee(splitOutputTxFee)
|
||||||
.setReserveExactAmount(reserveExactAmount);
|
.setReserveExactAmount(reserveExactAmount)
|
||||||
|
.setDeactivatedByTrigger(deactivatedByTrigger);
|
||||||
|
|
||||||
Optional.ofNullable(scheduledAmount).ifPresent(e -> builder.setScheduledAmount(scheduledAmount));
|
Optional.ofNullable(scheduledAmount).ifPresent(e -> builder.setScheduledAmount(scheduledAmount));
|
||||||
Optional.ofNullable(scheduledTxHashes).ifPresent(e -> builder.addAllScheduledTxHashes(scheduledTxHashes));
|
Optional.ofNullable(scheduledTxHashes).ifPresent(e -> builder.addAllScheduledTxHashes(scheduledTxHashes));
|
||||||
@ -207,7 +215,8 @@ public final class OpenOffer implements Tradable {
|
|||||||
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHash()),
|
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHash()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()),
|
ProtoUtil.stringOrNullFromProto(proto.getReserveTxHex()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()),
|
ProtoUtil.stringOrNullFromProto(proto.getReserveTxKey()),
|
||||||
ProtoUtil.stringOrNullFromProto(proto.getChallenge()));
|
ProtoUtil.stringOrNullFromProto(proto.getChallenge()),
|
||||||
|
proto.getDeactivatedByTrigger());
|
||||||
return openOffer;
|
return openOffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,6 +243,14 @@ public final class OpenOffer implements Tradable {
|
|||||||
public void setState(State state) {
|
public void setState(State state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
stateProperty.set(state);
|
stateProperty.set(state);
|
||||||
|
if (state == State.AVAILABLE) {
|
||||||
|
deactivatedByTrigger = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deactivate(boolean deactivatedByTrigger) {
|
||||||
|
this.deactivatedByTrigger = deactivatedByTrigger;
|
||||||
|
setState(State.DEACTIVATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlyObjectProperty<State> stateProperty() {
|
public ReadOnlyObjectProperty<State> stateProperty() {
|
||||||
|
@ -604,13 +604,14 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void deactivateOpenOffer(OpenOffer openOffer,
|
public void deactivateOpenOffer(OpenOffer openOffer,
|
||||||
|
boolean deactivatedByTrigger,
|
||||||
ResultHandler resultHandler,
|
ResultHandler resultHandler,
|
||||||
ErrorMessageHandler errorMessageHandler) {
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
Offer offer = openOffer.getOffer();
|
Offer offer = openOffer.getOffer();
|
||||||
if (openOffer.isAvailable()) {
|
if (openOffer.isAvailable()) {
|
||||||
offerBookService.deactivateOffer(offer.getOfferPayload(),
|
offerBookService.deactivateOffer(offer.getOfferPayload(),
|
||||||
() -> {
|
() -> {
|
||||||
openOffer.setState(OpenOffer.State.DEACTIVATED);
|
openOffer.deactivate(deactivatedByTrigger);
|
||||||
requestPersistence();
|
requestPersistence();
|
||||||
log.debug("deactivateOpenOffer, offerId={}", offer.getId());
|
log.debug("deactivateOpenOffer, offerId={}", offer.getId());
|
||||||
resultHandler.handleResult();
|
resultHandler.handleResult();
|
||||||
@ -661,6 +662,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
|
|
||||||
if (openOffer.isAvailable()) {
|
if (openOffer.isAvailable()) {
|
||||||
deactivateOpenOffer(openOffer,
|
deactivateOpenOffer(openOffer,
|
||||||
|
false,
|
||||||
resultHandler,
|
resultHandler,
|
||||||
errorMessage -> {
|
errorMessage -> {
|
||||||
offersToBeEdited.remove(openOffer.getId());
|
offersToBeEdited.remove(openOffer.getId());
|
||||||
|
@ -92,12 +92,11 @@ public class TriggerPriceService {
|
|||||||
.filter(marketPrice -> openOffersByCurrency.containsKey(marketPrice.getCurrencyCode()))
|
.filter(marketPrice -> openOffersByCurrency.containsKey(marketPrice.getCurrencyCode()))
|
||||||
.forEach(marketPrice -> {
|
.forEach(marketPrice -> {
|
||||||
openOffersByCurrency.get(marketPrice.getCurrencyCode()).stream()
|
openOffersByCurrency.get(marketPrice.getCurrencyCode()).stream()
|
||||||
.filter(openOffer -> !openOffer.isDeactivated())
|
|
||||||
.forEach(openOffer -> checkPriceThreshold(marketPrice, openOffer));
|
.forEach(openOffer -> checkPriceThreshold(marketPrice, openOffer));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean wasTriggered(MarketPrice marketPrice, OpenOffer openOffer) {
|
public static boolean isTriggered(MarketPrice marketPrice, OpenOffer openOffer) {
|
||||||
Price price = openOffer.getOffer().getPrice();
|
Price price = openOffer.getOffer().getPrice();
|
||||||
if (price == null || marketPrice == null) {
|
if (price == null || marketPrice == null) {
|
||||||
return false;
|
return false;
|
||||||
@ -125,13 +124,12 @@ public class TriggerPriceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkPriceThreshold(MarketPrice marketPrice, OpenOffer openOffer) {
|
private void checkPriceThreshold(MarketPrice marketPrice, OpenOffer openOffer) {
|
||||||
if (wasTriggered(marketPrice, openOffer)) {
|
String currencyCode = openOffer.getOffer().getCurrencyCode();
|
||||||
String currencyCode = openOffer.getOffer().getCurrencyCode();
|
int smallestUnitExponent = CurrencyUtil.isTraditionalCurrency(currencyCode) ?
|
||||||
int smallestUnitExponent = CurrencyUtil.isTraditionalCurrency(currencyCode) ?
|
TraditionalMoney.SMALLEST_UNIT_EXPONENT :
|
||||||
TraditionalMoney.SMALLEST_UNIT_EXPONENT :
|
CryptoMoney.SMALLEST_UNIT_EXPONENT;
|
||||||
CryptoMoney.SMALLEST_UNIT_EXPONENT;
|
|
||||||
long triggerPrice = openOffer.getTriggerPrice();
|
|
||||||
|
|
||||||
|
if (openOffer.getState() == OpenOffer.State.AVAILABLE && isTriggered(marketPrice, openOffer)) {
|
||||||
log.info("Market price exceeded the trigger price of the open offer.\n" +
|
log.info("Market price exceeded the trigger price of the open offer.\n" +
|
||||||
"We deactivate the open offer with ID {}.\nCurrency: {};\nOffer direction: {};\n" +
|
"We deactivate the open offer with ID {}.\nCurrency: {};\nOffer direction: {};\n" +
|
||||||
"Market price: {};\nTrigger price: {}",
|
"Market price: {};\nTrigger price: {}",
|
||||||
@ -139,14 +137,26 @@ public class TriggerPriceService {
|
|||||||
currencyCode,
|
currencyCode,
|
||||||
openOffer.getOffer().getDirection(),
|
openOffer.getOffer().getDirection(),
|
||||||
marketPrice.getPrice(),
|
marketPrice.getPrice(),
|
||||||
MathUtils.scaleDownByPowerOf10(triggerPrice, smallestUnitExponent)
|
MathUtils.scaleDownByPowerOf10(openOffer.getTriggerPrice(), smallestUnitExponent)
|
||||||
);
|
);
|
||||||
|
|
||||||
openOfferManager.deactivateOpenOffer(openOffer, () -> {
|
openOfferManager.deactivateOpenOffer(openOffer, true, () -> {
|
||||||
|
}, errorMessage -> {
|
||||||
|
});
|
||||||
|
} else if (openOffer.getState() == OpenOffer.State.DEACTIVATED && openOffer.isDeactivatedByTrigger() && !isTriggered(marketPrice, openOffer)) {
|
||||||
|
log.info("Market price is back within the trigger price of the open offer.\n" +
|
||||||
|
"We reactivate the open offer with ID {}.\nCurrency: {};\nOffer direction: {};\n" +
|
||||||
|
"Market price: {};\nTrigger price: {}",
|
||||||
|
openOffer.getOffer().getShortId(),
|
||||||
|
currencyCode,
|
||||||
|
openOffer.getOffer().getDirection(),
|
||||||
|
marketPrice.getPrice(),
|
||||||
|
MathUtils.scaleDownByPowerOf10(openOffer.getTriggerPrice(), smallestUnitExponent)
|
||||||
|
);
|
||||||
|
|
||||||
|
openOfferManager.activateOpenOffer(openOffer, () -> {
|
||||||
}, errorMessage -> {
|
}, errorMessage -> {
|
||||||
});
|
});
|
||||||
} else if (openOffer.getState() == OpenOffer.State.AVAILABLE) {
|
|
||||||
// TODO: check if open offer's reserve tx is failed or double spend seen
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class OpenOffersDataModel extends ActivatableDataModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onDeactivateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
void onDeactivateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
openOfferManager.deactivateOpenOffer(openOffer, resultHandler, errorMessageHandler);
|
openOfferManager.deactivateOpenOffer(openOffer, false, resultHandler, errorMessageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onRemoveOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
void onRemoveOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
@ -94,7 +94,7 @@ class OpenOffersDataModel extends ActivatableDataModel {
|
|||||||
list.sort((o1, o2) -> o2.getOffer().getDate().compareTo(o1.getOffer().getDate()));
|
list.sort((o1, o2) -> o2.getOffer().getDate().compareTo(o1.getOffer().getDate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean wasTriggered(OpenOffer openOffer) {
|
boolean isTriggered(OpenOffer openOffer) {
|
||||||
return TriggerPriceService.wasTriggered(priceFeedService.getMarketPrice(openOffer.getOffer().getCurrencyCode()), openOffer);
|
return TriggerPriceService.isTriggered(priceFeedService.getMarketPrice(openOffer.getOffer().getCurrencyCode()), openOffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,7 +368,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onActivateOpenOffer(OpenOffer openOffer) {
|
private void onActivateOpenOffer(OpenOffer openOffer) {
|
||||||
if (model.isBootstrappedOrShowPopup() && !model.dataModel.wasTriggered(openOffer)) {
|
if (model.isBootstrappedOrShowPopup() && !model.dataModel.isTriggered(openOffer)) {
|
||||||
model.onActivateOpenOffer(openOffer,
|
model.onActivateOpenOffer(openOffer,
|
||||||
() -> log.debug("Activate offer was successful"),
|
() -> log.debug("Activate offer was successful"),
|
||||||
(message) -> {
|
(message) -> {
|
||||||
@ -720,7 +720,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
|
|||||||
checkBox.setPadding(new Insets(-7, 0, -7, 0));
|
checkBox.setPadding(new Insets(-7, 0, -7, 0));
|
||||||
checkBox.setGraphic(iconView);
|
checkBox.setGraphic(iconView);
|
||||||
}
|
}
|
||||||
checkBox.setDisable(model.dataModel.wasTriggered(openOffer));
|
checkBox.setDisable(model.dataModel.isTriggered(openOffer));
|
||||||
checkBox.setOnAction(event -> {
|
checkBox.setOnAction(event -> {
|
||||||
if (openOffer.isDeactivated()) {
|
if (openOffer.isDeactivated()) {
|
||||||
onActivateOpenOffer(openOffer);
|
onActivateOpenOffer(openOffer);
|
||||||
@ -798,7 +798,7 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
|
|||||||
boolean triggerPriceSet = item.getOpenOffer().getTriggerPrice() > 0;
|
boolean triggerPriceSet = item.getOpenOffer().getTriggerPrice() > 0;
|
||||||
button.setVisible(triggerPriceSet);
|
button.setVisible(triggerPriceSet);
|
||||||
|
|
||||||
if (model.dataModel.wasTriggered(item.getOpenOffer())) {
|
if (model.dataModel.isTriggered(item.getOpenOffer())) {
|
||||||
button.getGraphic().getStyleClass().add("warning");
|
button.getGraphic().getStyleClass().add("warning");
|
||||||
button.setTooltip(new Tooltip(Res.get("openOffer.triggered")));
|
button.setTooltip(new Tooltip(Res.get("openOffer.triggered")));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1421,6 +1421,7 @@ message OpenOffer {
|
|||||||
string reserve_tx_hex = 10;
|
string reserve_tx_hex = 10;
|
||||||
string reserve_tx_key = 11;
|
string reserve_tx_key = 11;
|
||||||
string challenge = 12;
|
string challenge = 12;
|
||||||
|
bool deactivated_by_trigger = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Tradable {
|
message Tradable {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user