Clean up pending trades

This commit is contained in:
Manfred Karrer 2014-09-25 14:29:48 +02:00
parent 1a6fb9f5b5
commit 2840311853
12 changed files with 434 additions and 449 deletions

View File

@ -40,8 +40,7 @@ public class OfferListItem {
this.amount.set(BSFormatter.formatCoin(
offer.getAmount()) + " (" + BSFormatter.formatCoin(offer.getMinAmount()) + ")");
this.volume.set(BSFormatter.formatVolumeWithMinVolume(
offer.getOfferVolume(), offer.getMinOfferVolume()));
this.volume.set(BSFormatter.formatVolumeWithMinVolume(offer));
this.offerId = offer.getId();
}

View File

@ -17,22 +17,17 @@
package io.bitsquare.gui.main.orders.pending;
import io.bitsquare.locale.Country;
import io.bitsquare.trade.Offer;
import io.bitsquare.trade.Trade;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// TODO don't use inheritance
public class PendingTradesListItem {
/**
* We could remove that wrapper if it is not needed for additional UI only fields.
*/
class PendingTradesListItem {
private static final Logger log = LoggerFactory.getLogger(PendingTradesListItem.class);
private final Offer offer;
private final ObjectProperty<Country> bankAccountCountry = new SimpleObjectProperty<>();
private final Trade trade;
@ -40,20 +35,8 @@ public class PendingTradesListItem {
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
public PendingTradesListItem(Trade trade) {
PendingTradesListItem(Trade trade) {
this.trade = trade;
this.offer = trade.getOffer();
setBankAccountCountry(offer.getBankAccountCountry());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
void setBankAccountCountry(Country bankAccountCountry) {
this.bankAccountCountry.set(bankAccountCountry);
}
@ -61,20 +44,7 @@ public class PendingTradesListItem {
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
public Trade getTrade() {
Trade getTrade() {
return trade;
}
Offer getOffer() {
return offer;
}
Country getBankAccountCountry() {
return bankAccountCountry.get();
}
ObjectProperty<Country> bankAccountCountryProperty() {
return bankAccountCountry;
}
}

View File

@ -23,6 +23,7 @@ import io.bitsquare.btc.listeners.TxConfidenceListener;
import io.bitsquare.gui.UIModel;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.User;
import com.google.bitcoin.core.Coin;
import com.google.bitcoin.core.TransactionConfidence;
@ -31,12 +32,11 @@ import com.google.inject.Inject;
import java.util.Optional;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.MapChangeListener;
import javafx.collections.ObservableList;
@ -44,20 +44,26 @@ import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PendingTradesModel extends UIModel {
class PendingTradesModel extends UIModel {
private static final Logger log = LoggerFactory.getLogger(PendingTradesModel.class);
private final TradeManager tradeManager;
private WalletFacade walletFacade;
private final ObservableList<PendingTradesListItem> pendingTrades = FXCollections.observableArrayList();
private final WalletFacade walletFacade;
private final User user;
private PendingTradesListItem currentItem;
private final ObservableList<PendingTradesListItem> list = FXCollections.observableArrayList();
private PendingTradesListItem selectedItem;
private boolean isOfferer;
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
private TxConfidenceListener txConfidenceListener;
private ChangeListener<Trade.State> stateChangeListener;
private ChangeListener<Throwable> faultChangeListener;
private MapChangeListener<String, Trade> mapChangeListener;
final StringProperty txId = new SimpleStringProperty();
final ObjectProperty<Trade.State> tradeState = new SimpleObjectProperty<>();
final ObjectProperty<Throwable> fault = new SimpleObjectProperty<>();
final StringProperty txId = new SimpleStringProperty();
///////////////////////////////////////////////////////////////////////////////////////////
@ -65,9 +71,10 @@ public class PendingTradesModel extends UIModel {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PendingTradesModel(TradeManager tradeManager, WalletFacade walletFacade) {
PendingTradesModel(TradeManager tradeManager, WalletFacade walletFacade, User user) {
this.tradeManager = tradeManager;
this.walletFacade = walletFacade;
this.user = user;
}
@ -77,35 +84,51 @@ public class PendingTradesModel extends UIModel {
@Override
public void initialize() {
super.initialize();
// transform trades to list of PendingTradesListItems and keep it updated
tradeManager.getTrades().values().stream().forEach(e -> pendingTrades.add(new PendingTradesListItem(e)));
tradeManager.getTrades().addListener((MapChangeListener<String, Trade>) change -> {
stateChangeListener = (ov, oldValue, newValue) -> tradeState.set(newValue);
faultChangeListener = (ov, oldValue, newValue) -> fault.set(newValue);
mapChangeListener = change -> {
if (change.wasAdded())
pendingTrades.add(new PendingTradesListItem(change.getValueAdded()));
else if (change.wasAdded())
pendingTrades.remove(new PendingTradesListItem(change.getValueRemoved()));
});
list.add(new PendingTradesListItem(change.getValueAdded()));
else if (change.wasRemoved())
list.remove(new PendingTradesListItem(change.getValueRemoved()));
};
super.initialize();
}
@Override
public void activate() {
super.activate();
// TODO Check if we can really use tradeManager.getPendingTrade()
Optional<PendingTradesListItem> currentTradeItemOptional = pendingTrades.stream().filter((e) ->
tradeManager.getCurrentPendingTrade() != null &&
e.getTrade().getId().equals(tradeManager.getCurrentPendingTrade().getId())).findFirst();
list.clear();
// transform trades to list of PendingTradesListItems and keep it updated
tradeManager.getTrades().values().stream()
.filter(e -> e.getState() != Trade.State.CLOSED)
.forEach(e -> list.add(new PendingTradesListItem(e)));
tradeManager.getTrades().addListener(mapChangeListener);
// we sort by date
list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate()));
// select either currentPendingTrade or first in the list
Optional<PendingTradesListItem> currentTradeItemOptional = list.stream()
.filter((e) -> tradeManager.getCurrentPendingTrade() != null &&
tradeManager.getCurrentPendingTrade().getId().equals(e.getTrade().getId()))
.findFirst();
if (currentTradeItemOptional.isPresent())
selectPendingTrade(currentTradeItemOptional.get());
else if (pendingTrades.size() > 0)
selectPendingTrade(pendingTrades.get(0));
else if (list.size() > 0)
selectPendingTrade(list.get(0));
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
tradeManager.getTrades().removeListener(mapChangeListener);
selectPendingTrade(null);
}
@SuppressWarnings("EmptyMethod")
@ -119,79 +142,87 @@ public class PendingTradesModel extends UIModel {
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void selectPendingTrade(PendingTradesListItem item) {
if (item != null) {
currentItem = item;
isOfferer = tradeManager.isTradeMyOffer(currentItem.getTrade());
void selectPendingTrade(PendingTradesListItem item) {
// clean up previous selectedItem
if (selectedItem != null) {
Trade trade = getTrade();
trade.stateProperty().removeListener(stateChangeListener);
trade.faultProperty().removeListener(faultChangeListener);
if (txConfidenceListener != null)
walletFacade.removeTxConfidenceListener(txConfidenceListener);
}
selectedItem = item;
if (selectedItem != null) {
isOfferer = getTrade().getOffer().getMessagePublicKey().equals(user.getMessagePublicKey());
// we want to re-trigger a change if the state is the same but different trades
tradeState.set(null);
selectedIndex.set(pendingTrades.indexOf(item));
Trade currentTrade = currentItem.getTrade();
if (currentTrade.getDepositTx() != null) {
walletFacade.addTxConfidenceListener(new TxConfidenceListener(currentItem.getTrade()
.getDepositTx().getHashAsString()) {
@Override
public void onTransactionConfidenceChanged(TransactionConfidence confidence) {
updateConfidence(confidence);
}
});
updateConfidence(walletFacade.getConfidenceForTxId(currentItem.getTrade().getDepositTx()
.getHashAsString()));
}
Trade trade = getTrade();
txId.set(trade.getDepositTx().getHashAsString());
if (currentItem.getTrade().getDepositTx() != null)
txId.set(currentItem.getTrade().getDepositTx().getHashAsString());
else
txId.set("");
txConfidenceListener = new TxConfidenceListener(txId.get()) {
@Override
public void onTransactionConfidenceChanged(TransactionConfidence confidence) {
updateConfidence(confidence);
}
};
walletFacade.addTxConfidenceListener(txConfidenceListener);
updateConfidence(walletFacade.getConfidenceForTxId(txId.get()));
currentTrade.stateProperty().addListener((ov, oldValue, newValue) -> tradeState.set(newValue));
tradeState.set(currentTrade.stateProperty().get());
trade.stateProperty().addListener(stateChangeListener);
tradeState.set(trade.stateProperty().get());
currentTrade.faultProperty().addListener((ov, oldValue, newValue) -> fault.set(newValue));
fault.set(currentTrade.faultProperty().get());
trade.faultProperty().addListener(faultChangeListener);
fault.set(trade.faultProperty().get());
}
else {
txId.set(null);
tradeState.set(null);
}
}
public void paymentStarted() {
tradeManager.bankTransferInited(currentItem.getTrade().getId());
void fiatPaymentStarted() {
tradeManager.fiatPaymentStarted(getTrade().getId());
}
public void paymentReceived() {
tradeManager.onFiatReceived(currentItem.getTrade().getId());
void fiatPaymentReceived() {
tradeManager.fiatPaymentReceived(getTrade().getId());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<PendingTradesListItem> getPendingTrades() {
return pendingTrades;
ObservableList<PendingTradesListItem> getList() {
return list;
}
public boolean isOfferer() {
boolean isOfferer() {
return isOfferer;
}
public Trade getTrade() {
return currentItem.getTrade();
Trade getTrade() {
return selectedItem.getTrade();
}
public Coin getTotalFees() {
Coin tradeFee = isOfferer() ? FeePolicy.CREATE_OFFER_FEE : FeePolicy.TAKE_OFFER_FEE;
return tradeFee.add(FeePolicy.TX_FEE);
Coin getTotalFees() {
return FeePolicy.TX_FEE.add(isOfferer() ? FeePolicy.CREATE_OFFER_FEE : FeePolicy.TAKE_OFFER_FEE);
}
public WalletFacade getWalletFacade() {
WalletFacade getWalletFacade() {
return walletFacade;
}
PendingTradesListItem getSelectedItem() {
return selectedItem;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
@ -199,8 +230,12 @@ public class PendingTradesModel extends UIModel {
private void updateConfidence(TransactionConfidence confidence) {
if (confidence != null &&
confidence.getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING
&& currentItem.getTrade().getState() == Trade.State.DEPOSIT_PUBLISHED)
currentItem.getTrade().setState(Trade.State.DEPOSIT_CONFIRMED);
&& getTrade().getState() == Trade.State.DEPOSIT_PUBLISHED) {
// only set it once when actual state is DEPOSIT_PUBLISHED, and remove listener afterwards
getTrade().setState(Trade.State.DEPOSIT_CONFIRMED);
walletFacade.removeTxConfidenceListener(txConfidenceListener);
txConfidenceListener = null;
}
}
}

View File

@ -21,27 +21,24 @@ import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.PresentationModel;
import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.BSResources;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Trade;
import com.google.inject.Inject;
import javafx.beans.property.IntegerProperty;
import javafx.beans.InvalidationListener;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
private static final Logger log = LoggerFactory.getLogger(PendingTradesPM.class);
private BSFormatter formatter;
private BSResources resources;
private final BSFormatter formatter;
private InvalidationListener stateChangeListener;
enum State {
TAKER_SELLER_WAIT_TX_CONF,
@ -55,25 +52,20 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
OFFERER_BUYER_COMPLETED,
}
final StringProperty amount = new SimpleStringProperty();
final StringProperty price = new SimpleStringProperty();
final StringProperty volume = new SimpleStringProperty();
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
final ObjectProperty<State> state = new SimpleObjectProperty<>();
final ObjectProperty<Trade.State> tradeState = new SimpleObjectProperty<>();
final ObjectProperty<Throwable> fault = new SimpleObjectProperty<>();
final StringProperty txId = new SimpleStringProperty();
final ObjectProperty<State> state = new SimpleObjectProperty<>();
final ObjectProperty<Throwable> fault = new SimpleObjectProperty<>();
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PendingTradesPM(PendingTradesModel model, BSFormatter formatter, BSResources resources) {
PendingTradesPM(PendingTradesModel model, BSFormatter formatter) {
super(model);
this.formatter = formatter;
this.resources = resources;
}
@ -83,12 +75,7 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
@Override
public void initialize() {
selectedIndex.bind(model.selectedIndex);
txId.bind(model.txId);
model.tradeState.addListener((ov, oldValue, newValue) -> {
updateState();
});
fault.bind(model.fault);
stateChangeListener = (ov) -> updateState();
super.initialize();
}
@ -97,6 +84,10 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
public void activate() {
super.activate();
txId.bind(model.txId);
fault.bind(model.fault);
model.tradeState.addListener(stateChangeListener);
updateState();
}
@ -104,6 +95,11 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
@Override
public void deactivate() {
super.deactivate();
txId.unbind();
fault.unbind();
model.tradeState.removeListener(stateChangeListener);
}
@SuppressWarnings("EmptyMethod")
@ -117,17 +113,16 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void selectPendingTrade(PendingTradesListItem item) {
void selectPendingTrade(PendingTradesListItem item) {
model.selectPendingTrade(item);
}
public void paymentStarted() {
model.paymentStarted();
void fiatPaymentStarted() {
model.fiatPaymentStarted();
}
public void paymentReceived() {
model.paymentReceived();
void fiatPaymentReceived() {
model.fiatPaymentReceived();
}
@ -135,46 +130,36 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
ObservableList<PendingTradesListItem> getPendingTrades() {
return model.getPendingTrades();
ObservableList<PendingTradesListItem> getList() {
return new SortedList<>(model.getList());
}
public boolean isOfferer() {
boolean isOfferer() {
return model.isOfferer();
}
public WalletFacade getWalletFacade() {
WalletFacade getWalletFacade() {
return model.getWalletFacade();
}
PendingTradesListItem getSelectedItem() {
return model.getSelectedItem();
}
String getAmount(PendingTradesListItem item) {
return (item != null) ? BSFormatter.formatCoin(item.getOffer().getAmount()) +
" (" + BSFormatter.formatCoin(item.getOffer().getMinAmount()) + ")" : "";
return (item != null) ? BSFormatter.formatAmountWithMinAmount(item.getTrade().getOffer()) : "";
}
String getPrice(PendingTradesListItem item) {
return (item != null) ? BSFormatter.formatFiat(item.getOffer().getPrice()) : "";
return (item != null) ? BSFormatter.formatFiat(item.getTrade().getOffer().getPrice()) : "";
}
String getVolume(PendingTradesListItem item) {
return (item != null) ? BSFormatter.formatFiat(item.getOffer().getOfferVolume()) +
" (" + BSFormatter.formatFiat(item.getOffer().getMinOfferVolume()) + ")" : "";
}
String getBankAccountType(PendingTradesListItem item) {
return (item != null) ? BSResources.get(item.getOffer().getBankAccountType().toString()) : "";
return (item != null) ? BSFormatter.formatVolumeWithMinVolume(item.getTrade().getOffer()) : "";
}
String getDirectionLabel(PendingTradesListItem item) {
// mirror direction!
if (item != null) {
Direction direction = item.getOffer().getDirection() == Direction.BUY ? Direction.SELL : Direction.BUY;
return BSFormatter.formatDirection(direction, true);
}
else {
return "";
}
return (item != null) ? BSFormatter.formatDirection(item.getTrade().getOffer().getMirroredDirection()) : "";
}
String getPaymentMethod() {
@ -193,6 +178,13 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
return model.getTrade().getContract().getTakerBankAccount().getAccountSecondaryID();
}
String getDate(PendingTradesListItem item) {
return formatter.formatDateTime(item.getTrade().getDate());
}
String getTradeId(PendingTradesListItem item) {
return item.getTrade().getId();
}
String getTradeVolume() {
return formatter.formatCoinWithCode(model.getTrade().getTradeAmount());
@ -216,19 +208,18 @@ public class PendingTradesPM extends PresentationModel<PendingTradesModel> {
///////////////////////////////////////////////////////////////////////////////////////////
private void updateState() {
log.debug("updateState " + model.tradeState.get());
if (model.tradeState.get() != null) {
switch (model.tradeState.get()) {
case DEPOSIT_PUBLISHED:
state.set(model.isOfferer() ? State.OFFERER_BUYER_WAIT_TX_CONF : State.TAKER_SELLER_WAIT_TX_CONF);
break;
case DEPOSIT_CONFIRMED:
state.set(model.isOfferer() ? State.OFFERER_BUYER_START_PAYMENT : State
.TAKER_SELLER_WAIT_PAYMENT_STARTED);
state.set(model.isOfferer() ? State.OFFERER_BUYER_START_PAYMENT :
State.TAKER_SELLER_WAIT_PAYMENT_STARTED);
break;
case PAYMENT_STARTED:
state.set(model.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED : State
.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
state.set(model.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED :
State.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
break;
case PAYMENT_RECEIVED:
case PAYOUT_PUBLISHED:

View File

@ -42,12 +42,12 @@
<Insets top="10.0" left="-10" right="-10" bottom="-15"/>
</GridPane.margin>
<columns>
<TableColumn text="Amount in BTC (Min.)" fx:id="amountColumn" minWidth="130"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="130"/>
<TableColumn text="Amount in EUR (Min.)" fx:id="volumeColumn" minWidth="130"/>
<TableColumn text="Country" fx:id="countryColumn" minWidth="60"/>
<TableColumn text="Bank transfer type" fx:id="bankAccountTypeColumn" minWidth="130"/>
<TableColumn text="Trade tye" fx:id="directionColumn" minWidth="80" sortable="false"/>
<TableColumn text="Trade ID" fx:id="tradeIdColumn" minWidth="100" sortable="false"/>
<TableColumn text="Date" fx:id="dateColumn" minWidth="130"/>
<TableColumn text="Amount in BTC (Min.)" fx:id="amountColumn" minWidth="130" sortable="false"/>
<TableColumn text="Price" fx:id="priceColumn" minWidth="100" sortable="false"/>
<TableColumn text="Amount in EUR (Min.)" fx:id="volumeColumn" minWidth="130" sortable="false"/>
<TableColumn text="Trade type" fx:id="directionColumn" minWidth="80" sortable="false"/>
<TableColumn fx:id="selectColumn" minWidth="60" sortable="false" text=""/>
</columns>
</TableView>
@ -141,8 +141,8 @@
</TitledGroupBg>
<Label fx:id="btcLabel" GridPane.rowIndex="5" visible="false">
<GridPane.margin>
<Insets top="60.0"/>
<GridPane.margin>
<Insets top="60.0"/>
</GridPane.margin>
</Label>
<TextField fx:id="btcTextField" GridPane.rowIndex="5" GridPane.columnIndex="1" editable="false"

View File

@ -26,8 +26,6 @@ import io.bitsquare.gui.components.processbar.ProcessStepBar;
import io.bitsquare.gui.components.processbar.ProcessStepItem;
import io.bitsquare.gui.main.help.Help;
import io.bitsquare.gui.main.help.HelpId;
import io.bitsquare.gui.util.ImageUtil;
import io.bitsquare.locale.Country;
import java.net.URL;
@ -37,12 +35,11 @@ import java.util.ResourceBundle;
import javax.inject.Inject;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.util.Callback;
import org.slf4j.Logger;
@ -50,29 +47,26 @@ import org.slf4j.LoggerFactory;
public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
private static final Logger log = LoggerFactory.getLogger(PendingTradesViewCB.class);
public TitledGroupBg summaryGroupBg;
public Label btcLabel;
public TextField btcTextField;
public Label fiatLabel;
public TextField fiatTextField;
public Label feesLabel;
public TextField feesTextField;
public Label collateralLabel;
public TextField collateralTextField;
public InfoDisplay summaryInfoDisplay;
@FXML TitledGroupBg titledGroupBg, paymentsGroupBg;
@FXML TitledGroupBg titledGroupBg, paymentsGroupBg, summaryGroupBg;
@FXML ProcessStepBar processBar;
@FXML Label statusLabel, txIdLabel, paymentMethodLabel, holderNameLabel, primaryIdLabel, secondaryIdLabel;
@FXML TextField statusTextField, paymentMethodTextField;
@FXML Label statusLabel, txIdLabel, paymentMethodLabel, holderNameLabel, primaryIdLabel, secondaryIdLabel,
btcLabel, fiatLabel, feesLabel, collateralLabel;
@FXML TextField statusTextField, paymentMethodTextField, btcTextField, fiatTextField, feesTextField,
collateralTextField;
@FXML TxIdTextField txIdTextField;
@FXML InfoDisplay infoDisplay, paymentsInfoDisplay;
@FXML InfoDisplay infoDisplay, paymentsInfoDisplay, summaryInfoDisplay;
@FXML Button confirmPaymentReceiptButton, paymentsButton;
@FXML TextFieldWithCopyIcon holderNameTextField, secondaryIdTextField, primaryIdTextField;
@FXML TableView<PendingTradesListItem> table;
@FXML TableColumn<PendingTradesListItem, PendingTradesListItem> priceColumn, amountColumn, volumeColumn,
directionColumn, countryColumn, bankAccountTypeColumn, selectColumn;
directionColumn, dateColumn, tradeIdColumn, selectColumn;
private ChangeListener<PendingTradesListItem> selectedItemChangeListener;
private ListChangeListener<PendingTradesListItem> listChangeListener;
private ChangeListener<String> txIdChangeListener;
private ChangeListener<PendingTradesPM.State> offererStateChangeListener;
private ChangeListener<PendingTradesPM.State> takerStateChangeListener;
private ChangeListener<Throwable> faultChangeListener;
///////////////////////////////////////////////////////////////////////////////////////////
@ -80,7 +74,7 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public PendingTradesViewCB(PendingTradesPM presentationModel) {
PendingTradesViewCB(PendingTradesPM presentationModel) {
super(presentationModel);
}
@ -91,33 +85,41 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
@Override
public void initialize(URL url, ResourceBundle rb) {
setTradeIdColumnCellFactory();
setDirectionColumnCellFactory();
setAmountColumnCellFactory();
setPriceColumnCellFactory();
setVolumeColumnCellFactory();
setCountryColumnCellFactory();
setBankAccountTypeColumnCellFactory();
setDirectionColumnCellFactory();
setDateColumnCellFactory();
setSelectColumnCellFactory();
table.setItems(presentationModel.getPendingTrades());
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
table.getSelectionModel().selectedItemProperty().
addListener((obsValue, oldValue, newValue) -> {
if (oldValue != newValue) {
if (oldValue != null && newValue != null)
presentationModel.selectPendingTrade(newValue);
else if (newValue == null)
table.getSelectionModel().clearSelection();
}
else {
log.error("####### should not happen!");
}
});
txIdChangeListener = (ov, oldValue, newValue) ->
txIdTextField.setup(presentationModel.getWalletFacade(), newValue);
// need runLater to avoid conflict with user initiated selection
presentationModel.selectedIndex.addListener((ov, oldValue, newValue) ->
Platform.runLater(() -> table.getSelectionModel().select((int) newValue)));
selectedItemChangeListener = (obsValue, oldValue, newValue) -> {
if (oldValue != newValue) {
if (oldValue != null && newValue != null)
presentationModel.selectPendingTrade(newValue);
else if (newValue == null)
table.getSelectionModel().clearSelection();
}
else {
log.warn("should never happen!");
}
};
listChangeListener = change -> {
change.next();
if ((change.wasAdded() && change.getList().size() == 1) ||
(change.wasRemoved() && change.getList().size() == 0))
updateScreen();
};
offererStateChangeListener = (ov, oldValue, newValue) -> applyOffererState(newValue);
takerStateChangeListener = (ov, oldValue, newValue) -> applyTakerState(newValue);
faultChangeListener = (ov, oldValue, newValue) -> onFault(newValue);
super.initialize(url, rb);
}
@ -126,39 +128,33 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
public void activate() {
super.activate();
if (!presentationModel.getPendingTrades().isEmpty()) {
titledGroupBg.setVisible(true);
processBar.setVisible(true);
statusLabel.setVisible(true);
statusTextField.setVisible(true);
txIdLabel.setVisible(true);
txIdTextField.setVisible(true);
infoDisplay.setVisible(true);
table.setItems(presentationModel.getList());
if (presentationModel.isOfferer())
setupScreenForOfferer();
else
setupScreenForTaker();
presentationModel.getList().addListener(listChangeListener);
presentationModel.txId.addListener(txIdChangeListener);
presentationModel.fault.addListener(faultChangeListener);
presentationModel.txId.addListener((ov, oldValue, newValue) ->
txIdTextField.setup(presentationModel.getWalletFacade(), newValue));
txIdTextField.setup(presentationModel.getWalletFacade(), presentationModel.txId.get());
}
else {
titledGroupBg.setVisible(false);
processBar.setVisible(false);
statusLabel.setVisible(false);
statusTextField.setVisible(false);
txIdLabel.setVisible(false);
txIdTextField.setVisible(false);
infoDisplay.setVisible(false);
}
txIdTextField.setup(presentationModel.getWalletFacade(), presentationModel.txId.get());
table.getSelectionModel().select(presentationModel.getSelectedItem());
// TODO Set focus does not work yet...
/* table.requestFocus();
table.getFocusModel().focus( table.getSelectionModel().getSelectedIndex());*/
updateScreen();
}
@SuppressWarnings("EmptyMethod")
@Override
public void deactivate() {
super.deactivate();
table.getSelectionModel().selectedItemProperty().removeListener(selectedItemChangeListener);
presentationModel.getList().removeListener(listChangeListener);
presentationModel.txId.removeListener(txIdChangeListener);
presentationModel.fault.removeListener(faultChangeListener);
presentationModel.state.removeListener(offererStateChangeListener);
presentationModel.state.removeListener(takerStateChangeListener);
}
@SuppressWarnings("EmptyMethod")
@ -174,12 +170,12 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
@FXML
void onPaymentStarted() {
presentationModel.paymentStarted();
presentationModel.fiatPaymentStarted();
}
@FXML
void onConfirmPaymentReceipt() {
presentationModel.paymentReceived();
presentationModel.fiatPaymentReceived();
}
@FXML
@ -202,10 +198,25 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void updateScreen() {
boolean dataAvailable = !presentationModel.getList().isEmpty();
titledGroupBg.setVisible(dataAvailable);
processBar.setVisible(dataAvailable);
statusLabel.setVisible(dataAvailable);
statusTextField.setVisible(dataAvailable);
txIdLabel.setVisible(dataAvailable);
txIdTextField.setVisible(dataAvailable);
infoDisplay.setVisible(dataAvailable);
if (dataAvailable) {
if (presentationModel.isOfferer())
setupScreenForOfferer();
else
setupScreenForTaker();
}
}
private void setupScreenForOfferer() {
log.debug("setupScreenForOfferer");
if (processBar.getProcessStepItems() == null) {
List<ProcessStepItem> items = new ArrayList<>();
items.add(new ProcessStepItem("Wait for block chain confirmation"));
@ -215,115 +226,10 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
processBar.setProcessStepItems(items);
}
presentationModel.state.addListener((ov, oldValue, newValue) -> applyOffererState(newValue));
presentationModel.state.addListener(offererStateChangeListener);
applyOffererState(presentationModel.state.get());
}
private void applyOffererState(PendingTradesPM.State state) {
paymentsGroupBg.setVisible(false);
paymentMethodLabel.setVisible(false);
holderNameLabel.setVisible(false);
primaryIdLabel.setVisible(false);
secondaryIdLabel.setVisible(false);
paymentMethodTextField.setVisible(false);
paymentsInfoDisplay.setVisible(false);
paymentsButton.setVisible(false);
holderNameTextField.setVisible(false);
primaryIdTextField.setVisible(false);
secondaryIdTextField.setVisible(false);
summaryGroupBg.setVisible(false);
btcLabel.setVisible(false);
btcTextField.setVisible(false);
fiatLabel.setVisible(false);
fiatTextField.setVisible(false);
feesLabel.setVisible(false);
feesTextField.setVisible(false);
collateralLabel.setVisible(false);
collateralTextField.setVisible(false);
summaryInfoDisplay.setVisible(false);
if (state != null) {
switch (state) {
case OFFERER_BUYER_WAIT_TX_CONF:
processBar.setSelectedIndex(0);
statusTextField.setText("Deposit transaction is published. Waiting " +
"for at least 1 confirmation");
infoDisplay.setText("Deposit transaction has bee published. You need to wait for at least one " +
"block " +
"chain confirmation. After that you need to make the payments transfer.");
break;
case OFFERER_BUYER_START_PAYMENT:
processBar.setSelectedIndex(1);
statusTextField.setText("Deposit transaction has at least 1 confirmation. Start payment.");
infoDisplay.setText("Deposit transaction has at least one blockchain confirmation. You need to " +
"start " +
"the payment.");
paymentsGroupBg.setVisible(true);
paymentMethodLabel.setVisible(true);
holderNameLabel.setVisible(true);
primaryIdLabel.setVisible(true);
secondaryIdLabel.setVisible(true);
paymentMethodTextField.setVisible(true);
paymentsInfoDisplay.setVisible(true);
holderNameTextField.setVisible(true);
primaryIdTextField.setVisible(true);
secondaryIdTextField.setVisible(true);
paymentsButton.setVisible(true);
paymentMethodTextField.setText(presentationModel.getPaymentMethod());
holderNameTextField.setText(presentationModel.getHolderName());
primaryIdTextField.setText(presentationModel.getPrimaryId());
secondaryIdTextField.setText(presentationModel.getSecondaryId());
paymentsInfoDisplay.setText("Copy and paste the payments accounts data to your payments " +
"accounts web page and transfer the payment to the other trader. When the transfer is " +
"done confirm it with the 'Payment started' button.");
break;
case OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED:
processBar.setSelectedIndex(2);
statusTextField.setText("Waiting until the other trader has received your payment.");
infoDisplay.setText("Waiting until the other trader has confirmed that he has received your " +
"payment.");
break;
case OFFERER_BUYER_COMPLETED:
processBar.setSelectedIndex(3);
statusTextField.setText("Trade has successfully completed.");
infoDisplay.setText("Trade has successfully completed. You can find the details to that trade" +
" in the closed trades section.");
summaryGroupBg.setVisible(true);
btcLabel.setVisible(true);
btcTextField.setVisible(true);
fiatLabel.setVisible(true);
fiatTextField.setVisible(true);
feesLabel.setVisible(true);
feesTextField.setVisible(true);
collateralLabel.setVisible(true);
collateralTextField.setVisible(true);
summaryInfoDisplay.setVisible(true);
btcLabel.setText("You have bought:");
fiatLabel.setText("You have paid:");
btcTextField.setText(presentationModel.getTradeVolume());
fiatTextField.setText(presentationModel.getFiatVolume());
feesTextField.setText(presentationModel.getTotalFees());
collateralTextField.setText(presentationModel.getCollateral());
summaryInfoDisplay.setText("You can open that summary any time in the closed orders section.");
break;
}
}
else {
processBar.reset();
}
}
private void setupScreenForTaker() {
log.debug("setupScreenForTaker");
if (processBar.getProcessStepItems() == null) {
@ -335,37 +241,90 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
processBar.setProcessStepItems(items);
}
presentationModel.state.addListener((ov, oldValue, newValue) -> applyTakerState(newValue));
presentationModel.state.addListener(takerStateChangeListener);
applyTakerState(presentationModel.state.get());
}
private void applyTakerState(PendingTradesPM.State state) {
log.debug("#### state " + state);
private void applyOffererState(PendingTradesPM.State state) {
setPaymentsControlsVisible(false);
setSummaryControlsVisible(false);
processBar.reset();
if (state != null) {
switch (state) {
case OFFERER_BUYER_WAIT_TX_CONF:
processBar.setSelectedIndex(0);
statusTextField.setText("Deposit transaction is published. Waiting " +
"for at least 1 confirmation");
infoDisplay.setText("Deposit transaction has bee published. You need to wait for at least one " +
"block chain confirmation. After that you need to make the payments transfer.");
break;
case OFFERER_BUYER_START_PAYMENT:
processBar.setSelectedIndex(1);
setPaymentsControlsVisible(true);
statusTextField.setText("Deposit transaction has at least 1 confirmation. Start payment.");
infoDisplay.setText("Deposit transaction has at least one blockchain confirmation. You need to " +
"start the payment.");
paymentMethodTextField.setText(presentationModel.getPaymentMethod());
holderNameTextField.setText(presentationModel.getHolderName());
primaryIdTextField.setText(presentationModel.getPrimaryId());
secondaryIdTextField.setText(presentationModel.getSecondaryId());
paymentsInfoDisplay.setText("Copy and paste the payments accounts data to your payments " +
"accounts web page and transfer the payment to the other trader. When the transfer is " +
"done confirm it with the 'Payment started' button.");
break;
case OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED:
processBar.setSelectedIndex(2);
statusTextField.setText("Waiting until the other trader has received your payment.");
infoDisplay.setText("Waiting until the other trader has confirmed that he has received your " +
"payment.");
break;
case OFFERER_BUYER_COMPLETED:
processBar.setSelectedIndex(3);
setSummaryControlsVisible(true);
statusTextField.setText("Trade has successfully completed.");
infoDisplay.setText("Trade has successfully completed. You can find the details to that trade" +
" in the closed trades section.");
btcLabel.setText("You have bought:");
fiatLabel.setText("You have paid:");
btcTextField.setText(presentationModel.getTradeVolume());
fiatTextField.setText(presentationModel.getFiatVolume());
feesTextField.setText(presentationModel.getTotalFees());
collateralTextField.setText(presentationModel.getCollateral());
summaryInfoDisplay.setText("You can open that summary any time in the closed orders section.");
break;
}
}
}
private void applyTakerState(PendingTradesPM.State state) {
confirmPaymentReceiptButton.setVisible(false);
summaryGroupBg.setVisible(false);
btcLabel.setVisible(false);
btcTextField.setVisible(false);
fiatLabel.setVisible(false);
fiatTextField.setVisible(false);
feesLabel.setVisible(false);
feesTextField.setVisible(false);
collateralLabel.setVisible(false);
collateralTextField.setVisible(false);
summaryInfoDisplay.setVisible(false);
setSummaryControlsVisible(false);
processBar.reset();
if (state != null) {
switch (state) {
case TAKER_SELLER_WAIT_TX_CONF:
processBar.setSelectedIndex(0);
statusTextField.setText("Deposit transaction is published. Waiting for at least 1 confirmation");
infoDisplay.setText("Deposit transaction has bee published. He needs to wait for at least one " +
"blockchain " +
"confirmation.");
"blockchain confirmation.");
break;
case TAKER_SELLER_WAIT_PAYMENT_STARTED:
processBar.setSelectedIndex(1);
statusTextField.setText("Deposit transaction has at least 1 confirmation. Waiting that other " +
"trader starts payment.");
infoDisplay.setText("Deposit transaction has at least one blockchain " +
@ -374,30 +333,24 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
break;
case TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT:
processBar.setSelectedIndex(2);
confirmPaymentReceiptButton.setVisible(true);
statusTextField.setText("Payment is on the way. Check your payments account and confirm when you " +
"have received the payment.");
infoDisplay.setText("The other trader has started the payment. You need to check your payments " +
"account and confirm the payment when the money has arrived there.");
confirmPaymentReceiptButton.setVisible(true);
break;
case TAKER_SELLER_COMPLETED:
processBar.setSelectedIndex(3);
setSummaryControlsVisible(true);
statusTextField.setText("Trade has successfully completed.");
infoDisplay.setText("Trade has successfully completed. You can find the details to that trade" +
" in the closed trades section.");
summaryGroupBg.setVisible(true);
btcLabel.setVisible(true);
btcTextField.setVisible(true);
fiatLabel.setVisible(true);
fiatTextField.setVisible(true);
feesLabel.setVisible(true);
feesTextField.setVisible(true);
collateralLabel.setVisible(true);
collateralTextField.setVisible(true);
summaryInfoDisplay.setVisible(true);
btcLabel.setText("You have sold:");
fiatLabel.setText("You have received:");
btcTextField.setText(presentationModel.getTradeVolume());
@ -408,9 +361,38 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
break;
}
}
else {
processBar.reset();
}
}
private void onFault(Throwable fault) {
// TODO
log.error(fault.toString());
}
private void setPaymentsControlsVisible(boolean visible) {
paymentsGroupBg.setVisible(visible);
paymentMethodLabel.setVisible(visible);
holderNameLabel.setVisible(visible);
primaryIdLabel.setVisible(visible);
secondaryIdLabel.setVisible(visible);
paymentMethodTextField.setVisible(visible);
paymentsInfoDisplay.setVisible(visible);
paymentsButton.setVisible(visible);
holderNameTextField.setVisible(visible);
primaryIdTextField.setVisible(visible);
secondaryIdTextField.setVisible(visible);
}
private void setSummaryControlsVisible(boolean visible) {
summaryGroupBg.setVisible(visible);
btcLabel.setVisible(visible);
btcTextField.setVisible(visible);
fiatLabel.setVisible(visible);
fiatTextField.setVisible(visible);
feesLabel.setVisible(visible);
feesTextField.setVisible(visible);
collateralLabel.setVisible(visible);
collateralTextField.setVisible(visible);
summaryInfoDisplay.setVisible(visible);
}
@ -418,6 +400,54 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
// CellFactories
///////////////////////////////////////////////////////////////////////////////////////////
private void setDateColumnCellFactory() {
dateColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
dateColumn.setCellFactory(
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call(
TableColumn<PendingTradesListItem, PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null)
setText(presentationModel.getDate(item));
else
setText("");
}
};
}
});
}
private void setTradeIdColumnCellFactory() {
tradeIdColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
tradeIdColumn.setCellFactory(
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call(
TableColumn<PendingTradesListItem, PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(presentationModel.getTradeId(item));
Tooltip.install(this, new Tooltip(presentationModel.getTradeId(item)));
}
else {
setText("");
}
}
};
}
});
}
private void setAmountColumnCellFactory() {
amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
amountColumn.setCellFactory(
@ -497,62 +527,8 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
});
}
private void setCountryColumnCellFactory() {
countryColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
countryColumn.setCellFactory(
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call(
TableColumn<PendingTradesListItem, PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
final HBox hBox = new HBox();
{
hBox.setSpacing(3);
hBox.setAlignment(Pos.CENTER);
setGraphic(hBox);
}
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
hBox.getChildren().clear();
if (item != null) {
Country country = item.getOffer().getBankAccountCountry();
hBox.getChildren().add(ImageUtil.getCountryIconImageView(item
.getOffer().getBankAccountCountry()));
Tooltip.install(this, new Tooltip(country.getName()));
}
}
};
}
});
}
private void setBankAccountTypeColumnCellFactory() {
bankAccountTypeColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
bankAccountTypeColumn.setCellFactory(
new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>, TableCell<PendingTradesListItem,
PendingTradesListItem>>() {
@Override
public TableCell<PendingTradesListItem, PendingTradesListItem> call(
TableColumn<PendingTradesListItem, PendingTradesListItem> column) {
return new TableCell<PendingTradesListItem, PendingTradesListItem>() {
@Override
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
setText(presentationModel.getBankAccountType(item));
}
};
}
});
}
private void setSelectColumnCellFactory() {
selectColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper(offer.getValue()));
selectColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
selectColumn.setCellFactory(new Callback<TableColumn<PendingTradesListItem, PendingTradesListItem>,
TableCell<PendingTradesListItem, PendingTradesListItem>>() {
@Override
@ -581,7 +557,5 @@ public class PendingTradesViewCB extends CachedViewCB<PendingTradesPM> {
}
});
}
}

View File

@ -201,9 +201,7 @@ class OrderBookPM extends PresentationModel<OrderBookModel> {
}
String getDirectionLabel(Offer offer) {
// mirror direction!
Direction direction = offer.getDirection() == Direction.BUY ? Direction.SELL : Direction.BUY;
return BSFormatter.formatDirection(direction, true);
return BSFormatter.formatDirection(offer.getMirroredDirection());
}
Direction getDirection() {

View File

@ -141,8 +141,6 @@ public class OrderBookViewCB extends CachedViewCB<OrderBookPM> {
SortedList<OrderBookListItem> offerList = presentationModel.getOfferList();
orderBookTable.setItems(offerList);
offerList.comparatorProperty().bind(orderBookTable.comparatorProperty());
priceColumn.setSortType((presentationModel.getDirection() == Direction.BUY) ?
TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING);
orderBookTable.sort();

View File

@ -21,6 +21,7 @@ import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.locale.BSResources;
import io.bitsquare.locale.Country;
import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer;
import io.bitsquare.user.User;
import com.google.bitcoin.core.Coin;
@ -261,6 +262,10 @@ public class BSFormatter {
}
}
public static String formatDirection(Direction direction) {
return formatDirection(direction, true);
}
public static String formatDirection(Direction direction, boolean allUpperCase) {
String result = (direction == Direction.BUY) ? "Buy" : "Sell";
if (allUpperCase) {
@ -269,6 +274,14 @@ public class BSFormatter {
return result;
}
public static String formatAmountWithMinAmount(Offer offer) {
return formatCoin(offer.getAmount()) + " (" + BSFormatter.formatCoin(offer.getMinAmount()) + ")";
}
public static String formatVolumeWithMinVolume(Offer offer) {
return BSFormatter.formatFiat(offer.getOfferVolume()) +
" (" + BSFormatter.formatFiat(offer.getMinOfferVolume()) + ")";
}
public static String countryLocalesToString(List<Country> countries) {
return countries.stream().map(e -> e.getName()).collect(Collectors.joining(", "));
@ -317,10 +330,6 @@ public class BSFormatter {
return decimalFormat.format(value / 100) + " %";
}
public static String formatVolumeWithMinVolume(Fiat volume, Fiat minVolume) {
return formatFiat(volume) + " (" + formatFiat(minVolume) + ")";
}
private static String cleanInput(String input) {
input = input.replace(",", ".");
// don't use String.valueOf(Double.parseDouble(input)) as return value as it gives scientific

View File

@ -135,6 +135,10 @@ public class Offer implements Serializable {
return direction;
}
public Direction getMirroredDirection() {
return direction == Direction.BUY ? Direction.SELL : Direction.BUY;
}
public BankAccountType getBankAccountType() {
return bankAccountType;
}

View File

@ -23,6 +23,8 @@ import com.google.bitcoin.utils.Fiat;
import java.io.Serializable;
import java.util.Date;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -46,11 +48,13 @@ public class Trade implements Serializable {
PAYMENT_STARTED,
PAYMENT_RECEIVED, /* For taker only*/
PAYOUT_PUBLISHED,
FAULT
FAULT,
CLOSED
}
private final Offer offer;
private final Date date;
private String takeOfferFeeTxID;
private Coin tradeAmount;
private Contract contract;
@ -76,6 +80,7 @@ public class Trade implements Serializable {
public Trade(Offer offer) {
this.offer = offer;
date = new Date();
state = State.OPEN;
}
@ -133,6 +138,7 @@ public class Trade implements Serializable {
faultProperty().set(fault);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
@ -181,6 +187,10 @@ public class Trade implements Serializable {
return contractAsJson;
}
public Date getDate() {
return date;
}
// When serialized those transient properties are not instantiated, so we need to instantiate them at first access
public ObjectProperty<Transaction> depositTxProperty() {
if (_depositTx == null)

View File

@ -86,7 +86,7 @@ public class TradeManager {
private final ObservableMap<String, Offer> offers = FXCollections.observableHashMap();
private final ObservableMap<String, Trade> trades = FXCollections.observableHashMap();
// TODO There might be multiple pending trades
// the latest pending trade
private Trade currentPendingTrade;
@ -385,7 +385,7 @@ public class TradeManager {
//TODO we don't support interruptions yet.
// If the user has shut down the app we lose the offererAsBuyerProtocolMap
// Also we don't support yet offline messaging (mail box)
public void bankTransferInited(String tradeId) {
public void fiatPaymentStarted(String tradeId) {
if (offererAsBuyerProtocolMap.get(tradeId) != null) {
offererAsBuyerProtocolMap.get(tradeId).onUIEventBankTransferInited();
trades.get(tradeId).setState(Trade.State.PAYMENT_STARTED);
@ -398,7 +398,7 @@ public class TradeManager {
}
}
public void onFiatReceived(String tradeId) {
public void fiatPaymentReceived(String tradeId) {
takerAsSellerProtocolMap.get(tradeId).onUIEventFiatReceived();
trades.get(tradeId).setState(Trade.State.PAYMENT_RECEIVED);
persistTrades();
@ -454,9 +454,6 @@ public class TradeManager {
return trades.containsKey(offer.getId());
}
public boolean isTradeMyOffer(Trade trade) {
return trade.getOffer().getMessagePublicKey().equals(user.getMessagePublicKey());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters