Add null checks or price and volume

This commit is contained in:
Manfred Karrer 2016-04-16 14:08:39 +02:00
parent a45f8d7325
commit 3b94eda701
12 changed files with 142 additions and 85 deletions

View file

@ -236,19 +236,27 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
return getPubKeyRing().equals(keyRing.getPubKeyRing());
}
@Nullable
public Fiat getVolumeByAmount(Coin amount) {
Fiat price = getPrice();
if (price != null && amount != null) {
try {
return new ExchangeRate(getPrice()).coinToFiat(amount);
return new ExchangeRate(price).coinToFiat(amount);
} catch (Throwable t) {
log.error("getVolumeByAmount failed. Error=" + t.getMessage());
return Fiat.valueOf(currencyCode, 0);
return null;
}
} else {
return null;
}
}
@Nullable
public Fiat getOfferVolume() {
return getVolumeByAmount(getAmount());
}
@Nullable
public Fiat getMinOfferVolume() {
return getVolumeByAmount(getMinAmount());
}
@ -337,6 +345,7 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
return pubKeyRing;
}
@Nullable
public Fiat getPrice() {
if (useMarketBasedPrice) {
checkNotNull(priceFeed, "priceFeed must not be null");
@ -357,14 +366,13 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
return Fiat.parseFiat(currencyCode, String.valueOf(targetPrice));
} catch (Exception e) {
log.error("Exception at getPrice / parseToFiat: " + e.toString() + "\n" +
"We use an inaccessible price to avoid null pointers.\n" +
"That case should never happen.");
return Fiat.valueOf(currencyCode, direction == Direction.BUY ? Long.MIN_VALUE : Long.MAX_VALUE);
return null;
}
} else {
log.warn("We don't have a market price. We use an inaccessible price to avoid null pointers.\n" +
log.warn("We don't have a market price./n" +
"That case could only happen if you don't get a price feed.");
return Fiat.valueOf(currencyCode, direction == Direction.BUY ? Long.MIN_VALUE : Long.MAX_VALUE);
return null;
}
} else {
return Fiat.valueOf(currencyCode, fiatPrice);

View file

@ -82,6 +82,7 @@ public class ProcessPayDepositRequest extends TradeTask {
checkArgument(takersTradePrice > 0);
Fiat tradePriceAsFiat = Fiat.valueOf(trade.getOffer().getCurrencyCode(), takersTradePrice);
Fiat offerPriceAsFiat = trade.getOffer().getPrice();
checkArgument(offerPriceAsFiat != null, "offerPriceAsFiat must not be null");
double factor = (double) takersTradePrice / (double) offerPriceAsFiat.value;
// We allow max. 2 % difference between own offer price calculation and takers calculation.
// Market price might be different at offerers and takers side so we need a bit of tolerance.

View file

@ -47,6 +47,7 @@ import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import javafx.util.StringConverter;
import org.bitcoinj.utils.Fiat;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;
@ -184,10 +185,14 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
@Override
public void updateItem(final Offer offer, boolean empty) {
super.updateItem(offer, empty);
if (offer != null && !empty)
setText(formatter.formatFiat(offer.getPrice()));
if (offer != null && !empty) {
Fiat offerPrice = offer.getPrice();
if (offerPrice != null)
setText(formatter.formatFiat(offerPrice));
else
setText("");
} else
setText("");
}
};
}

View file

@ -33,6 +33,7 @@ import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.chart.XYChart;
import org.bitcoinj.utils.Fiat;
import java.util.ArrayList;
import java.util.List;
@ -90,8 +91,8 @@ class MarketsChartsViewModel extends ActivatableViewModel {
.filter(e -> e.getCurrencyCode().equals(tradeCurrency.get().getCode())
&& e.getDirection().equals(Offer.Direction.BUY))
.sorted((o1, o2) -> {
long a = o1.getPrice().value;
long b = o2.getPrice().value;
long a = o1.getPrice() != null ? o1.getPrice().value : 0;
long b = o2.getPrice() != null ? o2.getPrice().value : 0;
if (a != b)
return a < b ? 1 : -1;
return 0;
@ -105,8 +106,8 @@ class MarketsChartsViewModel extends ActivatableViewModel {
.filter(e -> e.getCurrencyCode().equals(tradeCurrency.get().getCode())
&& e.getDirection().equals(Offer.Direction.SELL))
.sorted((o1, o2) -> {
long a = o1.getPrice().value;
long b = o2.getPrice().value;
long a = o1.getPrice() != null ? o1.getPrice().value : 0;
long b = o2.getPrice() != null ? o2.getPrice().value : 0;
if (a != b)
return a > b ? 1 : -1;
return 0;
@ -120,7 +121,9 @@ class MarketsChartsViewModel extends ActivatableViewModel {
data.clear();
double accumulatedAmount = 0;
for (Offer offer : sortedList) {
double price = (double) offer.getPrice().value / LongMath.pow(10, offer.getPrice().smallestUnitExponent());
Fiat priceAsFiat = offer.getPrice();
if (priceAsFiat != null) {
double price = (double) priceAsFiat.value / LongMath.pow(10, priceAsFiat.smallestUnitExponent());
double amount = (double) offer.getAmount().value / LongMath.pow(10, offer.getAmount().smallestUnitExponent());
accumulatedAmount += amount;
if (direction.equals(Offer.Direction.BUY))
@ -129,6 +132,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
data.add(new XYChart.Data(price, accumulatedAmount));
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -82,28 +82,29 @@ class MarketsStatisticViewModel extends ActivatableViewModel {
.stream()
.filter(e -> e.getDirection().equals(Offer.Direction.BUY))
.sorted((o1, o2) -> {
long a = o1.getPrice().value;
long b = o2.getPrice().value;
long a = o1.getPrice() != null ? o1.getPrice().value : 0;
long b = o2.getPrice() != null ? o2.getPrice().value : 0;
if (a != b)
return a < b ? 1 : -1;
return 0;
})
.collect(Collectors.toList());
Fiat bestBuyOfferPrice = buyOffers.isEmpty() ? null : buyOffers.get(0).getPrice();
List<Offer> sellOffers = offers
.stream()
.filter(e -> e.getDirection().equals(Offer.Direction.SELL))
.sorted((o1, o2) -> {
long a = o1.getPrice().value;
long b = o2.getPrice().value;
long a = o1.getPrice() != null ? o1.getPrice().value : 0;
long b = o2.getPrice() != null ? o2.getPrice().value : 0;
if (a != b)
return a > b ? 1 : -1;
return 0;
})
.collect(Collectors.toList());
Fiat bestSellOfferPrice = sellOffers.isEmpty() ? null : sellOffers.get(0).getPrice();
Fiat spread = null;
Fiat bestSellOfferPrice = sellOffers.isEmpty() ? null : sellOffers.get(0).getPrice();
Fiat bestBuyOfferPrice = buyOffers.isEmpty() ? null : buyOffers.get(0).getPrice();
if (bestBuyOfferPrice != null && bestSellOfferPrice != null)
spread = bestSellOfferPrice.subtract(bestBuyOfferPrice);

View file

@ -51,6 +51,7 @@ import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.util.Callback;
import javafx.util.StringConverter;
import org.bitcoinj.utils.Fiat;
import javax.inject.Inject;
@ -164,9 +165,17 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
placeholder.setWrapText(true);
tableView.setPlaceholder(placeholder);
priceColumn.setComparator((o1, o2) -> o1.getOffer().getPrice().compareTo(o2.getOffer().getPrice()));
priceColumn.setComparator((o1, o2) -> {
Fiat price1 = o1.getOffer().getPrice();
Fiat price2 = o2.getOffer().getPrice();
return price1 != null && price2 != null ? price1.compareTo(price2) : 0;
});
amountColumn.setComparator((o1, o2) -> o1.getOffer().getAmount().compareTo(o2.getOffer().getAmount()));
volumeColumn.setComparator((o1, o2) -> o1.getOffer().getOfferVolume().compareTo(o2.getOffer().getOfferVolume()));
volumeColumn.setComparator((o1, o2) -> {
Fiat offerVolume1 = o1.getOffer().getOfferVolume();
Fiat offerVolume2 = o2.getOffer().getOfferVolume();
return offerVolume1 != null && offerVolume2 != null ? offerVolume1.compareTo(offerVolume2) : 0;
});
paymentMethodColumn.setComparator((o1, o2) -> o1.getOffer().getPaymentMethod().compareTo(o2.getOffer().getPaymentMethod()));
avatarColumn.setComparator((o1, o2) -> o1.getOffer().getOwnerNodeAddress().hostName.compareTo(o2.getOffer().getOwnerNodeAddress().hostName));

View file

@ -262,6 +262,7 @@ class OfferBookViewModel extends ActivatableViewModel {
Offer offer = item.getOffer();
Fiat price = offer.getPrice();
if (price != null) {
String postFix = "";
if (offer.getUseMarketBasedPrice()) {
postFix = " (" + formatter.formatToPercentWithSymbol(offer.getMarketPriceMargin()) + ")";
@ -270,6 +271,9 @@ class OfferBookViewModel extends ActivatableViewModel {
return formatter.formatPriceWithCode(price) + postFix;
else
return formatter.formatFiat(price) + postFix;
} else {
return "";
}
}
String getVolume(OfferBookListItem item) {

View file

@ -160,7 +160,8 @@ class TakeOfferDataModel extends ActivatableDataModel {
void initWithData(Offer offer) {
this.offer = offer;
tradePrice = offer.getPrice();
// we check at the view class and close in case we dont get a price
checkNotNull(tradePrice, "tradePrice must not be null");
addressEntry = walletService.getOrCreateAddressEntry(offer.getId(), AddressEntry.Context.OFFER_FUNDING);
checkNotNull(addressEntry, "addressEntry must not be null");

View file

@ -194,8 +194,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
///////////////////////////////////////////////////////////////////////////////////////////
public void initWithData(Offer offer) {
if (offer.getPrice() != null) {
model.initWithData(offer);
priceAsPercentageInputBox.setVisible(offer.getUseMarketBasedPrice());
if (model.getOffer().getDirection() == Offer.Direction.SELL) {
@ -233,6 +233,12 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
priceAsPercentageTextField.setText(model.marketPriceMargin);
addressTextField.setPaymentLabel(model.getPaymentLabel());
addressTextField.setAddress(model.dataModel.getAddressEntry().getAddressString());
} else {
new Popup().warning("You cannot take that offer as it uses a percentage price based on the " +
"market price but there is no price feed available.")
.onClose(this::close)
.show();
}
}
public void setCloseHandler(OfferView.CloseHandler closeHandler) {

View file

@ -175,11 +175,17 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
addLabelTextField(gridPane, ++rowIndex, CurrencyUtil.getNameByCode(offer.getCurrencyCode()) + " amount" + fiatDirectionInfo, formatter.formatFiatWithCode(offer.getVolumeByAmount(offer.getAmount())));
}
if (takeOfferHandlerOptional.isPresent())
if (takeOfferHandlerOptional.isPresent()) {
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(tradePrice) + " " + offer.getCurrencyCode() + "/" + "BTC");
else
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatFiat(offer.getPrice()) + " " + offer.getCurrencyCode() + "/" + "BTC");
} else {
Fiat price = offer.getPrice();
if (offer.getUseMarketBasedPrice()) {
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatPriceWithCode(price) +
" (" + formatter.formatToPercentWithSymbol(offer.getMarketPriceMargin()) + ")");
} else {
addLabelTextField(gridPane, ++rowIndex, "Price:", formatter.formatPriceWithCode(price));
}
}
if (offer.isMyOffer(keyRing) && user.getPaymentAccount(offer.getOffererPaymentAccountId()) != null)
addLabelTextField(gridPane, ++rowIndex, "Payment account:", user.getPaymentAccount(offer.getOffererPaymentAccountId()).getAccountName());
else

View file

@ -85,8 +85,11 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
Tradable tradable = o1.getTradable();
if (tradable instanceof Trade)
return ((Trade) o1.getTradable()).getTradePrice().compareTo(((Trade) o2.getTradable()).getTradePrice());
else
return o1.getTradable().getOffer().getPrice().compareTo(o2.getTradable().getOffer().getPrice());
else {
Fiat price1 = o1.getTradable().getOffer().getPrice();
Fiat price2 = o2.getTradable().getOffer().getPrice();
return price1 != null && price2 != null ? price1.compareTo(price2) : 0;
}
});
volumeColumn.setComparator((o1, o2) -> {
if (o1.getTradable() instanceof Trade && o2.getTradable() instanceof Trade) {

View file

@ -34,6 +34,7 @@ import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import org.bitcoinj.utils.Fiat;
import javax.inject.Inject;
@ -72,8 +73,16 @@ public class OpenOffersView extends ActivatableViewAndModel<VBox, OpenOffersView
offerIdColumn.setComparator((o1, o2) -> o1.getOffer().getId().compareTo(o2.getOffer().getId()));
directionColumn.setComparator((o1, o2) -> o1.getOffer().getDirection().compareTo(o2.getOffer().getDirection()));
amountColumn.setComparator((o1, o2) -> o1.getOffer().getAmount().compareTo(o2.getOffer().getAmount()));
priceColumn.setComparator((o1, o2) -> o1.getOffer().getPrice().compareTo(o2.getOffer().getPrice()));
volumeColumn.setComparator((o1, o2) -> o1.getOffer().getOfferVolume().compareTo(o2.getOffer().getOfferVolume()));
priceColumn.setComparator((o1, o2) -> {
Fiat price1 = o1.getOffer().getPrice();
Fiat price2 = o2.getOffer().getPrice();
return price1 != null && price2 != null ? price1.compareTo(price2) : 0;
});
volumeColumn.setComparator((o1, o2) -> {
Fiat offerVolume1 = o1.getOffer().getOfferVolume();
Fiat offerVolume2 = o2.getOffer().getOfferVolume();
return offerVolume1 != null && offerVolume2 != null ? offerVolume1.compareTo(offerVolume2) : 0;
});
dateColumn.setComparator((o1, o2) -> o1.getOffer().getDate().compareTo(o2.getOffer().getDate()));
dateColumn.setSortType(TableColumn.SortType.DESCENDING);