diff --git a/core/src/main/java/haveno/core/trade/statistics/TradeStatisticsManager.java b/core/src/main/java/haveno/core/trade/statistics/TradeStatisticsManager.java index d5aa42bb..4ec3a2d5 100644 --- a/core/src/main/java/haveno/core/trade/statistics/TradeStatisticsManager.java +++ b/core/src/main/java/haveno/core/trade/statistics/TradeStatisticsManager.java @@ -35,6 +35,7 @@ import haveno.network.p2p.storage.persistence.AppendOnlyDataStoreService; import java.io.File; import java.time.Instant; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -98,6 +99,11 @@ public class TradeStatisticsManager { .map(e -> (TradeStatistics3) e) .filter(TradeStatistics3::isValid) .collect(Collectors.toSet()); + + + // remove duplicates in early trades due to bug + deduplicateEarlyTradeStatistics(set); + synchronized (observableTradeStatisticsSet) { observableTradeStatisticsSet.addAll(set); priceFeedService.applyLatestHavenoMarketPrice(observableTradeStatisticsSet); @@ -105,6 +111,37 @@ public class TradeStatisticsManager { maybeDumpStatistics(); } + private void deduplicateEarlyTradeStatistics(Set set) { + + // collect trades before May 18, 2024 + Set tradesBeforeMay18_24 = set.stream() + .filter(e -> e.getDate().toInstant().isBefore(Instant.parse("2024-05-18T00:00:00Z"))) + .collect(Collectors.toSet()); + + // collect duplicated trades + Set duplicated = new HashSet(); + Set deduplicated = new HashSet(); + for (TradeStatistics3 tradeStatistics : tradesBeforeMay18_24) { + if (hasLenientDuplicate(tradeStatistics, deduplicated)) duplicated.add(tradeStatistics); + else deduplicated.add(tradeStatistics); + } + + // remove duplicated trades + set.removeAll(duplicated); + } + + private boolean hasLenientDuplicate(TradeStatistics3 tradeStatistics, Set set) { + return set.stream().anyMatch(e -> isLenientDuplicate(tradeStatistics, e)); + } + + private boolean isLenientDuplicate(TradeStatistics3 tradeStatistics1, TradeStatistics3 tradeStatistics2) { + boolean isWithin2Minutes = Math.abs(tradeStatistics1.getDate().getTime() - tradeStatistics2.getDate().getTime()) < 120000; + return isWithin2Minutes && + tradeStatistics1.getCurrency().equals(tradeStatistics2.getCurrency()) && + tradeStatistics1.getAmount() == tradeStatistics2.getAmount() && + tradeStatistics1.getPrice() == tradeStatistics2.getPrice(); + } + public ObservableSet getObservableTradeStatisticsSet() { return observableTradeStatisticsSet; }