Trade process error handling

This commit is contained in:
Manfred Karrer 2015-04-23 00:35:37 +02:00
parent 3f6f8dd160
commit ca3d1c96f2
56 changed files with 306 additions and 243 deletions

View file

@ -158,7 +158,7 @@ public class BitsquareApp extends Application {
primaryStage.show();
//TODO just temp.
// showDebugWindow();
showDebugWindow();
} catch (Throwable throwable) {
showErrorPopup(throwable, true);
}

View file

@ -34,6 +34,7 @@ import org.bitcoinj.utils.Fiat;
import com.google.inject.Inject;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -145,7 +146,9 @@ class TakeOfferDataModel implements Activatable, DataModel {
};
updateBalance(walletService.getBalanceForAddress(addressEntry.getAddress()));
tradeManager.onCheckOfferAvailability(offer);
// delay a bit to get the listeners called
offer.resetState();
Platform.runLater(() -> tradeManager.onCheckOfferAvailability(offer));
}

View file

@ -24,7 +24,7 @@
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" tabClosingPolicy="UNAVAILABLE"
xmlns:fx="http://javafx.com/fxml">
<Tab fx:id="offersTab" text="Open offers"/>
<Tab fx:id="openOffersTab" text="Open offers"/>
<Tab fx:id="openTradesTab" text="Open trades"/>
<Tab fx:id="closedTradesTab" text="History"/>

View file

@ -28,7 +28,6 @@ import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.portfolio.closedtrades.ClosedTradesView;
import io.bitsquare.gui.main.portfolio.openoffer.OpenOffersView;
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesView;
import io.bitsquare.trade.TradeManager;
import javax.inject.Inject;
@ -39,7 +38,7 @@ import javafx.scene.control.*;
@FxmlView
public class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable> {
@FXML Tab offersTab, openTradesTab, closedTradesTab;
@FXML Tab openOffersTab, openTradesTab, closedTradesTab;
private Tab currentTab;
private Navigation.Listener navigationListener;
@ -49,7 +48,7 @@ public class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable>
private final Navigation navigation;
@Inject
public PortfolioView(CachingViewLoader viewLoader, Navigation navigation, TradeManager tradeManager) {
public PortfolioView(CachingViewLoader viewLoader, Navigation navigation) {
this.viewLoader = viewLoader;
this.navigation = navigation;
}
@ -57,12 +56,14 @@ public class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable>
@Override
public void initialize() {
navigationListener = viewPath -> {
log.debug("navigationListener");
if (viewPath.size() == 3 && viewPath.indexOf(PortfolioView.class) == 1)
loadView(viewPath.tip());
};
tabChangeListener = (ov, oldValue, newValue) -> {
if (newValue == offersTab)
log.debug("tabChangeListener");
if (newValue == openOffersTab)
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class);
else if (newValue == openTradesTab)
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
@ -76,10 +77,12 @@ public class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable>
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
navigation.addListener(navigationListener);
/* if (tradeManager.getPendingTrades().size() == 0)
navigation.navigateTo(MainView.class, PortfolioView.class, OffersView.class);
else
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);*/
if (root.getSelectionModel().getSelectedItem() == openOffersTab)
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class);
else if (root.getSelectionModel().getSelectedItem() == openTradesTab)
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
else if (root.getSelectionModel().getSelectedItem() == closedTradesTab)
navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class);
}
@Override
@ -96,7 +99,7 @@ public class PortfolioView extends ActivatableViewAndModel<TabPane, Activatable>
View view = viewLoader.load(viewClass);
if (view instanceof OpenOffersView) currentTab = offersTab;
if (view instanceof OpenOffersView) currentTab = openOffersTab;
else if (view instanceof PendingTradesView) currentTab = openTradesTab;
else if (view instanceof ClosedTradesView) currentTab = closedTradesTab;

View file

@ -92,6 +92,10 @@ public class BuyerSubView extends TradeSubView {
tradeStepDetailsView.deactivate();
switch (state) {
case UNDEFINED:
/* showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Trade is in an incomplete state.");*/
break;
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
showItem(waitTxInBlockchain);
@ -144,6 +148,14 @@ public class BuyerSubView extends TradeSubView {
"You can review the details to that trade any time in the closed trades screen.");
completedView.setWithdrawAmountTextFieldText(model.getPayoutAmount());
break;
case CLOSED:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Trade is closed");
break;
case FAULT:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Error occured");
break;
/*case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;

View file

@ -108,12 +108,12 @@ class PendingTradesDataModel implements Activatable, DataModel {
private void onListChanged() {
list.clear();
list.addAll(tradeManager.getPendingTrades().stream().map(PendingTradesListItem::new).collect(Collectors.toList()));
list.addAll(tradeManager.getPendingTrades().stream().filter(e -> !e.isFaultState())
.map(PendingTradesListItem::new).collect(Collectors.toList()));
// we sort by date, earliest first
list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate()));
log.debug("onListChanged {}", list.size());
if (list.size() > 0)
onSelectTrade(list.get(0));
else if (list.size() == 0)
@ -131,7 +131,6 @@ class PendingTradesDataModel implements Activatable, DataModel {
///////////////////////////////////////////////////////////////////////////////////////////
void onSelectTrade(PendingTradesListItem item) {
log.debug("selectTrade {} {}", item != null, item != null ? item.getTrade().getId() : "null");
// clean up previous selectedItem
unbindStates();
@ -176,7 +175,6 @@ class PendingTradesDataModel implements Activatable, DataModel {
toAddress,
trade,
() -> {
log.debug("requestWithdraw was successful");
Platform.runLater(() -> navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class));
},
(errorMessage, throwable) -> {

View file

@ -53,44 +53,30 @@ import org.slf4j.LoggerFactory;
public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataModel> implements ViewModel {
private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class);
/* enum ViewState {
UNDEFINED,
WAIT_FOR_BLOCKCHAIN_CONFIRMATION,
WAIT_FOR_FIAT_PAYMENT_STARTED,
REQUEST_CONFIRM_FIAT_PAYMENT_RECEIVED,
SELLER_REQUEST_PAYOUT_FINALIZE_MSG_SENT,
SELLER_PAYOUT_FINALIZED,
SELLER_COMPLETED,
WAIT_FOR_BLOCKCHAIN_CONFIRMATION,
BUYER_START_PAYMENT,
BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED,
BUYER_PAYOUT_FINALIZED,
BUYER_COMPLETED,
MESSAGE_SENDING_FAILED,
TIMEOUT,
EXCEPTION
}*/
interface State {
}
enum BuyerState implements State {
UNDEFINED,
WAIT_FOR_BLOCKCHAIN_CONFIRMATION,
REQUEST_START_FIAT_PAYMENT,
WAIT_FOR_FIAT_PAYMENT_RECEIPT,
WAIT_FOR_UNLOCK_PAYOUT,
REQUEST_WITHDRAWAL
REQUEST_WITHDRAWAL,
CLOSED,
FAULT
}
enum SellerState implements State {
UNDEFINED,
WAIT_FOR_BLOCKCHAIN_CONFIRMATION,
WAIT_FOR_FIAT_PAYMENT_STARTED,
REQUEST_CONFIRM_FIAT_PAYMENT_RECEIVED,
WAIT_FOR_PAYOUT_TX,
WAIT_FOR_UNLOCK_PAYOUT,
REQUEST_WITHDRAWAL
REQUEST_WITHDRAWAL,
CLOSED,
FAULT
}
private final BSFormatter formatter;
@ -98,8 +84,8 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
private final InvalidationListener buyerStateListener;
private final BtcAddressValidator btcAddressValidator;
private final ObjectProperty<BuyerState> buyerState = new SimpleObjectProperty<>(BuyerState.WAIT_FOR_BLOCKCHAIN_CONFIRMATION);
private final ObjectProperty<SellerState> sellerState = new SimpleObjectProperty<>(SellerState.WAIT_FOR_BLOCKCHAIN_CONFIRMATION);
private final ObjectProperty<BuyerState> buyerState = new SimpleObjectProperty<>(BuyerState.UNDEFINED);
private final ObjectProperty<SellerState> sellerState = new SimpleObjectProperty<>(SellerState.UNDEFINED);
private final StringProperty txId = new SimpleStringProperty();
private final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
@ -191,6 +177,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
public void onWithdrawRequest(String withdrawToAddress) {
dataModel.onWithdrawRequest(withdrawToAddress);
if (dataModel.getSellerProcessState().get() instanceof SellerTradeState.ProcessState)
sellerState.setValue(SellerState.CLOSED);
else
buyerState.setValue(BuyerState.CLOSED);
}
public void withdrawAddressFocusOut(String text) {
@ -338,6 +328,8 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
if (processState != null) {
switch (processState) {
case UNDEFINED:
sellerState.set(SellerState.UNDEFINED);
break;
case DEPOSIT_PUBLISHED_MSG_RECEIVED:
sellerState.set(SellerState.WAIT_FOR_BLOCKCHAIN_CONFIRMATION);
@ -373,17 +365,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
break;
/* case PAYOUT_BROAD_CASTED_FAILED:
// sellerState.set(SellerState.EXCEPTION);
case FAULT:
sellerState.set(SellerState.FAULT);
break;
case MESSAGE_SENDING_FAILED:
//sellerState.set(SellerState.MESSAGE_SENDING_FAILED);
break;
case EXCEPTION:
// sellerState.set(SellerState.EXCEPTION);
break;*/
default:
log.warn("unhandled processState " + processState);
break;
@ -402,6 +387,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
if (processState != null) {
switch (processState) {
case UNDEFINED:
sellerState.set(SellerState.UNDEFINED);
break;
@ -436,18 +422,10 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
break;
/* case PAYOUT_BROAD_CASTED_FAILED:
// buyerState.set(BuyerState.EXCEPTION);
case FAULT:
sellerState.set(SellerState.FAULT);
break;
case MESSAGE_SENDING_FAILED:
// buyerState.set(BuyerState.MESSAGE_SENDING_FAILED);
break;
case EXCEPTION:
// buyerState.set(BuyerState.EXCEPTION);
break;
*/
default:
log.warn("unhandled viewState " + processState);
break;

View file

@ -92,6 +92,10 @@ public class SellerSubView extends TradeSubView {
tradeStepDetailsView.deactivate();
switch (viewState) {
case UNDEFINED:
/* showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Trade is in an incomplete state.");*/
break;
case WAIT_FOR_BLOCKCHAIN_CONFIRMATION:
showItem(waitTxInBlockchain);
@ -173,6 +177,15 @@ public class SellerSubView extends TradeSubView {
completedView.setWithdrawAmountTextFieldText(model.getPayoutAmount());
break;
case CLOSED:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Trade is closed");
break;
case FAULT:
showItem(waitTxInBlockchain);
((WaitTxInBlockchainView) tradeStepDetailsView).setInfoLabelText("Error occured");
break;
/* case MESSAGE_SENDING_FAILED:
Popups.openWarningPopup("Sending message to trading peer failed.", model.getErrorMessage());
break;