Remove fault property from trade, handle offerer protocol at startup

This commit is contained in:
Manfred Karrer 2015-03-14 11:08:27 +01:00
parent d1920b6e38
commit f5a7391cb5
10 changed files with 66 additions and 69 deletions

View File

@ -195,16 +195,16 @@ class MainViewModel implements ViewModel {
log.trace("updateProcess completed");
});
Observable<?> allTasks = Observable.merge(messageObservable, walletServiceObservable, updateProcessObservable);
allTasks.subscribe(
Observable<?> allServices = Observable.merge(messageObservable, walletServiceObservable, updateProcessObservable);
allServices.subscribe(
next -> {
},
error -> log.error(error.toString()),
() -> Platform.runLater(() -> allTasksCompleted())
() -> Platform.runLater(() -> onAllServicesInitialized())
);
}
private void allTasksCompleted() {
private void onAllServicesInitialized() {
log.trace("backend completed");
tradeManager.getPendingTrades().addListener(
@ -232,6 +232,8 @@ class MainViewModel implements ViewModel {
user.setAccountID(walletService.getRegistrationAddressEntry().toString());
persistence.write(user.getClass().getName(), user);
}
tradeManager.onAllServicesInitialized();
}
private void applyUpdateState(UpdateProcess.State state) {

View File

@ -70,12 +70,10 @@ class PendingTradesDataModel implements Activatable, DataModel {
private TxConfidenceListener txConfidenceListener;
private final ChangeListener<Trade.State> stateChangeListener;
private final ChangeListener<Throwable> faultChangeListener;
private final MapChangeListener<String, Trade> mapChangeListener;
final StringProperty txId = new SimpleStringProperty();
final ObjectProperty<Trade.State> tradeState = new SimpleObjectProperty<>();
final ObjectProperty<Throwable> fault = new SimpleObjectProperty<>();
@Inject
@ -85,7 +83,6 @@ class PendingTradesDataModel implements Activatable, DataModel {
this.user = user;
this.stateChangeListener = (ov, oldValue, newValue) -> tradeState.set(newValue);
this.faultChangeListener = (ov, oldValue, newValue) -> fault.set(newValue);
this.mapChangeListener = change -> {
if (change.wasAdded())
@ -151,9 +148,6 @@ class PendingTradesDataModel implements Activatable, DataModel {
};
walletService.addTxConfidenceListener(txConfidenceListener);
updateConfidence(walletService.getConfidenceForTxId(txId.get()));
trade.faultProperty().addListener(faultChangeListener);
fault.set(trade.faultProperty().get());
}
else {
txId.set(null);
@ -296,7 +290,6 @@ class PendingTradesDataModel implements Activatable, DataModel {
if (selectedItem != null) {
Trade trade = getTrade();
trade.stateProperty().removeListener(stateChangeListener);
trade.faultProperty().removeListener(faultChangeListener);
}
if (txConfidenceListener != null)

View File

@ -87,7 +87,6 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
private ChangeListener<String> txIdChangeListener;
private ChangeListener<PendingTradesViewModel.State> offererStateChangeListener;
private ChangeListener<PendingTradesViewModel.State> takerStateChangeListener;
private ChangeListener<Throwable> faultChangeListener;
private final Navigation navigation;
@ -129,7 +128,6 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
offererStateChangeListener = (ov, oldValue, newValue) -> applyOffererState(newValue);
takerStateChangeListener = (ov, oldValue, newValue) -> applyTakerState(newValue);
faultChangeListener = (ov, oldValue, newValue) -> onFault(newValue);
withdrawAddressTextField.setValidator(model.getBtcAddressValidator());
withdrawButton.disableProperty().bind(model.withdrawalButtonDisable);
@ -141,7 +139,6 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
model.getList().addListener(listChangeListener);
model.txId.addListener(txIdChangeListener);
model.fault.addListener(faultChangeListener);
txIdTextField.setup(model.getWalletService(), model.txId.get());
table.getSelectionModel().select(model.getSelectedItem());
@ -163,7 +160,6 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
table.getSelectionModel().selectedItemProperty().removeListener(selectedItemChangeListener);
model.getList().removeListener(listChangeListener);
model.txId.removeListener(txIdChangeListener);
model.fault.removeListener(faultChangeListener);
model.state.removeListener(offererStateChangeListener);
model.state.removeListener(takerStateChangeListener);
@ -414,12 +410,6 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
}
}
private void onFault(Throwable fault) {
// TODO error handling not implemented yet
if (fault != null)
log.error(fault.toString());
}
private void setPaymentsControlsVisible(boolean visible) {
paymentsGroupBg.setVisible(visible);
paymentMethodLabel.setVisible(visible);

View File

@ -65,7 +65,6 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
final StringProperty txId = new SimpleStringProperty();
final ObjectProperty<State> state = new SimpleObjectProperty<>();
final ObjectProperty<Throwable> fault = new SimpleObjectProperty<>();
final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
@ -82,7 +81,6 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
@Override
public void doActivate() {
txId.bind(dataModel.txId);
fault.bind(dataModel.fault);
dataModel.tradeState.addListener(stateChangeListener);
updateState();
@ -91,7 +89,6 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
@Override
public void doDeactivate() {
txId.unbind();
fault.unbind();
dataModel.tradeState.removeListener(stateChangeListener);
}
@ -236,7 +233,7 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
case PAYOUT_PUBLISHED:
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_COMPLETED : State.TAKER_SELLER_COMPLETED);
break;
case FAILED:
case MESSAGE_SENDING_FAILED:
// TODO error states not implemented yet
break;
default:

View File

@ -163,8 +163,9 @@ class TakeOfferDataModel implements Activatable, DataModel {
break;
case FIAT_PAYMENT_STARTED:
break;
case FAILED:
requestTakeOfferErrorMessage.set("An error occurred. Error: " + trade.getFault().getMessage());
case MESSAGE_SENDING_FAILED:
requestTakeOfferErrorMessage.set("An error occurred when sending a message to the offerer. Maybe there are connection problems. Please " +
"try later again.");
break;
case PAYOUT_PUBLISHED:
break;

View File

@ -151,6 +151,12 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
offerIsAvailableChangeListener = (ov, oldValue, newValue) -> handleOfferIsAvailableState(newValue);
model.offerIsAvailable.addListener(offerIsAvailableChangeListener);
handleOfferIsAvailableState(model.offerIsAvailable.get());
// In case of returning to a canceled or failed take offer request and if trade wallet is sufficient funded we display directly the payment screen
if (!model.isTakeOfferButtonDisabled.get()) {
showPayFundsScreen();
showPaymentInfoScreenButton.setVisible(false);
}
}
public void setCloseHandler(TradeView.CloseHandler closeHandler) {
@ -167,7 +173,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
isOfferAvailableProgressIndicator.setProgress(0);
isOfferAvailableProgressIndicator.setVisible(false);
isOfferAvailableProgressIndicator.setManaged(false);
showPaymentInfoScreenButton.setVisible(true);
if (model.isTakeOfferButtonDisabled.get())
showPaymentInfoScreenButton.setVisible(true);
break;
case OFFERER_OFFLINE:
Popups.openWarningPopup("You cannot take that offer", "The offerer is offline.");
@ -195,6 +202,10 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
@FXML
void onShowPayFundsScreen() {
showPayFundsScreen();
}
private void showPayFundsScreen() {
// TODO deactivate for testing the moment
/* if (model.displaySecurityDepositInfo()) {
overlayManager.blurContent();

View File

@ -47,7 +47,7 @@ public class Trade implements Serializable {
FIAT_PAYMENT_STARTED,
FIAT_PAYMENT_RECEIVED,
PAYOUT_PUBLISHED,
FAILED
MESSAGE_SENDING_FAILED
}
private final Offer offer;
@ -61,7 +61,6 @@ public class Trade implements Serializable {
private Coin tradeAmount;
private State state;
private Throwable fault;
// For changing values we use properties to get binding support in the UI (table)
// When serialized those transient properties are not instantiated, so we instantiate them in the getters at first
@ -69,8 +68,7 @@ public class Trade implements Serializable {
transient private ObjectProperty<Coin> _tradeAmount;
transient private ObjectProperty<Fiat> _tradeVolume;
transient private ObjectProperty<State> _state;
transient private ObjectProperty<Throwable> _fault;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
@ -131,11 +129,6 @@ public class Trade implements Serializable {
stateProperty().set(state);
}
public void setFault(Throwable fault) {
this.fault = fault;
faultProperty().set(fault);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
@ -161,10 +154,6 @@ public class Trade implements Serializable {
return state;
}
public Throwable getFault() {
return fault;
}
public Coin getSecurityDeposit() {
return offer.getSecurityDeposit();
}
@ -210,10 +199,4 @@ public class Trade implements Serializable {
return _state;
}
public ObjectProperty<Throwable> faultProperty() {
if (_fault == null)
_fault = new SimpleObjectProperty<>(fault);
return _fault;
}
}

View File

@ -74,8 +74,8 @@ public class TradeManager {
private final SignatureService signatureService;
private final OfferBookService offerBookService;
private final Map<String, SellerAsTakerProtocol> takerAsSellerProtocolMap = new HashMap<>();
private final Map<String, BuyerAsOffererProtocol> offererAsBuyerProtocolMap = new HashMap<>();
private final Map<String, SellerAsTakerProtocol> sellerAsTakerProtocolMap = new HashMap<>();
private final Map<String, BuyerAsOffererProtocol> buyerAcceptsOfferProtocolMap = new HashMap<>();
private final Map<String, CheckOfferAvailabilityProtocol> checkOfferAvailabilityProtocolMap = new HashMap<>();
private final ObservableMap<String, OpenOffer> openOffers = FXCollections.observableHashMap();
@ -123,6 +123,13 @@ public class TradeManager {
tradeMessageService.addMessageHandler(messageHandler);
}
// When all services are initialized we create the protocols for our open offers (which will listen for take offer requests)
public void onAllServicesInitialized() {
for (Map.Entry<String, OpenOffer> entry : openOffers.entrySet()) {
createBuyerAcceptsOfferProtocol(entry.getValue());
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Called from UI
@ -180,7 +187,7 @@ public class TradeManager {
model,
(transaction) -> {
OpenOffer openOffer = createOpenOffer(offer);
createOffererAsBuyerProtocol(openOffer);
createBuyerAcceptsOfferProtocol(openOffer);
resultHandler.handleResult(transaction);
},
(message) -> {
@ -214,7 +221,7 @@ public class TradeManager {
persistPendingTrades();
break;
case OFFERER_REJECTED:
case FAILED:
case MESSAGE_SENDING_FAILED:
removeFailedTrade(trade);
break;
default:
@ -232,7 +239,7 @@ public class TradeManager {
user);
SellerAsTakerProtocol sellerTakesOfferProtocol = new SellerAsTakerProtocol(model);
takerAsSellerProtocolMap.put(trade.getId(), sellerTakesOfferProtocol);
sellerAsTakerProtocolMap.put(trade.getId(), sellerTakesOfferProtocol);
sellerTakesOfferProtocol.takeOffer();
@ -241,14 +248,14 @@ public class TradeManager {
public void onFiatPaymentStarted(String tradeId) {
// TODO remove if check when peristence is impl.
if (offererAsBuyerProtocolMap.containsKey(tradeId)) {
offererAsBuyerProtocolMap.get(tradeId).onFiatPaymentStarted();
if (buyerAcceptsOfferProtocolMap.containsKey(tradeId)) {
buyerAcceptsOfferProtocolMap.get(tradeId).onFiatPaymentStarted();
persistPendingTrades();
}
}
public void onFiatPaymentReceived(String tradeId) {
takerAsSellerProtocolMap.get(tradeId).onFiatPaymentReceived();
sellerAsTakerProtocolMap.get(tradeId).onFiatPaymentReceived();
}
@ -315,9 +322,9 @@ public class TradeManager {
OpenOffer openOffer = openOffers.remove(offerId);
disposeCheckOfferAvailabilityRequest(openOffer.getOffer());
persistOpenOffers();
if (removeFromOffererAsBuyerProtocolMap && offererAsBuyerProtocolMap.containsKey(offerId)) {
offererAsBuyerProtocolMap.get(offerId).cleanup();
offererAsBuyerProtocolMap.remove(offerId);
if (removeFromOffererAsBuyerProtocolMap && buyerAcceptsOfferProtocolMap.containsKey(offerId)) {
buyerAcceptsOfferProtocolMap.get(offerId).cleanup();
buyerAcceptsOfferProtocolMap.remove(offerId);
}
resultHandler.handleResult();
@ -343,7 +350,7 @@ public class TradeManager {
return trade;
}
private void createOffererAsBuyerProtocol(OpenOffer openOffer) {
private void createBuyerAcceptsOfferProtocol(OpenOffer openOffer) {
BuyerAsOffererModel model = new BuyerAsOffererModel(
openOffer,
tradeMessageService,
@ -383,9 +390,9 @@ public class TradeManager {
persistPendingTrades();
break;
case OFFERER_REJECTED:
case FAILED:
case MESSAGE_SENDING_FAILED:
removeFailedTrade(trade);
offererAsBuyerProtocolMap.get(trade.getId()).cleanup();
buyerAcceptsOfferProtocolMap.get(trade.getId()).cleanup();
break;
default:
log.error("Unhandled trade state: " + newValue);
@ -400,7 +407,7 @@ public class TradeManager {
});
BuyerAsOffererProtocol buyerAcceptsOfferProtocol = new BuyerAsOffererProtocol(model);
offererAsBuyerProtocolMap.put(openOffer.getId(), buyerAcceptsOfferProtocol);
buyerAcceptsOfferProtocolMap.put(openOffer.getId(), buyerAcceptsOfferProtocol);
}
private void removeFailedTrade(Trade trade) {
@ -414,13 +421,13 @@ public class TradeManager {
pendingTrades.remove(trade.getId());
persistPendingTrades();
if (takerAsSellerProtocolMap.containsKey(trade.getId())) {
takerAsSellerProtocolMap.get(trade.getId()).cleanup();
takerAsSellerProtocolMap.remove(trade.getId());
if (sellerAsTakerProtocolMap.containsKey(trade.getId())) {
sellerAsTakerProtocolMap.get(trade.getId()).cleanup();
sellerAsTakerProtocolMap.remove(trade.getId());
}
else if (offererAsBuyerProtocolMap.containsKey(trade.getId())) {
offererAsBuyerProtocolMap.get(trade.getId()).cleanup();
offererAsBuyerProtocolMap.remove(trade.getId());
else if (buyerAcceptsOfferProtocolMap.containsKey(trade.getId())) {
buyerAcceptsOfferProtocolMap.get(trade.getId()).cleanup();
buyerAcceptsOfferProtocolMap.remove(trade.getId());
}
if (!failed) {

View File

@ -55,6 +55,6 @@ public class ProcessRespondToTakeOfferRequestMessage extends Task<SellerAsTakerM
@Override
protected void applyStateOnFault() {
// do nothing
model.getTrade().setState(Trade.State.MESSAGE_SENDING_FAILED);
}
}

View File

@ -21,14 +21,18 @@ import io.bitsquare.offer.Offer;
import io.bitsquare.trade.listeners.SendMessageListener;
import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel;
import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage;
import io.bitsquare.util.Utilities;
import io.bitsquare.util.taskrunner.Task;
import io.bitsquare.util.taskrunner.TaskRunner;
import javafx.animation.AnimationTimer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RequestTakeOffer extends Task<SellerAsTakerModel> {
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
private AnimationTimer timeoutTimer;
public RequestTakeOffer(TaskRunner taskHandler, SellerAsTakerModel model) {
super(taskHandler, model);
@ -36,10 +40,18 @@ public class RequestTakeOffer extends Task<SellerAsTakerModel> {
@Override
protected void doRun() {
timeoutTimer = Utilities.setTimeout(10000, animationTimer -> {
failed("Timeout reached. We did not get any response form the offerer.");
model.getOffer().setState(Offer.State.OFFERER_OFFLINE);
return null;
});
timeoutTimer.start();
model.getTradeMessageService().sendMessage(model.getPeer(), new RequestTakeOfferMessage(model.getTrade().getId()),
new SendMessageListener() {
@Override
public void handleResult() {
timeoutTimer.stop();
complete();
}
@ -53,6 +65,7 @@ public class RequestTakeOffer extends Task<SellerAsTakerModel> {
@Override
protected void applyStateOnFault() {
timeoutTimer.stop();
if (model.getOffer().getState() != Offer.State.OFFERER_OFFLINE)
model.getOffer().setState(Offer.State.AVAILABILITY_CHECK_FAILED);
}