mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Accept old trade statistic object
The code didn't handle before the use case of new trade statistic objects created by two old clients. This change make it independent of the cut off date and allows us at a later point to update all trade statistics objects with depositTxId value of null.
This commit is contained in:
parent
cad09aabfd
commit
2ad279f99e
@ -53,6 +53,8 @@ import java.util.Optional;
|
|||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -63,7 +65,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Value
|
@Value
|
||||||
public final class TradeStatistics2 implements ProcessOncePersistableNetworkPayload, PersistableNetworkPayload, PersistableEnvelope, CapabilityRequiringPayload {
|
public final class TradeStatistics2 implements ProcessOncePersistableNetworkPayload, PersistableNetworkPayload, PersistableEnvelope, CapabilityRequiringPayload, Comparable<TradeStatistics2> {
|
||||||
|
|
||||||
public static final String MEDIATOR_ADDRESS = "medAddr";
|
public static final String MEDIATOR_ADDRESS = "medAddr";
|
||||||
public static final String REFUND_AGENT_ADDRESS = "refAddr";
|
public static final String REFUND_AGENT_ADDRESS = "refAddr";
|
||||||
@ -282,10 +284,30 @@ public final class TradeStatistics2 implements ProcessOncePersistableNetworkPayl
|
|||||||
// Since the trade wasn't executed it's better to filter it out to avoid it having an undue influence on the
|
// Since the trade wasn't executed it's better to filter it out to avoid it having an undue influence on the
|
||||||
// BSQ trade stats.
|
// BSQ trade stats.
|
||||||
boolean excludedFailedTrade = offerId.equals("6E5KOI6O-3a06a037-6f03-4bfa-98c2-59f49f73466a-112");
|
boolean excludedFailedTrade = offerId.equals("6E5KOI6O-3a06a037-6f03-4bfa-98c2-59f49f73466a-112");
|
||||||
boolean depositTxIdValid = depositTxId == null || (tradeDate < CUT_OFF_DATE_FOR_DEPOSIT_TX_ID.getTime() && !depositTxId.isEmpty());
|
boolean depositTxIdValid = depositTxId == null || !depositTxId.isEmpty();
|
||||||
return tradeAmount > 0 && tradePrice > 0 && !excludedFailedTrade && depositTxIdValid;
|
return tradeAmount > 0 && tradePrice > 0 && !excludedFailedTrade && depositTxIdValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Can be removed as soon as everyone uses v1.2.6+
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NotNull TradeStatistics2 o) {
|
||||||
|
if (direction.equals(o.direction) &&
|
||||||
|
baseCurrency.equals(o.baseCurrency) &&
|
||||||
|
counterCurrency.equals(o.counterCurrency) &&
|
||||||
|
offerPaymentMethod.equals(o.offerPaymentMethod) &&
|
||||||
|
offerDate == o.offerDate &&
|
||||||
|
offerUseMarketBasedPrice == o.offerUseMarketBasedPrice &&
|
||||||
|
offerAmount == o.offerAmount &&
|
||||||
|
offerMinAmount == o.offerMinAmount &&
|
||||||
|
offerId.equals(o.offerId) &&
|
||||||
|
tradePrice == o.tradePrice &&
|
||||||
|
tradeAmount == o.tradeAmount) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TradeStatistics2{" +
|
return "TradeStatistics2{" +
|
||||||
|
@ -30,6 +30,7 @@ import bisq.common.storage.JsonFileManager;
|
|||||||
import bisq.common.util.Utilities;
|
import bisq.common.util.Utilities;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
@ -39,6 +40,7 @@ import java.io.File;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -93,9 +95,22 @@ public class TradeStatisticsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addToSet(TradeStatistics2 tradeStatistics) {
|
private void addToSet(TradeStatistics2 tradeStatistics) {
|
||||||
|
|
||||||
if (!observableTradeStatisticsSet.contains(tradeStatistics)) {
|
if (!observableTradeStatisticsSet.contains(tradeStatistics)) {
|
||||||
if (observableTradeStatisticsSet.stream().anyMatch(e -> e.getOfferId().equals(tradeStatistics.getOfferId()))) {
|
Optional<TradeStatistics2> duplicate = observableTradeStatisticsSet.stream().filter(
|
||||||
return;
|
e -> e.getOfferId().equals(tradeStatistics.getOfferId())).findAny();
|
||||||
|
|
||||||
|
if (duplicate.isPresent()) {
|
||||||
|
// TODO: Can be removed as soon as everyone uses v1.2.6+
|
||||||
|
// Removes an existing object with a trade id if the new one matches the existing except
|
||||||
|
// for the deposit tx id
|
||||||
|
if (tradeStatistics.getDepositTxId() == null &&
|
||||||
|
tradeStatistics.isValid() &&
|
||||||
|
duplicate.get().compareTo(tradeStatistics) == 0) {
|
||||||
|
observableTradeStatisticsSet.remove(duplicate.get());
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tradeStatistics.isValid()) {
|
if (!tradeStatistics.isValid()) {
|
||||||
|
@ -36,6 +36,7 @@ public class TradeStatistics2Maker {
|
|||||||
|
|
||||||
public static final Property<TradeStatistics2, Date> date = new Property<>();
|
public static final Property<TradeStatistics2, Date> date = new Property<>();
|
||||||
public static final Property<TradeStatistics2, String> depositTxId = new Property<>();
|
public static final Property<TradeStatistics2, String> depositTxId = new Property<>();
|
||||||
|
public static final Property<TradeStatistics2, Coin> tradeAmount = new Property<>();
|
||||||
|
|
||||||
public static final Instantiator<TradeStatistics2> TradeStatistic2 = lookup -> {
|
public static final Instantiator<TradeStatistics2> TradeStatistic2 = lookup -> {
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
@ -81,7 +82,7 @@ public class TradeStatistics2Maker {
|
|||||||
null,
|
null,
|
||||||
0),
|
0),
|
||||||
Price.valueOf("BTC", 100000L),
|
Price.valueOf("BTC", 100000L),
|
||||||
Coin.SATOSHI,
|
lookup.valueOf(tradeAmount, Coin.SATOSHI),
|
||||||
lookup.valueOf(date, new Date(calendar.getTimeInMillis())),
|
lookup.valueOf(date, new Date(calendar.getTimeInMillis())),
|
||||||
lookup.valueOf(depositTxId, "123456"),
|
lookup.valueOf(depositTxId, "123456"),
|
||||||
Collections.emptyMap());
|
Collections.emptyMap());
|
||||||
|
@ -17,24 +17,19 @@
|
|||||||
|
|
||||||
package bisq.core.trade.statistics;
|
package bisq.core.trade.statistics;
|
||||||
|
|
||||||
import org.apache.commons.lang3.time.DateUtils;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static bisq.core.trade.statistics.TradeStatistics2Maker.date;
|
|
||||||
import static bisq.core.trade.statistics.TradeStatistics2Maker.dayZeroTrade;
|
import static bisq.core.trade.statistics.TradeStatistics2Maker.dayZeroTrade;
|
||||||
import static bisq.core.trade.statistics.TradeStatistics2Maker.depositTxId;
|
import static bisq.core.trade.statistics.TradeStatistics2Maker.depositTxId;
|
||||||
import static com.natpryce.makeiteasy.MakeItEasy.make;
|
import static com.natpryce.makeiteasy.MakeItEasy.make;
|
||||||
import static com.natpryce.makeiteasy.MakeItEasy.with;
|
|
||||||
import static com.natpryce.makeiteasy.MakeItEasy.withNull;
|
import static com.natpryce.makeiteasy.MakeItEasy.withNull;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
public class TradeStatistics2Test {
|
public class TradeStatistics2Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isValid_WithDepositTxIdBeforeCutOffDate() {
|
public void isValid_WithDepositTxId() {
|
||||||
|
|
||||||
TradeStatistics2 tradeStatistic = make(dayZeroTrade);
|
TradeStatistics2 tradeStatistic = make(dayZeroTrade);
|
||||||
|
|
||||||
@ -42,20 +37,8 @@ public class TradeStatistics2Test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isValid_Not_WithDepositTxIdAfterCutOffDate() {
|
public void isValid_WithEmptyDepositTxId() {
|
||||||
TradeStatistics2 tradeStatistic = make(dayZeroTrade.but(
|
TradeStatistics2 tradeStatistic = make(dayZeroTrade.but(withNull(depositTxId)));
|
||||||
with(date, DateUtils.addDays(TradeStatistics2.CUT_OFF_DATE_FOR_DEPOSIT_TX_ID, 1))
|
|
||||||
));
|
|
||||||
|
|
||||||
assertFalse(tradeStatistic.isValid());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isValid_WithEmptyDepositTxIdAfterCutOffDate() {
|
|
||||||
TradeStatistics2 tradeStatistic = make(dayZeroTrade.but(
|
|
||||||
with(date, DateUtils.addDays(TradeStatistics2.CUT_OFF_DATE_FOR_DEPOSIT_TX_ID, 1)),
|
|
||||||
withNull(depositTxId)
|
|
||||||
));
|
|
||||||
|
|
||||||
assertTrue(tradeStatistic.isValid());
|
assertTrue(tradeStatistic.isValid());
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Bisq.
|
||||||
|
*
|
||||||
|
* Bisq is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package bisq.core.trade.statistics;
|
||||||
|
|
||||||
|
import bisq.core.provider.price.PriceFeedService;
|
||||||
|
|
||||||
|
import bisq.network.p2p.P2PService;
|
||||||
|
import bisq.network.p2p.storage.P2PDataStorage;
|
||||||
|
import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreListener;
|
||||||
|
import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService;
|
||||||
|
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static bisq.core.trade.statistics.TradeStatistics2Maker.dayZeroTrade;
|
||||||
|
import static bisq.core.trade.statistics.TradeStatistics2Maker.depositTxId;
|
||||||
|
import static bisq.core.trade.statistics.TradeStatistics2Maker.tradeAmount;
|
||||||
|
import static com.natpryce.makeiteasy.MakeItEasy.make;
|
||||||
|
import static com.natpryce.makeiteasy.MakeItEasy.with;
|
||||||
|
import static com.natpryce.makeiteasy.MakeItEasy.withNull;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
public class TradeStatisticsManagerTest {
|
||||||
|
|
||||||
|
private TradeStatisticsManager manager;
|
||||||
|
private TradeStatistics2 tradeWithNullDepositTxId;
|
||||||
|
private ArgumentCaptor<AppendOnlyDataStoreListener> listenerArgumentCaptor;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void prepareMocksAndObjects() {
|
||||||
|
P2PService p2PService = mock(P2PService.class);
|
||||||
|
P2PDataStorage p2PDataStorage = mock(P2PDataStorage.class);
|
||||||
|
File storageDir = mock(File.class);
|
||||||
|
TradeStatistics2StorageService tradeStatistics2StorageService = mock(TradeStatistics2StorageService.class);
|
||||||
|
PriceFeedService priceFeedService = mock(PriceFeedService.class);
|
||||||
|
|
||||||
|
AppendOnlyDataStoreService appendOnlyDataStoreService = mock(AppendOnlyDataStoreService.class);
|
||||||
|
when(p2PService.getP2PDataStorage()).thenReturn(p2PDataStorage);
|
||||||
|
|
||||||
|
manager = new TradeStatisticsManager(p2PService, priceFeedService,
|
||||||
|
tradeStatistics2StorageService, appendOnlyDataStoreService, storageDir, false);
|
||||||
|
|
||||||
|
tradeWithNullDepositTxId = make(dayZeroTrade.but(withNull(depositTxId)));
|
||||||
|
|
||||||
|
manager.onAllServicesInitialized();
|
||||||
|
listenerArgumentCaptor = ArgumentCaptor.forClass(AppendOnlyDataStoreListener.class);
|
||||||
|
verify(p2PDataStorage).addAppendOnlyDataStoreListener(listenerArgumentCaptor.capture());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addToSet_ObjectWithNullDepositTxId() {
|
||||||
|
listenerArgumentCaptor.getValue().onAdded(tradeWithNullDepositTxId);
|
||||||
|
assertTrue(manager.getObservableTradeStatisticsSet().contains(tradeWithNullDepositTxId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addToSet_RemoveExistingObjectIfObjectWithNullDepositTxIdIsAdded() {
|
||||||
|
TradeStatistics2 tradeWithDepositTxId = make(dayZeroTrade);
|
||||||
|
|
||||||
|
listenerArgumentCaptor.getValue().onAdded(tradeWithDepositTxId);
|
||||||
|
listenerArgumentCaptor.getValue().onAdded(tradeWithNullDepositTxId);
|
||||||
|
|
||||||
|
assertFalse(manager.getObservableTradeStatisticsSet().contains(tradeWithDepositTxId));
|
||||||
|
assertTrue(manager.getObservableTradeStatisticsSet().contains(tradeWithNullDepositTxId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addToSet_NotRemoveExistingObjectIfObjectsNotEqual() {
|
||||||
|
TradeStatistics2 tradeWithDepositTxId = make(dayZeroTrade.but(with(tradeAmount, Coin.FIFTY_COINS)));
|
||||||
|
|
||||||
|
listenerArgumentCaptor.getValue().onAdded(tradeWithDepositTxId);
|
||||||
|
listenerArgumentCaptor.getValue().onAdded(tradeWithNullDepositTxId);
|
||||||
|
|
||||||
|
assertTrue(manager.getObservableTradeStatisticsSet().contains(tradeWithDepositTxId));
|
||||||
|
assertFalse(manager.getObservableTradeStatisticsSet().contains(tradeWithNullDepositTxId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void addToSet_IgnoreObjectIfObjectWithNullDepositTxIdAlreadyExists() {
|
||||||
|
TradeStatistics2 tradeWithDepositTxId = make(dayZeroTrade);
|
||||||
|
|
||||||
|
listenerArgumentCaptor.getValue().onAdded(tradeWithNullDepositTxId);
|
||||||
|
listenerArgumentCaptor.getValue().onAdded(tradeWithDepositTxId);
|
||||||
|
|
||||||
|
assertTrue(manager.getObservableTradeStatisticsSet().contains(tradeWithNullDepositTxId));
|
||||||
|
assertFalse(manager.getObservableTradeStatisticsSet().contains(tradeWithDepositTxId));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user