Add pricefeed to offer, display offerprice with perc. (WIP)

This commit is contained in:
Manfred Karrer 2016-04-15 00:35:31 +02:00
parent 7fe4d37501
commit 13a62b1342
11 changed files with 115 additions and 38 deletions

View file

@ -24,6 +24,7 @@ import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.AddressEntryException;
import io.bitsquare.btc.TradeWalletService;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.common.handlers.FaultHandler;
import io.bitsquare.common.handlers.ResultHandler;
@ -97,6 +98,7 @@ public class TradeManager {
FailedTradesManager failedTradesManager,
ArbitratorManager arbitratorManager,
P2PService p2PService,
PriceFeed priceFeed,
@Named("storage.dir") File storageDir) {
this.user = user;
this.keyRing = keyRing;
@ -109,8 +111,9 @@ public class TradeManager {
this.p2PService = p2PService;
tradableListStorage = new Storage<>(storageDir);
this.trades = new TradableList<>(tradableListStorage, "PendingTrades");
trades = new TradableList<>(tradableListStorage, "PendingTrades");
trades.forEach(e -> e.getOffer().setPriceFeed(priceFeed));
p2PService.addDecryptedDirectMessageListener(new DecryptedDirectMessageListener() {
@Override
public void onDirectMessage(DecryptedMsgWithPubKey decryptedMsgWithPubKey, NodeAddress peerNodeAddress) {

View file

@ -18,6 +18,7 @@
package io.bitsquare.trade.closed;
import com.google.inject.Inject;
import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.Tradable;
@ -37,9 +38,10 @@ public class ClosedTradableManager {
private final KeyRing keyRing;
@Inject
public ClosedTradableManager(KeyRing keyRing, @Named("storage.dir") File storageDir) {
public ClosedTradableManager(KeyRing keyRing, PriceFeed priceFeed, @Named("storage.dir") File storageDir) {
this.keyRing = keyRing;
this.closedTrades = new TradableList<>(new Storage<>(storageDir), "ClosedTrades");
closedTrades.forEach(e -> e.getOffer().setPriceFeed(priceFeed));
}
public void add(Tradable tradable) {

View file

@ -18,6 +18,7 @@
package io.bitsquare.trade.failed;
import com.google.inject.Inject;
import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.TradableList;
@ -37,9 +38,10 @@ public class FailedTradesManager {
private final KeyRing keyRing;
@Inject
public FailedTradesManager(KeyRing keyRing, @Named("storage.dir") File storageDir) {
public FailedTradesManager(KeyRing keyRing, PriceFeed priceFeed, @Named("storage.dir") File storageDir) {
this.keyRing = keyRing;
this.failedTrades = new TradableList<>(new Storage<>(storageDir), "FailedTrades");
failedTrades.forEach(e -> e.getOffer().setPriceFeed(priceFeed));
}
public void add(Trade trade) {

View file

@ -19,6 +19,8 @@ package io.bitsquare.trade.offer;
import io.bitsquare.app.Version;
import io.bitsquare.btc.Restrictions;
import io.bitsquare.btc.pricefeed.MarketPrice;
import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.common.crypto.PubKeyRing;
import io.bitsquare.common.handlers.ResultHandler;
@ -106,7 +108,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
private final long date;
private final long protocolVersion;
private final long fiatPrice;
private final double percentageBasedPrice;
private final double marketPriceMargin;
private final boolean usePercentageBasedPrice;
private final long amount;
private final long minAmount;
@ -129,6 +131,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
transient private OfferAvailabilityProtocol availabilityProtocol;
@JsonExclude
transient private StringProperty errorMessageProperty = new SimpleStringProperty();
transient private PriceFeed priceFeed;
///////////////////////////////////////////////////////////////////////////////////////////
@ -140,7 +143,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
PubKeyRing pubKeyRing,
Direction direction,
long fiatPrice,
double percentageBasedPrice,
double marketPriceMargin,
boolean usePercentageBasedPrice,
long amount,
long minAmount,
@ -151,13 +154,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
@Nullable String countryCode,
@Nullable ArrayList<String> acceptedCountryCodes,
@Nullable String bankId,
@Nullable ArrayList<String> acceptedBankIds) {
@Nullable ArrayList<String> acceptedBankIds,
PriceFeed priceFeed) {
this.id = id;
this.offererNodeAddress = offererNodeAddress;
this.pubKeyRing = pubKeyRing;
this.direction = direction;
this.fiatPrice = fiatPrice;
this.percentageBasedPrice = percentageBasedPrice;
this.marketPriceMargin = marketPriceMargin;
this.usePercentageBasedPrice = usePercentageBasedPrice;
this.amount = amount;
this.minAmount = minAmount;
@ -169,6 +173,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
this.acceptedCountryCodes = acceptedCountryCodes;
this.bankId = bankId;
this.acceptedBankIds = acceptedBankIds;
this.priceFeed = priceFeed;
protocolVersion = Version.TRADE_PROTOCOL_VERSION;
@ -269,6 +274,10 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setPriceFeed(PriceFeed priceFeed) {
this.priceFeed = priceFeed;
}
public void setState(State state) {
this.state = state;
stateProperty().set(state);
@ -318,11 +327,34 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
}
public Fiat getPrice() {
return Fiat.valueOf(currencyCode, fiatPrice);
Fiat priceAsFiat = Fiat.valueOf(currencyCode, fiatPrice);
if (usePercentageBasedPrice && priceFeed != null) {
MarketPrice marketPrice = priceFeed.getMarketPrice(currencyCode);
if (marketPrice != null) {
PriceFeed.Type priceFeedType = direction == Direction.SELL ? PriceFeed.Type.ASK : PriceFeed.Type.BID;
double marketPriceAsDouble = marketPrice.getPrice(priceFeedType);
double factor = direction == Offer.Direction.BUY ? 1 - marketPriceMargin : 1 + marketPriceMargin;
double targetPrice = marketPriceAsDouble * factor;
try {
return Fiat.parseFiat(currencyCode, String.valueOf(targetPrice));
} catch (Exception e) {
log.warn("Exception at parseToFiat: " + e.toString());
log.warn("We use the static price.");
return priceAsFiat;
}
} else {
log.warn("We don't have a market price. We use the static price instead.");
return priceAsFiat;
}
} else {
if (priceFeed == null)
log.warn("priceFeed must not be null");
return priceAsFiat;
}
}
public double getPercentageBasedPrice() {
return percentageBasedPrice;
public double getMarketPriceMargin() {
return marketPriceMargin;
}
public boolean isUsePercentageBasedPrice() {
@ -408,7 +440,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
Offer offer = (Offer) o;
if (date != offer.date) return false;
if (fiatPrice != offer.fiatPrice) return false;
if (Double.compare(offer.percentageBasedPrice, percentageBasedPrice) != 0) return false;
if (Double.compare(offer.marketPriceMargin, marketPriceMargin) != 0) return false;
if (usePercentageBasedPrice != offer.usePercentageBasedPrice) return false;
if (amount != offer.amount) return false;
if (minAmount != offer.minAmount) return false;
@ -441,7 +473,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
result = 31 * result + (currencyCode != null ? currencyCode.hashCode() : 0);
result = 31 * result + (int) (date ^ (date >>> 32));
result = 31 * result + (int) (fiatPrice ^ (fiatPrice >>> 32));
long temp = Double.doubleToLongBits(percentageBasedPrice);
long temp = Double.doubleToLongBits(marketPriceMargin);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (usePercentageBasedPrice ? 1 : 0);
result = 31 * result + (int) (amount ^ (amount >>> 32));
@ -467,7 +499,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
"\n\tcurrencyCode='" + currencyCode + '\'' +
"\n\tdate=" + date +
"\n\tfiatPrice=" + fiatPrice +
"\n\tpercentagePrice=" + percentageBasedPrice +
"\n\tmarketPriceMargin=" + marketPriceMargin +
"\n\tusePercentageBasedPrice=" + usePercentageBasedPrice +
"\n\tamount=" + amount +
"\n\tminAmount=" + minAmount +

View file

@ -17,6 +17,7 @@
package io.bitsquare.trade.offer;
import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.common.handlers.ErrorMessageHandler;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.p2p.P2PService;
@ -45,6 +46,7 @@ public class OfferBookService {
}
private final P2PService p2PService;
private PriceFeed priceFeed;
private final List<OfferBookChangedListener> offerBookChangedListeners = new LinkedList<>();
@ -53,15 +55,19 @@ public class OfferBookService {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public OfferBookService(P2PService p2PService) {
public OfferBookService(P2PService p2PService, PriceFeed priceFeed) {
this.p2PService = p2PService;
this.priceFeed = priceFeed;
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
@Override
public void onAdded(ProtectedStorageEntry data) {
offerBookChangedListeners.stream().forEach(listener -> {
if (data.getStoragePayload() instanceof Offer)
listener.onAdded((Offer) data.getStoragePayload());
if (data.getStoragePayload() instanceof Offer) {
Offer offer = (Offer) data.getStoragePayload();
offer.setPriceFeed(priceFeed);
listener.onAdded(offer);
}
});
}
@ -118,7 +124,11 @@ public class OfferBookService {
public List<Offer> getOffers() {
return p2PService.getDataMap().values().stream()
.filter(data -> data.getStoragePayload() instanceof Offer)
.map(data -> (Offer) data.getStoragePayload())
.map(data -> {
Offer offer = (Offer) data.getStoragePayload();
offer.setPriceFeed(priceFeed);
return offer;
})
.collect(Collectors.toList());
}

View file

@ -22,6 +22,7 @@ import io.bitsquare.app.Log;
import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.TradeWalletService;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.pricefeed.PriceFeed;
import io.bitsquare.common.Timer;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.crypto.KeyRing;
@ -95,6 +96,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
TradeWalletService tradeWalletService,
OfferBookService offerBookService,
ClosedTradableManager closedTradableManager,
PriceFeed priceFeed,
@Named("storage.dir") File storageDir) {
this.keyRing = keyRing;
this.user = user;
@ -105,7 +107,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
this.closedTradableManager = closedTradableManager;
openOffersStorage = new Storage<>(storageDir);
this.openOffers = new TradableList<>(openOffersStorage, "OpenOffers");
openOffers = new TradableList<>(openOffersStorage, "OpenOffers");
openOffers.forEach(e -> e.getOffer().setPriceFeed(priceFeed));
// In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(OpenOfferManager.this::shutDown,