Add listeners if pricefeed is not available

This commit is contained in:
Manfred Karrer 2016-04-16 15:46:45 +02:00
parent 3b94eda701
commit b97506cf51
11 changed files with 150 additions and 42 deletions

View File

@ -107,6 +107,7 @@ public class PriceFeed {
return null;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setter
///////////////////////////////////////////////////////////////////////////////////////////

View File

@ -277,7 +277,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
resultHandler.handleResult();
},
(errorMessage) -> {
availabilityProtocol.cancel();
if (availabilityProtocol != null)
availabilityProtocol.cancel();
log.error(errorMessage);
});
availabilityProtocol.sendOfferAvailabilityRequest();
@ -370,8 +371,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
return null;
}
} else {
log.warn("We don't have a market price./n" +
"That case could only happen if you don't get a price feed.");
log.warn("We don't have a market price.\n" +
"That case could only happen if you don't have a price feed.");
return null;
}
} else {

View File

@ -35,6 +35,8 @@ import io.bitsquare.trade.offer.Offer;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@ -47,7 +49,6 @@ 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;
@ -182,17 +183,34 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
@Override
public TableCell<Offer, Offer> call(TableColumn<Offer, Offer> column) {
return new TableCell<Offer, Offer>() {
private Offer offer;
ChangeListener<Number> listener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (offer != null && offer.getPrice() != null) {
setText(formatter.formatFiat(offer.getPrice()));
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
}
}
};
@Override
public void updateItem(final Offer offer, boolean empty) {
super.updateItem(offer, empty);
if (offer != null && !empty) {
Fiat offerPrice = offer.getPrice();
if (offerPrice != null)
setText(formatter.formatFiat(offerPrice));
else
setText("");
} else
if (offer.getPrice() == null) {
this.offer = offer;
model.priceFeed.currenciesUpdateFlagProperty().addListener(listener);
setText("N/A");
} else {
setText(formatter.formatFiat(offer.getPrice()));
}
} else {
if (listener != null)
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
this.offer = null;
setText("");
}
}
};
}
@ -236,13 +254,34 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
@Override
public TableCell<Offer, Offer> call(TableColumn<Offer, Offer> column) {
return new TableCell<Offer, Offer>() {
private Offer offer;
ChangeListener<Number> listener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (offer != null && offer.getPrice() != null) {
setText(formatter.formatFiat(offer.getOfferVolume()));
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
}
}
};
@Override
public void updateItem(final Offer offer, boolean empty) {
super.updateItem(offer, empty);
if (offer != null && !empty)
setText(formatter.formatFiat(offer.getOfferVolume()));
else
if (offer != null && !empty) {
if (offer.getPrice() == null) {
this.offer = offer;
model.priceFeed.currenciesUpdateFlagProperty().addListener(listener);
setText("N/A");
} else {
setText(formatter.formatFiat(offer.getOfferVolume()));
}
} else {
if (listener != null)
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
this.offer = null;
setText("");
}
}
};
}

View File

@ -29,6 +29,8 @@ import io.bitsquare.trade.offer.Offer;
import io.bitsquare.user.Preferences;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
@ -44,15 +46,16 @@ class MarketsChartsViewModel extends ActivatableViewModel {
private final OfferBook offerBook;
private final Preferences preferences;
private final PriceFeed priceFeed;
final PriceFeed priceFeed;
final ObjectProperty<TradeCurrency> tradeCurrency = new SimpleObjectProperty<>(CurrencyUtil.getDefaultTradeCurrency());
private final List<XYChart.Data> buyData = new ArrayList();
private final List<XYChart.Data> sellData = new ArrayList();
private final List<XYChart.Data> buyData = new ArrayList<>();
private final List<XYChart.Data> sellData = new ArrayList<>();
private final ObservableList<OfferBookListItem> offerBookListItems;
private final ListChangeListener<OfferBookListItem> listChangeListener;
private final ObservableList<Offer> top3BuyOfferList = FXCollections.observableArrayList();
private final ObservableList<Offer> top3SellOfferList = FXCollections.observableArrayList();
private final ChangeListener<Number> cacheFilledListener;
///////////////////////////////////////////////////////////////////////////////////////////
@ -67,15 +70,30 @@ class MarketsChartsViewModel extends ActivatableViewModel {
offerBookListItems = offerBook.getOfferBookListItems();
listChangeListener = c -> updateChartData(offerBookListItems);
cacheFilledListener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (!offerBookListItems.stream().filter(item -> item.getOffer().getPrice() == null).findAny().isPresent()) {
offerBook.fillOfferBookListItems();
updateChartData(offerBookListItems);
priceFeed.currenciesUpdateFlagProperty().removeListener(cacheFilledListener);
}
}
};
}
@Override
protected void activate() {
priceFeed.setType(PriceFeed.Type.LAST);
offerBookListItems.addListener(listChangeListener);
offerBook.fillOfferBookListItems();
updateChartData(offerBookListItems);
if (offerBookListItems.stream().filter(item -> item.getOffer().getPrice() == null).findAny().isPresent())
priceFeed.currenciesUpdateFlagProperty().addListener(cacheFilledListener);
if (!preferences.getUseStickyMarketPrice())
priceFeed.setCurrencyCode(tradeCurrency.get().getCode());
}

View File

@ -751,7 +751,9 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
isBtcInputValid(minAmount.get()).isValid &&
isFiatInputValid(price.get()).isValid &&
isFiatInputValid(volume.get()).isValid &&
dataModel.isMinAmountLessOrEqualAmount();
dataModel.isMinAmountLessOrEqualAmount() &&
!dataModel.useMarketBasedPrice.get() || dataModel.getMarketPriceMargin() != 0 &&
dataModel.useMarketBasedPrice.get() || dataModel.priceAsFiat.get().getValue() != 0;
isNextButtonDisabled.set(!inputDataValid);
// boolean notSufficientFees = dataModel.isWalletFunded.get() && dataModel.isMainNet.get() && !dataModel.isFeeFromFundingTxSufficient.get();
//isPlaceOfferButtonDisabled.set(createOfferRequested || !inputDataValid || notSufficientFees);

View File

@ -41,6 +41,8 @@ import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.trade.offer.Offer;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
@ -420,13 +422,35 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
public TableCell<OfferBookListItem, OfferBookListItem> call(
TableColumn<OfferBookListItem, OfferBookListItem> column) {
return new TableCell<OfferBookListItem, OfferBookListItem>() {
private OfferBookListItem offerBookListItem;
ChangeListener<Number> listener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (offerBookListItem != null && offerBookListItem.getOffer().getPrice() != null) {
setText(model.getPrice(offerBookListItem));
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
}
}
};
@Override
public void updateItem(final OfferBookListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(model.getPrice(item));
else
if (item != null && !empty) {
if (item.getOffer().getPrice() == null) {
this.offerBookListItem = item;
model.priceFeed.currenciesUpdateFlagProperty().addListener(listener);
setText("N/A");
} else {
setText(model.getPrice(item));
}
} else {
if (listener != null)
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
this.offerBookListItem = null;
setText("");
}
}
};
}
@ -448,13 +472,34 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
public TableCell<OfferBookListItem, OfferBookListItem> call(
TableColumn<OfferBookListItem, OfferBookListItem> column) {
return new TableCell<OfferBookListItem, OfferBookListItem>() {
private OfferBookListItem offerBookListItem;
ChangeListener<Number> listener = new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if (offerBookListItem != null && offerBookListItem.getOffer().getOfferVolume() != null) {
setText(model.getVolume(offerBookListItem));
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
}
}
};
@Override
public void updateItem(final OfferBookListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(model.getVolume(item));
else
if (item != null && !empty) {
if (item.getOffer().getPrice() == null) {
this.offerBookListItem = item;
model.priceFeed.currenciesUpdateFlagProperty().addListener(listener);
setText("N/A");
} else {
setText(model.getVolume(item));
}
} else {
if (listener != null)
model.priceFeed.currenciesUpdateFlagProperty().removeListener(listener);
this.offerBookListItem = null;
setText("");
}
}
};
}

View File

@ -70,7 +70,7 @@ class OfferBookViewModel extends ActivatableViewModel {
private final OfferBook offerBook;
private final Preferences preferences;
private final P2PService p2PService;
private final PriceFeed priceFeed;
final PriceFeed priceFeed;
private ClosedTradableManager closedTradableManager;
private Navigation navigation;
final BSFormatter formatter;
@ -272,19 +272,21 @@ class OfferBookViewModel extends ActivatableViewModel {
else
return formatter.formatFiat(price) + postFix;
} else {
return "";
return "N/A";
}
}
String getVolume(OfferBookListItem item) {
Fiat offerVolume = item.getOffer().getOfferVolume();
Fiat minOfferVolume = item.getOffer().getMinOfferVolume();
if (showAllTradeCurrenciesProperty.get())
return (item != null) ? formatter.formatFiatWithCode(offerVolume) +
" (" + formatter.formatFiatWithCode(minOfferVolume) + ")" : "";
else
return (item != null) ? formatter.formatFiat(offerVolume) +
" (" + formatter.formatFiat(minOfferVolume) + ")" : "";
if (offerVolume != null && minOfferVolume != null) {
if (showAllTradeCurrenciesProperty.get())
return formatter.formatFiatWithCode(offerVolume) + " (" + formatter.formatFiatWithCode(minOfferVolume) + ")";
else
return formatter.formatFiat(offerVolume) + " (" + formatter.formatFiat(minOfferVolume) + ")";
} else {
return "N/A";
}
}
String getPaymentMethod(OfferBookListItem item) {

View File

@ -148,7 +148,8 @@ class TakeOfferDataModel extends ActivatableDataModel {
protected void deactivate() {
removeBindings();
removeListeners();
tradeManager.onCancelAvailabilityRequest(offer);
if (offer != null)
tradeManager.onCancelAvailabilityRequest(offer);
}
@ -160,8 +161,6 @@ 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");
@ -309,7 +308,7 @@ class TakeOfferDataModel extends ActivatableDataModel {
///////////////////////////////////////////////////////////////////////////////////////////
void calculateVolume() {
if (offer != null &&
if (tradePrice != null && offer != null &&
amountAsCoin.get() != null &&
!amountAsCoin.get().isZero()) {
volumeAsFiat.set(new ExchangeRate(tradePrice).coinToFiat(amountAsCoin.get()));

View File

@ -59,6 +59,7 @@ import javafx.stage.Window;
import javafx.util.StringConverter;
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
import org.bitcoinj.core.Coin;
import org.bitcoinj.uri.BitcoinURI;
import org.controlsfx.control.PopOver;
import org.fxmisc.easybind.EasyBind;
@ -194,7 +195,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
///////////////////////////////////////////////////////////////////////////////////////////
public void initWithData(Offer offer) {
if (offer.getPrice() != null) {
model.initWithData(offer);
priceAsPercentageInputBox.setVisible(offer.getUseMarketBasedPrice());
@ -233,12 +233,12 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
priceAsPercentageTextField.setText(model.marketPriceMargin);
addressTextField.setPaymentLabel(model.getPaymentLabel());
addressTextField.setAddress(model.dataModel.getAddressEntry().getAddressString());
} else {
if (offer.getPrice() == null)
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) {
@ -247,7 +247,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
// called form parent as the view does not get notified when the tab is closed
public void onClose() {
if (model.dataModel.balance.get().isPositive() && !model.takeOfferCompleted.get()) {
Coin balance = model.dataModel.balance.get();
if (balance != null && balance.isPositive() && !model.takeOfferCompleted.get()) {
model.dataModel.swapTradeToSavings();
new Popup().information("You have already funds paid in.\n" +
"In the \"Funds/Available for withdrawal\" section you can withdraw those funds.")

View File

@ -32,7 +32,7 @@
<TableColumn text="Trade ID" fx:id="idColumn" minWidth="100"/>
<TableColumn text="Date/Time" fx:id="dateColumn" minWidth="130"/>
<TableColumn text="Trade amount in BTC" fx:id="tradeAmountColumn" minWidth="130"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="110"/>
<TableColumn text="Trade amount" fx:id="tradeVolumeColumn" minWidth="130"/>
<TableColumn text="Payment method" fx:id="paymentMethodColumn" minWidth="120"/>
<TableColumn text="My role" fx:id="roleColumn" minWidth="120" maxWidth="120"/>

View File

@ -27,8 +27,8 @@ import java.util.function.Consumer;
public class LocalhostNetworkNode extends NetworkNode {
private static final Logger log = LoggerFactory.getLogger(LocalhostNetworkNode.class);
private static volatile int simulateTorDelayTorNode = 200;
private static volatile int simulateTorDelayHiddenService = 300;
private static volatile int simulateTorDelayTorNode = 500;
private static volatile int simulateTorDelayHiddenService = 500;
public static void setSimulateTorDelayTorNode(int simulateTorDelayTorNode) {
LocalhostNetworkNode.simulateTorDelayTorNode = simulateTorDelayTorNode;