Add publish statistics task for taker if offerer uses old version

This commit is contained in:
Manfred Karrer 2016-07-25 16:13:26 +02:00
parent 38cc71c6aa
commit ada3bd4dc3
17 changed files with 213 additions and 49 deletions

View file

@ -10,12 +10,14 @@ import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.ExchangeRate; import org.bitcoinj.utils.ExchangeRate;
import org.bitcoinj.utils.Fiat; import org.bitcoinj.utils.Fiat;
import javax.annotation.concurrent.Immutable;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Immutable
public final class TradeStatistics implements StoragePayload, CapabilityRequiringPayload { public final class TradeStatistics implements StoragePayload, CapabilityRequiringPayload {
@JsonExclude @JsonExclude
private static final long serialVersionUID = Version.P2P_NETWORK_VERSION; private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
@ -86,9 +88,72 @@ public final class TradeStatistics implements StoragePayload, CapabilityRequirin
} }
public Fiat getTradeVolume() { public Fiat getTradeVolume() {
if (getTradeAmount() != null && getTradePrice() != null) return new ExchangeRate(getTradePrice()).coinToFiat(getTradeAmount());
return new ExchangeRate(getTradePrice()).coinToFiat(getTradeAmount()); }
else
return null; // We don't include the pubKeyRing as both traders might publish it if the offerer uses an old
// version and update later (taker publishes first, then later offerer)
// We also don't include the trade date as that is set locally and different for offerer and taker
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof TradeStatistics)) return false;
TradeStatistics that = (TradeStatistics) o;
if (tradePrice != that.tradePrice) return false;
if (tradeAmount != that.tradeAmount) return false;
if (offerDate != that.offerDate) return false;
if (useMarketBasedPrice != that.useMarketBasedPrice) return false;
if (Double.compare(that.marketPriceMargin, marketPriceMargin) != 0) return false;
if (offerAmount != that.offerAmount) return false;
if (offerMinAmount != that.offerMinAmount) return false;
if (currency != null ? !currency.equals(that.currency) : that.currency != null) return false;
if (direction != that.direction) return false;
if (paymentMethod != null ? !paymentMethod.equals(that.paymentMethod) : that.paymentMethod != null)
return false;
if (offerId != null ? !offerId.equals(that.offerId) : that.offerId != null) return false;
return !(depositTxId != null ? !depositTxId.equals(that.depositTxId) : that.depositTxId != null);
}
@Override
public int hashCode() {
int result;
long temp;
result = currency != null ? currency.hashCode() : 0;
result = 31 * result + (direction != null ? direction.hashCode() : 0);
result = 31 * result + (int) (tradePrice ^ (tradePrice >>> 32));
result = 31 * result + (int) (tradeAmount ^ (tradeAmount >>> 32));
result = 31 * result + (paymentMethod != null ? paymentMethod.hashCode() : 0);
result = 31 * result + (int) (offerDate ^ (offerDate >>> 32));
result = 31 * result + (useMarketBasedPrice ? 1 : 0);
temp = Double.doubleToLongBits(marketPriceMargin);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (int) (offerAmount ^ (offerAmount >>> 32));
result = 31 * result + (int) (offerMinAmount ^ (offerMinAmount >>> 32));
result = 31 * result + (offerId != null ? offerId.hashCode() : 0);
result = 31 * result + (depositTxId != null ? depositTxId.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "TradeStatistics{" +
"currency='" + currency + '\'' +
", direction=" + direction +
", tradePrice=" + tradePrice +
", tradeAmount=" + tradeAmount +
", tradeDate=" + tradeDate +
", paymentMethod='" + paymentMethod + '\'' +
", offerDate=" + offerDate +
", useMarketBasedPrice=" + useMarketBasedPrice +
", marketPriceMargin=" + marketPriceMargin +
", offerAmount=" + offerAmount +
", offerMinAmount=" + offerMinAmount +
", offerId='" + offerId + '\'' +
", depositTxId='" + depositTxId + '\'' +
", pubKeyRing=" + pubKeyRing +
'}';
} }
} }

View file

@ -38,7 +38,7 @@ public class TradeStatisticsManager {
HashSet<TradeStatistics> persisted = storage.initAndGetPersistedWithFileName("TradeStatistics"); HashSet<TradeStatistics> persisted = storage.initAndGetPersistedWithFileName("TradeStatistics");
if (persisted != null) if (persisted != null)
observableTradeStatisticsSet = FXCollections.observableSet(persisted); persisted.stream().forEach(e -> add(e));
p2PService.addHashSetChangedListener(new HashMapChangedListener() { p2PService.addHashSetChangedListener(new HashMapChangedListener() {
@Override @Override
@ -57,23 +57,28 @@ public class TradeStatisticsManager {
} }
public void add(TradeStatistics tradeStatistics) { public void add(TradeStatistics tradeStatistics) {
if (!observableTradeStatisticsSet.contains(tradeStatistics)) { if (!tradeStatisticsSet.contains(tradeStatistics)) {
observableTradeStatisticsSet.add(tradeStatistics); boolean itemAlreadyAdded = tradeStatisticsSet.stream().filter(e -> (e.offerId.equals(tradeStatistics.offerId))).findAny().isPresent();
tradeStatisticsSet.add(tradeStatistics); if (!itemAlreadyAdded) {
storage.queueUpForSave(tradeStatisticsSet, 2000); tradeStatisticsSet.add(tradeStatistics);
observableTradeStatisticsSet.add(tradeStatistics);
storage.queueUpForSave(tradeStatisticsSet, 2000);
if (dumpStatistics) { if (dumpStatistics) {
// We store the statistics as json so it is easy for further processing (e.g. for web based services) // We store the statistics as json so it is easy for further processing (e.g. for web based services)
// TODO This is just a quick solution for storing to one file. // TODO This is just a quick solution for storing to one file.
// 1 statistic entry has 500 bytes as json. // 1 statistic entry has 500 bytes as json.
// Need a more scalable solution later when we get more volume. // Need a more scalable solution later when we get more volume.
// The flag will only be activated by dedicated nodes, so it should not be too critical for the moment, but needs to // The flag will only be activated by dedicated nodes, so it should not be too critical for the moment, but needs to
// get improved. Maybe a LevelDB like DB...? Could be impl. in a headless version only. // get improved. Maybe a LevelDB like DB...? Could be impl. in a headless version only.
List<TradeStatistics> list = tradeStatisticsSet.stream().collect(Collectors.toList()); List<TradeStatistics> list = tradeStatisticsSet.stream().collect(Collectors.toList());
list.sort((o1, o2) -> (o1.tradeDate < o2.tradeDate ? 1 : (o1.tradeDate == o2.tradeDate ? 0 : -1))); list.sort((o1, o2) -> (o1.tradeDate < o2.tradeDate ? 1 : (o1.tradeDate == o2.tradeDate ? 0 : -1)));
TradeStatistics[] array = new TradeStatistics[tradeStatisticsSet.size()]; TradeStatistics[] array = new TradeStatistics[tradeStatisticsSet.size()];
list.toArray(array); list.toArray(array);
jsonStorage.queueUpForSave(Utilities.objectToJson(array), 5_000); jsonStorage.queueUpForSave(Utilities.objectToJson(array), 5_000);
}
} else {
log.error("We have already an item with the same offer ID. That might happen if both the offerer and the taker published the tradeStatistics");
} }
} }
} }

View file

@ -31,7 +31,6 @@ import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.protocol.trade.tasks.buyer.*; import io.bitsquare.trade.protocol.trade.tasks.buyer.*;
import io.bitsquare.trade.protocol.trade.tasks.offerer.*; import io.bitsquare.trade.protocol.trade.tasks.offerer.*;
import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime; import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime;
import io.bitsquare.trade.protocol.trade.tasks.shared.PublishTradeStatistics;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View file

@ -122,7 +122,8 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
VerifyOffererAccount.class, VerifyOffererAccount.class,
VerifyAndSignContract.class, VerifyAndSignContract.class,
SignAndPublishDepositTxAsBuyer.class, SignAndPublishDepositTxAsBuyer.class,
SendDepositTxPublishedMessage.class SendDepositTxPublishedMessage.class,
PublishTradeStatistics.class
); );
taskRunner.run(); taskRunner.run();
} }

View file

@ -29,7 +29,6 @@ import io.bitsquare.trade.protocol.trade.messages.*;
import io.bitsquare.trade.protocol.trade.tasks.offerer.*; import io.bitsquare.trade.protocol.trade.tasks.offerer.*;
import io.bitsquare.trade.protocol.trade.tasks.seller.*; import io.bitsquare.trade.protocol.trade.tasks.seller.*;
import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime; import io.bitsquare.trade.protocol.trade.tasks.shared.BroadcastAfterLockTime;
import io.bitsquare.trade.protocol.trade.tasks.shared.PublishTradeStatistics;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;

View file

@ -132,7 +132,8 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
VerifyOffererAccount.class, VerifyOffererAccount.class,
VerifyAndSignContract.class, VerifyAndSignContract.class,
SignAndPublishDepositTxAsSeller.class, SignAndPublishDepositTxAsSeller.class,
SendDepositTxPublishedMessage.class SendDepositTxPublishedMessage.class,
PublishTradeStatistics.class
); );
taskRunner.run(); taskRunner.run();
} }

View file

@ -15,7 +15,7 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>. * along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.bitsquare.trade.protocol.trade.tasks.shared; package io.bitsquare.trade.protocol.trade.tasks.offerer;
import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
@ -35,6 +35,7 @@ public class PublishTradeStatistics extends TradeTask {
protected void run() { protected void run() {
try { try {
runInterceptHook(); runInterceptHook();
// Offerer publishes directly
TradeStatistics tradeStatistics = new TradeStatistics(trade.getOffer(), TradeStatistics tradeStatistics = new TradeStatistics(trade.getOffer(),
trade.getTradePrice(), trade.getTradePrice(),
trade.getTradeAmount(), trade.getTradeAmount(),

View file

@ -0,0 +1,78 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare 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.
*
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol.trade.tasks.taker;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeStatistics;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
public class PublishTradeStatistics extends TradeTask {
private static final Logger log = LoggerFactory.getLogger(PublishTradeStatistics.class);
public PublishTradeStatistics(TaskRunner taskHandler, Trade trade) {
super(taskHandler, trade);
}
@Override
protected void run() {
try {
runInterceptHook();
// taker only publishes if the offerer uses an old version
processModel.getP2PService().getNetworkNode().getConfirmedConnections()
.stream()
.filter(c -> c.getPeersNodeAddressOptional().isPresent() && c.getPeersNodeAddressOptional().get().equals(trade.getTradingPeerNodeAddress()))
.findAny()
.ifPresent(c -> {
TradeStatistics tradeStatistics = new TradeStatistics(trade.getOffer(),
trade.getTradePrice(),
trade.getTradeAmount(),
trade.getDate(),
(trade.getDepositTx() != null ? trade.getDepositTx().getHashAsString() : ""),
processModel.getPubKeyRing());
final List<Integer> requiredCapabilities = tradeStatistics.getRequiredCapabilities();
final List<Integer> supportedCapabilities = c.getSupportedCapabilities();
boolean matches = false;
if (supportedCapabilities != null) {
for (int messageCapability : requiredCapabilities) {
for (int connectionCapability : supportedCapabilities) {
if (messageCapability == connectionCapability) {
matches = true;
break;
}
}
}
}
if (!matches) {
log.error("We publish tradeStatistics because the offerer does use an old version.");
processModel.getP2PService().addData(tradeStatistics, true);
} else {
log.error("We do not publish tradeStatistics because the offerer support the capabilities.");
}
});
complete();
} catch (Throwable t) {
failed(t);
}
}
}

View file

@ -111,7 +111,8 @@ public final class Preferences implements Persistable {
private boolean autoSelectArbitrators = true; private boolean autoSelectArbitrators = true;
private final Map<String, Boolean> dontShowAgainMap; private final Map<String, Boolean> dontShowAgainMap;
private boolean tacAccepted; private boolean tacAccepted;
private boolean useTorForBitcoinJ = true; //TODO we set it to false for now as it is not ready yet
private boolean useTorForBitcoinJ = false;
private boolean showOwnOffersInOfferBook = true; private boolean showOwnOffersInOfferBook = true;
private Locale preferredLocale; private Locale preferredLocale;
private TradeCurrency preferredTradeCurrency; private TradeCurrency preferredTradeCurrency;

View file

@ -26,6 +26,6 @@
xmlns:fx="http://javafx.com/fxml"> xmlns:fx="http://javafx.com/fxml">
<Tab fx:id="chartsTab" text="Offer book" closable="false"/> <Tab fx:id="chartsTab" text="Offer book" closable="false"/>
<Tab fx:id="tradesTab" text="Trades" closable="false"/>
<Tab fx:id="statisticsTab" text="Spreads" closable="false"/> <Tab fx:id="statisticsTab" text="Spreads" closable="false"/>
<Tab fx:id="tradesTab" text="Trades" closable="false"/>
</TabPane> </TabPane>

View file

@ -28,7 +28,6 @@ public class CandleData {
public final long accumulatedVolume; public final long accumulatedVolume;
public final boolean isBullish; public final boolean isBullish;
// public CandleStickExtraValues(double close, double high, double low, double average, double volume) {
public CandleData(long tick, long open, long close, long high, long low, long average, long accumulatedAmount, long accumulatedVolume, boolean isBullish) { public CandleData(long tick, long open, long close, long high, long low, long average, long accumulatedAmount, long accumulatedVolume, boolean isBullish) {
this.tick = tick; this.tick = tick;
this.open = open; this.open = open;

View file

@ -190,23 +190,29 @@ public class CandleStickChart extends XYChart<Number, Number> {
for (int j = 0; j < series.getData().size(); j++) { for (int j = 0; j < series.getData().size(); j++) {
XYChart.Data item = series.getData().get(j); XYChart.Data item = series.getData().get(j);
Node candle = createCandle(seriesIndex, item, j); Node candle = createCandle(seriesIndex, item, j);
getPlotChildren().add(candle);
if (shouldAnimate()) { if (!getPlotChildren().contains(candle)) {
candle.setOpacity(0); getPlotChildren().add(candle);
FadeTransition ft = new FadeTransition(Duration.millis(500), candle); if (shouldAnimate()) {
ft.setToValue(1); candle.setOpacity(0);
ft.play(); FadeTransition ft = new FadeTransition(Duration.millis(500), candle);
ft.setToValue(1);
ft.play();
}
} }
} }
Path seriesPath = new Path(); Path seriesPath = new Path();
seriesPath.getStyleClass().setAll("candlestick-average-line", "series" + seriesIndex); seriesPath.getStyleClass().setAll("candlestick-average-line", "series" + seriesIndex);
series.setNode(seriesPath); series.setNode(seriesPath);
getPlotChildren().add(seriesPath);
if (shouldAnimate()) { if (!getPlotChildren().contains(seriesPath)) {
seriesPath.setOpacity(0); getPlotChildren().add(seriesPath);
FadeTransition ft = new FadeTransition(Duration.millis(500), seriesPath); if (shouldAnimate()) {
ft.setToValue(1); seriesPath.setOpacity(0);
ft.play(); FadeTransition ft = new FadeTransition(Duration.millis(500), seriesPath);
ft.setToValue(1);
ft.play();
}
} }
} }

View file

@ -208,8 +208,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
balanceTextField.setTargetAmount(model.dataModel.totalToPayAsCoin.get()); balanceTextField.setTargetAmount(model.dataModel.totalToPayAsCoin.get());
if (DevFlags.STRESS_TEST_MODE) // if (DevFlags.STRESS_TEST_MODE)
UserThread.runAfter(this::onShowPayFundsScreen, 200, TimeUnit.MILLISECONDS); // UserThread.runAfter(this::onShowPayFundsScreen, 200, TimeUnit.MILLISECONDS);
} }
} }

View file

@ -268,7 +268,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
// called form parent as the view does not get notified when the tab is closed // called form parent as the view does not get notified when the tab is closed
public void onClose() { public void onClose() {
Coin balance = model.dataModel.balance.get(); Coin balance = model.dataModel.balance.get();
if (balance != null && balance.isPositive() && !model.takeOfferCompleted.get()) { if (balance != null && balance.isPositive() && !model.takeOfferCompleted.get() && !DevFlags.DEV_MODE) {
model.dataModel.swapTradeToSavings(); model.dataModel.swapTradeToSavings();
new Popup().information("You had already funded that offer.\n" + new Popup().information("You had already funded that offer.\n" +
"Your funds have been moved to your local Bitsquare wallet and are available for " + "Your funds have been moved to your local Bitsquare wallet and are available for " +
@ -523,7 +523,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
showTransactionPublishedScreenSubscription = EasyBind.subscribe(model.showTransactionPublishedScreen, newValue -> { showTransactionPublishedScreenSubscription = EasyBind.subscribe(model.showTransactionPublishedScreen, newValue -> {
if (newValue && DevFlags.DEV_MODE) { if (newValue && DevFlags.DEV_MODE) {
close(); close();
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
} else if (newValue && model.getTrade() != null && model.getTrade().errorMessageProperty().get() == null) { } else if (newValue && model.getTrade() != null && model.getTrade().errorMessageProperty().get() == null) {
String key = "takeOfferSuccessInfo"; String key = "takeOfferSuccessInfo";
if (preferences.showAgain(key)) { if (preferences.showAgain(key)) {

View file

@ -128,6 +128,8 @@ public class NetworkSettingsView extends ActivatableViewAndModel<GridPane, Activ
@Override @Override
public void activate() { public void activate() {
// TODO we deactive atm as its not ready now
useTorCheckBox.setDisable(true);
useTorCheckBox.setSelected(preferences.getUseTorForBitcoinJ()); useTorCheckBox.setSelected(preferences.getUseTorForBitcoinJ());
useTorCheckBox.setOnAction(event -> { useTorCheckBox.setOnAction(event -> {
boolean selected = useTorCheckBox.isSelected(); boolean selected = useTorCheckBox.isSelected();

View file

@ -35,9 +35,12 @@ public class SeedNodesRepository {
new NodeAddress("b66vnevaljo6xt5a.onion:8000"),*/ new NodeAddress("b66vnevaljo6xt5a.onion:8000"),*/
// v0.4.2 // v0.4.2
// ...128
DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("uadzuib66jupaept.onion:8000"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("uadzuib66jupaept.onion:8000"),
DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("hbma455xxbqhcuqh.onion:8000"),
DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("wgthuiqn3aoiovbm.onion:8000"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("wgthuiqn3aoiovbm.onion:8000"),
// ...188
DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("hbma455xxbqhcuqh.onion:8000"),
DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("2zxtnprnx5wqr7a3.onion:8000"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8000") : new NodeAddress("2zxtnprnx5wqr7a3.onion:8000"),
// testnet // testnet
@ -50,9 +53,9 @@ public class SeedNodesRepository {
// 3. Shut down the seed node // 3. Shut down the seed node
// 4. Rename the directory with your local onion address // 4. Rename the directory with your local onion address
// 5. Edit here your found onion address (new NodeAddress("YOUR_ONION.onion:8002") // 5. Edit here your found onion address (new NodeAddress("YOUR_ONION.onion:8002")
new NodeAddress("rxdkppp3vicnbgqt.onion:8002"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8002") : new NodeAddress("rxdkppp3vicnbgqt.onion:8002"),
new NodeAddress("brmbf6mf67d2hlm4.onion:8002"), DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8002") : new NodeAddress("brmbf6mf67d2hlm4.onion:8002"),
new NodeAddress("mfla72c4igh5ta2t.onion:8002") DevFlags.STRESS_TEST_MODE ? new NodeAddress("hlitt7z4bec4kdh4.onion:8002") : new NodeAddress("mfla72c4igh5ta2t.onion:8002")
); );
// Addresses are used if the last digit of their port match the network id: // Addresses are used if the last digit of their port match the network id:

View file

@ -14,6 +14,7 @@ import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.common.util.Utilities; import io.bitsquare.common.util.Utilities;
import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.P2PService;
import io.bitsquare.p2p.P2PServiceListener; import io.bitsquare.p2p.P2PServiceListener;
import io.bitsquare.trade.TradeStatisticsManager;
import io.bitsquare.trade.offer.OpenOfferManager; import io.bitsquare.trade.offer.OpenOfferManager;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bitcoinj.store.BlockStoreException; import org.bitcoinj.store.BlockStoreException;
@ -30,6 +31,7 @@ public class SeedNode {
private static Environment env; private static Environment env;
private final Injector injector; private final Injector injector;
private final SeedNodeModule seedNodeModule; private final SeedNodeModule seedNodeModule;
private final TradeStatisticsManager tradeStatisticsManager;
private P2PService p2pService; private P2PService p2pService;
@ -116,6 +118,9 @@ public class SeedNode {
} }
}); });
// Wee want to persist trade statistics so we need to instantiate the tradeStatisticsManager
tradeStatisticsManager = injector.getInstance(TradeStatisticsManager.class);
} }
public void shutDown() { public void shutDown() {