Skip to content

Commit 82194c6

Browse files
committed
improve updating the trade period state
1 parent 87ce137 commit 82194c6

File tree

3 files changed

+87
-77
lines changed

3 files changed

+87
-77
lines changed

core/src/main/java/haveno/core/trade/Trade.java

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2273,6 +2273,38 @@ public Volume getVolume() {
22732273
}
22742274
}
22752275

2276+
public void maybeUpdateTradePeriod() {
2277+
if (startTime > 0) return; // already set
2278+
if (getTakeOfferDate() == null) return; // trade not started yet
2279+
if (!isDepositsFinalized()) return; // deposits not finalized yet
2280+
2281+
long now = System.currentTimeMillis();
2282+
long tradeTime = getTakeOfferDate().getTime();
2283+
MoneroDaemon monerod = xmrWalletService.getMonerod();
2284+
if (monerod == null) throw new RuntimeException("Cannot set start time for trade " + getId() + " because it has no connection to monerod");
2285+
2286+
// get finalize time of last deposit tx
2287+
long finalizeHeight = getDepositsFinalizedHeight();
2288+
long finalizeTime = monerod.getBlockByHeight(finalizeHeight).getTimestamp() * 1000;
2289+
2290+
// If block date is in future (Date in blocks can be off by +/- 2 hours) we use our current date.
2291+
// If block date is earlier than our trade date we use our trade date.
2292+
if (finalizeTime > now)
2293+
startTime = now;
2294+
else
2295+
startTime = Math.max(finalizeTime, tradeTime);
2296+
2297+
log.debug("We set the start for the trade period to {}. Trade started at: {}. Block got mined at: {}",
2298+
new Date(startTime), new Date(tradeTime), new Date(finalizeTime));
2299+
}
2300+
2301+
private long getDepositsFinalizedHeight() {
2302+
MoneroTxWallet makerDepositTx = getMakerDepositTx();
2303+
MoneroTxWallet takerDepositTx = getTakerDepositTx();
2304+
if (makerDepositTx == null || (takerDepositTx == null && !hasBuyerAsTakerWithoutDeposit())) throw new RuntimeException("Cannot get finalized height for trade " + getId() + " because its deposit tx is null. Is client connected to a daemon?");
2305+
return Math.max(makerDepositTx.getHeight() + NUM_BLOCKS_DEPOSITS_FINALIZED - 1, hasBuyerAsTakerWithoutDeposit() ? 0l : takerDepositTx.getHeight() + NUM_BLOCKS_DEPOSITS_FINALIZED - 1);
2306+
}
2307+
22762308
public long getMaxTradePeriod() {
22772309
return getOffer().getPaymentMethod().getMaxTradePeriod();
22782310
}
@@ -2294,38 +2326,7 @@ public Date getStartDate() {
22942326
* Returns the current time until the deposits are finalized.
22952327
*/
22962328
private long getEffectiveStartTime() {
2297-
if (startTime > 0) return startTime;
2298-
if (getTakeOfferDate() == null) return System.currentTimeMillis(); // trade not started yet
2299-
if (isDepositsFinalized()) {
2300-
setStartTimeFromFinalizedTxs(); // save to model
2301-
return startTime;
2302-
} else {
2303-
return System.currentTimeMillis();
2304-
}
2305-
}
2306-
2307-
private void setStartTimeFromFinalizedTxs() {
2308-
long now = System.currentTimeMillis();
2309-
final long tradeTime = getTakeOfferDate().getTime();
2310-
MoneroDaemon monerod = xmrWalletService.getMonerod();
2311-
MoneroTxWallet makerDepositTx = getMakerDepositTx();
2312-
MoneroTxWallet takerDepositTx = getTakerDepositTx();
2313-
if (monerod == null) throw new RuntimeException("Cannot set start time for trade " + getId() + " because it has no connection to monerod");
2314-
if (makerDepositTx == null || (takerDepositTx == null && !hasBuyerAsTakerWithoutDeposit())) throw new RuntimeException("Cannot set start time for trade " + getId() + " because its finalized deposit tx is null. Is client connected to a daemon?");
2315-
2316-
// get finalize time of last deposit tx
2317-
long finalizeHeight = Math.max(makerDepositTx.getHeight() + NUM_BLOCKS_DEPOSITS_FINALIZED - 1, hasBuyerAsTakerWithoutDeposit() ? 0l : takerDepositTx.getHeight() + NUM_BLOCKS_DEPOSITS_FINALIZED - 1);
2318-
long finalizeTime = monerod.getBlockByHeight(finalizeHeight).getTimestamp() * 1000;
2319-
2320-
// If block date is in future (Date in blocks can be off by +/- 2 hours) we use our current date.
2321-
// If block date is earlier than our trade date we use our trade date.
2322-
if (finalizeTime > now)
2323-
startTime = now;
2324-
else
2325-
startTime = Math.max(finalizeTime, tradeTime);
2326-
2327-
log.debug("We set the start for the trade period to {}. Trade started at: {}. Block got mined at: {}",
2328-
new Date(startTime), new Date(tradeTime), new Date(finalizeTime));
2329+
return startTime > 0 ? startTime : System.currentTimeMillis();
23292330
}
23302331

23312332
public boolean hasFailed() {
@@ -3250,7 +3251,7 @@ private void setStateDepositsUnlocked() {
32503251
private void setStateDepositsFinalized() {
32513252
if (!isDepositsFinalized()) {
32523253
setStateIfValidTransitionTo(State.DEPOSIT_TXS_FINALIZED_IN_BLOCKCHAIN);
3253-
setStartTimeFromFinalizedTxs();
3254+
ThreadUtils.submitToPool(() -> maybeUpdateTradePeriod());
32543255
}
32553256
}
32563257

core/src/main/java/haveno/core/trade/TradeManager.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,11 +1044,13 @@ public void onMinuteTick() {
10441044
});
10451045
}
10461046

1047+
// TODO: could use monerod.getBlocksByHeight() to more efficiently update trade period state
10471048
private void updateTradePeriodState() {
10481049
if (isShutDownStarted) return;
1049-
synchronized (tradableList.getList()) {
1050-
for (Trade trade : tradableList.getList()) {
1051-
if (!trade.isInitialized() || trade.isPayoutPublished()) continue;
1050+
for (Trade trade : getOpenTrades()) {
1051+
if (!trade.isInitialized() || trade.isPayoutPublished()) continue;
1052+
try {
1053+
trade.maybeUpdateTradePeriod();
10521054
Date maxTradePeriodDate = trade.getMaxTradePeriodDate();
10531055
Date halfTradePeriodDate = trade.getHalfTradePeriodDate();
10541056
if (maxTradePeriodDate != null && halfTradePeriodDate != null) {
@@ -1061,6 +1063,9 @@ private void updateTradePeriodState() {
10611063
requestPersistence();
10621064
}
10631065
}
1066+
} catch (Exception e) {
1067+
log.warn("Error updating trade period state for {} {}: {}", trade.getClass().getSimpleName(), trade.getShortId(), e.getMessage(), e);
1068+
continue;
10641069
}
10651070
}
10661071
}

desktop/src/main/java/haveno/desktop/main/MainViewModel.java

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package haveno.desktop.main;
1919

2020
import com.google.inject.Inject;
21+
22+
import haveno.common.ThreadUtils;
2123
import haveno.common.Timer;
2224
import haveno.common.UserThread;
2325
import haveno.common.app.DevEnv;
@@ -219,47 +221,49 @@ public void onSetupComplete() {
219221
(a, b) -> a && b);
220222
tradesAndUIReady.subscribe((observable, oldValue, newValue) -> {
221223
if (newValue) {
222-
tradeManager.applyTradePeriodState();
223-
224-
tradeManager.getOpenTrades().forEach(trade -> {
225-
226-
// check initialization error
227-
if (trade.getInitError() != null) {
228-
new Popup().warning("Error initializing trade" + " " + trade.getShortId() + "\n\n" +
229-
trade.getInitError().getMessage())
230-
.show();
231-
return;
232-
}
233-
234-
// check trade period
235-
Date maxTradePeriodDate = trade.getMaxTradePeriodDate();
236-
String key;
237-
switch (trade.getPeriodState()) {
238-
case FIRST_HALF:
239-
break;
240-
case SECOND_HALF:
241-
key = "displayHalfTradePeriodOver" + trade.getId();
242-
if (DontShowAgainLookup.showAgain(key)) {
243-
DontShowAgainLookup.dontShowAgain(key, true);
244-
if (trade instanceof ArbitratorTrade) break; // skip popup if arbitrator trade
245-
new Popup().warning(Res.get("popup.warning.tradePeriod.halfReached",
246-
trade.getShortId(),
247-
DisplayUtils.formatDateTime(maxTradePeriodDate)))
248-
.show();
249-
}
250-
break;
251-
case TRADE_PERIOD_OVER:
252-
key = "displayTradePeriodOver" + trade.getId();
253-
if (DontShowAgainLookup.showAgain(key)) {
254-
DontShowAgainLookup.dontShowAgain(key, true);
255-
if (trade instanceof ArbitratorTrade) break; // skip popup if arbitrator trade
256-
new Popup().warning(Res.get("popup.warning.tradePeriod.ended",
257-
trade.getShortId(),
258-
DisplayUtils.formatDateTime(maxTradePeriodDate)))
259-
.show();
260-
}
261-
break;
262-
}
224+
ThreadUtils.submitToPool(() -> {
225+
tradeManager.applyTradePeriodState();
226+
227+
tradeManager.getOpenTrades().forEach(trade -> {
228+
229+
// check initialization error
230+
if (trade.getInitError() != null) {
231+
new Popup().warning("Error initializing trade" + " " + trade.getShortId() + "\n\n" +
232+
trade.getInitError().getMessage())
233+
.show();
234+
return;
235+
}
236+
237+
// check trade period
238+
Date maxTradePeriodDate = trade.getMaxTradePeriodDate();
239+
String key;
240+
switch (trade.getPeriodState()) {
241+
case FIRST_HALF:
242+
break;
243+
case SECOND_HALF:
244+
key = "displayHalfTradePeriodOver" + trade.getId();
245+
if (DontShowAgainLookup.showAgain(key)) {
246+
DontShowAgainLookup.dontShowAgain(key, true);
247+
if (trade instanceof ArbitratorTrade) break; // skip popup if arbitrator trade
248+
new Popup().warning(Res.get("popup.warning.tradePeriod.halfReached",
249+
trade.getShortId(),
250+
DisplayUtils.formatDateTime(maxTradePeriodDate)))
251+
.show();
252+
}
253+
break;
254+
case TRADE_PERIOD_OVER:
255+
key = "displayTradePeriodOver" + trade.getId();
256+
if (DontShowAgainLookup.showAgain(key)) {
257+
DontShowAgainLookup.dontShowAgain(key, true);
258+
if (trade instanceof ArbitratorTrade) break; // skip popup if arbitrator trade
259+
new Popup().warning(Res.get("popup.warning.tradePeriod.ended",
260+
trade.getShortId(),
261+
DisplayUtils.formatDateTime(maxTradePeriodDate)))
262+
.show();
263+
}
264+
break;
265+
}
266+
});
263267
});
264268
}
265269
});

0 commit comments

Comments
 (0)