mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-08-02 11:46:11 -04:00
Add pricefeed to offer, display offerprice with perc. (WIP)
This commit is contained in:
parent
7fe4d37501
commit
13a62b1342
11 changed files with 115 additions and 38 deletions
|
@ -24,6 +24,7 @@ import io.bitsquare.btc.AddressEntry;
|
||||||
import io.bitsquare.btc.AddressEntryException;
|
import io.bitsquare.btc.AddressEntryException;
|
||||||
import io.bitsquare.btc.TradeWalletService;
|
import io.bitsquare.btc.TradeWalletService;
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.btc.WalletService;
|
||||||
|
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
import io.bitsquare.common.crypto.KeyRing;
|
||||||
import io.bitsquare.common.handlers.FaultHandler;
|
import io.bitsquare.common.handlers.FaultHandler;
|
||||||
import io.bitsquare.common.handlers.ResultHandler;
|
import io.bitsquare.common.handlers.ResultHandler;
|
||||||
|
@ -97,6 +98,7 @@ public class TradeManager {
|
||||||
FailedTradesManager failedTradesManager,
|
FailedTradesManager failedTradesManager,
|
||||||
ArbitratorManager arbitratorManager,
|
ArbitratorManager arbitratorManager,
|
||||||
P2PService p2PService,
|
P2PService p2PService,
|
||||||
|
PriceFeed priceFeed,
|
||||||
@Named("storage.dir") File storageDir) {
|
@Named("storage.dir") File storageDir) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.keyRing = keyRing;
|
this.keyRing = keyRing;
|
||||||
|
@ -109,7 +111,8 @@ public class TradeManager {
|
||||||
this.p2PService = p2PService;
|
this.p2PService = p2PService;
|
||||||
|
|
||||||
tradableListStorage = new Storage<>(storageDir);
|
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() {
|
p2PService.addDecryptedDirectMessageListener(new DecryptedDirectMessageListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package io.bitsquare.trade.closed;
|
package io.bitsquare.trade.closed;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
import io.bitsquare.common.crypto.KeyRing;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.trade.Tradable;
|
import io.bitsquare.trade.Tradable;
|
||||||
|
@ -37,9 +38,10 @@ public class ClosedTradableManager {
|
||||||
private final KeyRing keyRing;
|
private final KeyRing keyRing;
|
||||||
|
|
||||||
@Inject
|
@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.keyRing = keyRing;
|
||||||
this.closedTrades = new TradableList<>(new Storage<>(storageDir), "ClosedTrades");
|
this.closedTrades = new TradableList<>(new Storage<>(storageDir), "ClosedTrades");
|
||||||
|
closedTrades.forEach(e -> e.getOffer().setPriceFeed(priceFeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(Tradable tradable) {
|
public void add(Tradable tradable) {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package io.bitsquare.trade.failed;
|
package io.bitsquare.trade.failed;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
import io.bitsquare.common.crypto.KeyRing;
|
||||||
import io.bitsquare.storage.Storage;
|
import io.bitsquare.storage.Storage;
|
||||||
import io.bitsquare.trade.TradableList;
|
import io.bitsquare.trade.TradableList;
|
||||||
|
@ -37,9 +38,10 @@ public class FailedTradesManager {
|
||||||
private final KeyRing keyRing;
|
private final KeyRing keyRing;
|
||||||
|
|
||||||
@Inject
|
@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.keyRing = keyRing;
|
||||||
this.failedTrades = new TradableList<>(new Storage<>(storageDir), "FailedTrades");
|
this.failedTrades = new TradableList<>(new Storage<>(storageDir), "FailedTrades");
|
||||||
|
failedTrades.forEach(e -> e.getOffer().setPriceFeed(priceFeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(Trade trade) {
|
public void add(Trade trade) {
|
||||||
|
|
|
@ -19,6 +19,8 @@ package io.bitsquare.trade.offer;
|
||||||
|
|
||||||
import io.bitsquare.app.Version;
|
import io.bitsquare.app.Version;
|
||||||
import io.bitsquare.btc.Restrictions;
|
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.KeyRing;
|
||||||
import io.bitsquare.common.crypto.PubKeyRing;
|
import io.bitsquare.common.crypto.PubKeyRing;
|
||||||
import io.bitsquare.common.handlers.ResultHandler;
|
import io.bitsquare.common.handlers.ResultHandler;
|
||||||
|
@ -106,7 +108,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
private final long date;
|
private final long date;
|
||||||
private final long protocolVersion;
|
private final long protocolVersion;
|
||||||
private final long fiatPrice;
|
private final long fiatPrice;
|
||||||
private final double percentageBasedPrice;
|
private final double marketPriceMargin;
|
||||||
private final boolean usePercentageBasedPrice;
|
private final boolean usePercentageBasedPrice;
|
||||||
private final long amount;
|
private final long amount;
|
||||||
private final long minAmount;
|
private final long minAmount;
|
||||||
|
@ -129,6 +131,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
transient private OfferAvailabilityProtocol availabilityProtocol;
|
transient private OfferAvailabilityProtocol availabilityProtocol;
|
||||||
@JsonExclude
|
@JsonExclude
|
||||||
transient private StringProperty errorMessageProperty = new SimpleStringProperty();
|
transient private StringProperty errorMessageProperty = new SimpleStringProperty();
|
||||||
|
transient private PriceFeed priceFeed;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -140,7 +143,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
PubKeyRing pubKeyRing,
|
PubKeyRing pubKeyRing,
|
||||||
Direction direction,
|
Direction direction,
|
||||||
long fiatPrice,
|
long fiatPrice,
|
||||||
double percentageBasedPrice,
|
double marketPriceMargin,
|
||||||
boolean usePercentageBasedPrice,
|
boolean usePercentageBasedPrice,
|
||||||
long amount,
|
long amount,
|
||||||
long minAmount,
|
long minAmount,
|
||||||
|
@ -151,13 +154,14 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
@Nullable String countryCode,
|
@Nullable String countryCode,
|
||||||
@Nullable ArrayList<String> acceptedCountryCodes,
|
@Nullable ArrayList<String> acceptedCountryCodes,
|
||||||
@Nullable String bankId,
|
@Nullable String bankId,
|
||||||
@Nullable ArrayList<String> acceptedBankIds) {
|
@Nullable ArrayList<String> acceptedBankIds,
|
||||||
|
PriceFeed priceFeed) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.offererNodeAddress = offererNodeAddress;
|
this.offererNodeAddress = offererNodeAddress;
|
||||||
this.pubKeyRing = pubKeyRing;
|
this.pubKeyRing = pubKeyRing;
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
this.fiatPrice = fiatPrice;
|
this.fiatPrice = fiatPrice;
|
||||||
this.percentageBasedPrice = percentageBasedPrice;
|
this.marketPriceMargin = marketPriceMargin;
|
||||||
this.usePercentageBasedPrice = usePercentageBasedPrice;
|
this.usePercentageBasedPrice = usePercentageBasedPrice;
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
this.minAmount = minAmount;
|
this.minAmount = minAmount;
|
||||||
|
@ -169,6 +173,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
this.acceptedCountryCodes = acceptedCountryCodes;
|
this.acceptedCountryCodes = acceptedCountryCodes;
|
||||||
this.bankId = bankId;
|
this.bankId = bankId;
|
||||||
this.acceptedBankIds = acceptedBankIds;
|
this.acceptedBankIds = acceptedBankIds;
|
||||||
|
this.priceFeed = priceFeed;
|
||||||
|
|
||||||
protocolVersion = Version.TRADE_PROTOCOL_VERSION;
|
protocolVersion = Version.TRADE_PROTOCOL_VERSION;
|
||||||
|
|
||||||
|
@ -269,6 +274,10 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
// Setters
|
// Setters
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void setPriceFeed(PriceFeed priceFeed) {
|
||||||
|
this.priceFeed = priceFeed;
|
||||||
|
}
|
||||||
|
|
||||||
public void setState(State state) {
|
public void setState(State state) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
stateProperty().set(state);
|
stateProperty().set(state);
|
||||||
|
@ -318,11 +327,34 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
}
|
}
|
||||||
|
|
||||||
public Fiat getPrice() {
|
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() {
|
public double getMarketPriceMargin() {
|
||||||
return percentageBasedPrice;
|
return marketPriceMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUsePercentageBasedPrice() {
|
public boolean isUsePercentageBasedPrice() {
|
||||||
|
@ -408,7 +440,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
Offer offer = (Offer) o;
|
Offer offer = (Offer) o;
|
||||||
if (date != offer.date) return false;
|
if (date != offer.date) return false;
|
||||||
if (fiatPrice != offer.fiatPrice) 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 (usePercentageBasedPrice != offer.usePercentageBasedPrice) return false;
|
||||||
if (amount != offer.amount) return false;
|
if (amount != offer.amount) return false;
|
||||||
if (minAmount != offer.minAmount) 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 + (currencyCode != null ? currencyCode.hashCode() : 0);
|
||||||
result = 31 * result + (int) (date ^ (date >>> 32));
|
result = 31 * result + (int) (date ^ (date >>> 32));
|
||||||
result = 31 * result + (int) (fiatPrice ^ (fiatPrice >>> 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 + (int) (temp ^ (temp >>> 32));
|
||||||
result = 31 * result + (usePercentageBasedPrice ? 1 : 0);
|
result = 31 * result + (usePercentageBasedPrice ? 1 : 0);
|
||||||
result = 31 * result + (int) (amount ^ (amount >>> 32));
|
result = 31 * result + (int) (amount ^ (amount >>> 32));
|
||||||
|
@ -467,7 +499,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
|
||||||
"\n\tcurrencyCode='" + currencyCode + '\'' +
|
"\n\tcurrencyCode='" + currencyCode + '\'' +
|
||||||
"\n\tdate=" + date +
|
"\n\tdate=" + date +
|
||||||
"\n\tfiatPrice=" + fiatPrice +
|
"\n\tfiatPrice=" + fiatPrice +
|
||||||
"\n\tpercentagePrice=" + percentageBasedPrice +
|
"\n\tmarketPriceMargin=" + marketPriceMargin +
|
||||||
"\n\tusePercentageBasedPrice=" + usePercentageBasedPrice +
|
"\n\tusePercentageBasedPrice=" + usePercentageBasedPrice +
|
||||||
"\n\tamount=" + amount +
|
"\n\tamount=" + amount +
|
||||||
"\n\tminAmount=" + minAmount +
|
"\n\tminAmount=" + minAmount +
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package io.bitsquare.trade.offer;
|
package io.bitsquare.trade.offer;
|
||||||
|
|
||||||
|
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||||
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
||||||
import io.bitsquare.common.handlers.ResultHandler;
|
import io.bitsquare.common.handlers.ResultHandler;
|
||||||
import io.bitsquare.p2p.P2PService;
|
import io.bitsquare.p2p.P2PService;
|
||||||
|
@ -45,6 +46,7 @@ public class OfferBookService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final P2PService p2PService;
|
private final P2PService p2PService;
|
||||||
|
private PriceFeed priceFeed;
|
||||||
private final List<OfferBookChangedListener> offerBookChangedListeners = new LinkedList<>();
|
private final List<OfferBookChangedListener> offerBookChangedListeners = new LinkedList<>();
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,15 +55,19 @@ public class OfferBookService {
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public OfferBookService(P2PService p2PService) {
|
public OfferBookService(P2PService p2PService, PriceFeed priceFeed) {
|
||||||
this.p2PService = p2PService;
|
this.p2PService = p2PService;
|
||||||
|
this.priceFeed = priceFeed;
|
||||||
|
|
||||||
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
|
p2PService.addHashSetChangedListener(new HashMapChangedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAdded(ProtectedStorageEntry data) {
|
public void onAdded(ProtectedStorageEntry data) {
|
||||||
offerBookChangedListeners.stream().forEach(listener -> {
|
offerBookChangedListeners.stream().forEach(listener -> {
|
||||||
if (data.getStoragePayload() instanceof Offer)
|
if (data.getStoragePayload() instanceof Offer) {
|
||||||
listener.onAdded((Offer) data.getStoragePayload());
|
Offer offer = (Offer) data.getStoragePayload();
|
||||||
|
offer.setPriceFeed(priceFeed);
|
||||||
|
listener.onAdded(offer);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +124,11 @@ public class OfferBookService {
|
||||||
public List<Offer> getOffers() {
|
public List<Offer> getOffers() {
|
||||||
return p2PService.getDataMap().values().stream()
|
return p2PService.getDataMap().values().stream()
|
||||||
.filter(data -> data.getStoragePayload() instanceof Offer)
|
.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());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.btc.AddressEntry;
|
import io.bitsquare.btc.AddressEntry;
|
||||||
import io.bitsquare.btc.TradeWalletService;
|
import io.bitsquare.btc.TradeWalletService;
|
||||||
import io.bitsquare.btc.WalletService;
|
import io.bitsquare.btc.WalletService;
|
||||||
|
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||||
import io.bitsquare.common.Timer;
|
import io.bitsquare.common.Timer;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.common.crypto.KeyRing;
|
import io.bitsquare.common.crypto.KeyRing;
|
||||||
|
@ -95,6 +96,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
TradeWalletService tradeWalletService,
|
TradeWalletService tradeWalletService,
|
||||||
OfferBookService offerBookService,
|
OfferBookService offerBookService,
|
||||||
ClosedTradableManager closedTradableManager,
|
ClosedTradableManager closedTradableManager,
|
||||||
|
PriceFeed priceFeed,
|
||||||
@Named("storage.dir") File storageDir) {
|
@Named("storage.dir") File storageDir) {
|
||||||
this.keyRing = keyRing;
|
this.keyRing = keyRing;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
|
@ -105,7 +107,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||||
this.closedTradableManager = closedTradableManager;
|
this.closedTradableManager = closedTradableManager;
|
||||||
|
|
||||||
openOffersStorage = new Storage<>(storageDir);
|
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
|
// 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,
|
Runtime.getRuntime().addShutdownHook(new Thread(OpenOfferManager.this::shutDown,
|
||||||
|
|
|
@ -301,7 +301,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
countryCode,
|
countryCode,
|
||||||
acceptedCountryCodes,
|
acceptedCountryCodes,
|
||||||
bankId,
|
bankId,
|
||||||
acceptedBanks);
|
acceptedBanks,
|
||||||
|
priceFeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onPlaceOffer(Offer offer, TransactionResultHandler resultHandler) {
|
void onPlaceOffer(Offer offer, TransactionResultHandler resultHandler) {
|
||||||
|
|
|
@ -117,6 +117,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
private Timer timeoutTimer;
|
private Timer timeoutTimer;
|
||||||
private PriceFeed.Type priceFeedType;
|
private PriceFeed.Type priceFeedType;
|
||||||
private boolean priceAsPercentageIsInput;
|
private boolean priceAsPercentageIsInput;
|
||||||
|
private ChangeListener<Boolean> usePercentageBasedPriceListener;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -239,6 +240,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
calculateVolume();
|
calculateVolume();
|
||||||
dataModel.calculateTotalToPay();
|
dataModel.calculateTotalToPay();
|
||||||
|
|
||||||
|
if (!priceAsPercentageIsInput) {
|
||||||
MarketPrice marketPrice = priceFeed.getMarketPrice(dataModel.tradeCurrencyCode.get());
|
MarketPrice marketPrice = priceFeed.getMarketPrice(dataModel.tradeCurrencyCode.get());
|
||||||
if (marketPrice != null) {
|
if (marketPrice != null) {
|
||||||
double marketPriceAsDouble = marketPrice.getPrice(priceFeedType);
|
double marketPriceAsDouble = marketPrice.getPrice(priceFeedType);
|
||||||
|
@ -254,6 +256,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
updateButtonDisableState();
|
updateButtonDisableState();
|
||||||
};
|
};
|
||||||
priceAsPercentageListener = (ov, oldValue, newValue) -> {
|
priceAsPercentageListener = (ov, oldValue, newValue) -> {
|
||||||
|
@ -295,6 +298,11 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
usePercentageBasedPriceListener = (observable, oldValue, newValue) -> {
|
||||||
|
if (newValue)
|
||||||
|
priceValidationResult.set(new InputValidator.ValidationResult(true));
|
||||||
|
};
|
||||||
|
|
||||||
volumeListener = (ov, oldValue, newValue) -> {
|
volumeListener = (ov, oldValue, newValue) -> {
|
||||||
if (isFiatInputValid(newValue).isValid) {
|
if (isFiatInputValid(newValue).isValid) {
|
||||||
setVolumeToModel();
|
setVolumeToModel();
|
||||||
|
@ -324,6 +332,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
minAmount.addListener(minAmountListener);
|
minAmount.addListener(minAmountListener);
|
||||||
price.addListener(priceListener);
|
price.addListener(priceListener);
|
||||||
priceAsPercentage.addListener(priceAsPercentageListener);
|
priceAsPercentage.addListener(priceAsPercentageListener);
|
||||||
|
dataModel.usePercentageBasedPrice.addListener(usePercentageBasedPriceListener);
|
||||||
volume.addListener(volumeListener);
|
volume.addListener(volumeListener);
|
||||||
|
|
||||||
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
|
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
|
||||||
|
@ -341,6 +350,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
minAmount.removeListener(minAmountListener);
|
minAmount.removeListener(minAmountListener);
|
||||||
price.removeListener(priceListener);
|
price.removeListener(priceListener);
|
||||||
priceAsPercentage.removeListener(priceAsPercentageListener);
|
priceAsPercentage.removeListener(priceAsPercentageListener);
|
||||||
|
dataModel.usePercentageBasedPrice.removeListener(usePercentageBasedPriceListener);
|
||||||
volume.removeListener(volumeListener);
|
volume.removeListener(volumeListener);
|
||||||
|
|
||||||
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
|
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
|
||||||
|
@ -366,7 +376,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
if (dataModel.paymentAccount != null)
|
if (dataModel.paymentAccount != null)
|
||||||
btcValidator.setMaxTradeLimitInBitcoin(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimit());
|
btcValidator.setMaxTradeLimitInBitcoin(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimit());
|
||||||
|
|
||||||
priceFeedType = direction == Offer.Direction.BUY ? PriceFeed.Type.ASK : PriceFeed.Type.BID;
|
priceFeedType = direction == Offer.Direction.SELL ? PriceFeed.Type.ASK : PriceFeed.Type.BID;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -565,7 +575,8 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
Fiat priceAsFiat = dataModel.priceAsFiat.get();
|
Fiat priceAsFiat = dataModel.priceAsFiat.get();
|
||||||
long shiftDivisor = checkedPow(10, priceAsFiat.smallestUnitExponent());
|
long shiftDivisor = checkedPow(10, priceAsFiat.smallestUnitExponent());
|
||||||
double offerPrice = ((double) priceAsFiat.longValue()) / ((double) shiftDivisor);
|
double offerPrice = ((double) priceAsFiat.longValue()) / ((double) shiftDivisor);
|
||||||
if (marketPriceAsDouble != 0 && Math.abs(1 - (offerPrice / marketPriceAsDouble)) > preferences.getMaxPriceDistanceInPercent()) {
|
double percentage = Math.abs(1 - (offerPrice / marketPriceAsDouble));
|
||||||
|
if (marketPriceAsDouble != 0 && percentage > preferences.getMaxPriceDistanceInPercent()) {
|
||||||
displayPriceOutofRangePopup();
|
displayPriceOutofRangePopup();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -257,10 +257,19 @@ class OfferBookViewModel extends ActivatableViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
String getPrice(OfferBookListItem item) {
|
String getPrice(OfferBookListItem item) {
|
||||||
|
if ((item == null))
|
||||||
|
return "";
|
||||||
|
|
||||||
|
Offer offer = item.getOffer();
|
||||||
|
Fiat price = offer.getPrice();
|
||||||
|
String postFix = "";
|
||||||
|
if (offer.isUsePercentageBasedPrice()) {
|
||||||
|
postFix = " (" + formatter.formatToPercentWithSymbol(offer.getMarketPriceMargin()) + ")";
|
||||||
|
}
|
||||||
if (showAllTradeCurrenciesProperty.get())
|
if (showAllTradeCurrenciesProperty.get())
|
||||||
return (item != null) ? formatter.formatFiatWithCode(item.getOffer().getPrice()) : "";
|
return formatter.formatPriceWithCode(price) + postFix;
|
||||||
else
|
else
|
||||||
return (item != null) ? formatter.formatFiat(item.getOffer().getPrice()) : "";
|
return formatter.formatFiat(price) + postFix;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getVolume(OfferBookListItem item) {
|
String getVolume(OfferBookListItem item) {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package io.bitsquare.gui.main.offer.takeoffer;
|
package io.bitsquare.gui.main.offer.takeoffer;
|
||||||
|
|
||||||
import io.bitsquare.arbitration.Arbitrator;
|
import io.bitsquare.arbitration.Arbitrator;
|
||||||
|
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||||
import io.bitsquare.gui.Navigation;
|
import io.bitsquare.gui.Navigation;
|
||||||
import io.bitsquare.gui.common.model.ActivatableWithDataModel;
|
import io.bitsquare.gui.common.model.ActivatableWithDataModel;
|
||||||
import io.bitsquare.gui.common.model.ViewModel;
|
import io.bitsquare.gui.common.model.ViewModel;
|
||||||
|
@ -52,6 +53,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||||
final TakeOfferDataModel dataModel;
|
final TakeOfferDataModel dataModel;
|
||||||
private final BtcValidator btcValidator;
|
private final BtcValidator btcValidator;
|
||||||
private final P2PService p2PService;
|
private final P2PService p2PService;
|
||||||
|
private PriceFeed priceFeed;
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
final BSFormatter formatter;
|
final BSFormatter formatter;
|
||||||
|
|
||||||
|
@ -101,13 +103,14 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public TakeOfferViewModel(TakeOfferDataModel dataModel, BtcValidator btcValidator, P2PService p2PService,
|
public TakeOfferViewModel(TakeOfferDataModel dataModel, BtcValidator btcValidator, P2PService p2PService, PriceFeed priceFeed,
|
||||||
Navigation navigation, BSFormatter formatter) {
|
Navigation navigation, BSFormatter formatter) {
|
||||||
super(dataModel);
|
super(dataModel);
|
||||||
this.dataModel = dataModel;
|
this.dataModel = dataModel;
|
||||||
|
|
||||||
this.btcValidator = btcValidator;
|
this.btcValidator = btcValidator;
|
||||||
this.p2PService = p2PService;
|
this.p2PService = p2PService;
|
||||||
|
this.priceFeed = priceFeed;
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
|
|
||||||
|
|
|
@ -277,6 +277,7 @@ public class OfferBookViewModelTest {
|
||||||
countryCode,
|
countryCode,
|
||||||
acceptedCountryCodes,
|
acceptedCountryCodes,
|
||||||
bankId,
|
bankId,
|
||||||
acceptedBanks);
|
acceptedBanks,
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue