Improve trade state names

This commit is contained in:
Manfred Karrer 2016-03-03 12:57:57 +01:00
parent f5b996ef00
commit afd88bc55f
38 changed files with 235 additions and 177 deletions

View file

@ -18,6 +18,8 @@
package io.bitsquare.trade; package io.bitsquare.trade;
import io.bitsquare.app.Version; import io.bitsquare.app.Version;
import io.bitsquare.common.handlers.ErrorMessageHandler;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.storage.Storage; import io.bitsquare.storage.Storage;
import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.offer.Offer;
@ -48,9 +50,9 @@ public abstract class SellerTrade extends Trade {
state = State.PREPARATION; state = State.PREPARATION;
} }
public void onFiatPaymentReceived() { public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
checkArgument(tradeProtocol instanceof SellerProtocol, "tradeProtocol NOT instanceof SellerProtocol"); checkArgument(tradeProtocol instanceof SellerProtocol, "tradeProtocol NOT instanceof SellerProtocol");
((SellerProtocol) tradeProtocol).onFiatPaymentReceived(); ((SellerProtocol) tradeProtocol).onFiatPaymentReceived(resultHandler, errorMessageHandler);
} }

View file

@ -67,24 +67,24 @@ public abstract class Trade implements Tradable, Model {
TAKER_FEE_PAID(Phase.TAKER_FEE_PAID), TAKER_FEE_PAID(Phase.TAKER_FEE_PAID),
DEPOSIT_PUBLISH_REQUESTED(Phase.DEPOSIT_REQUESTED), OFFERER_SENT_PUBLISH_DEPOSIT_TX_REQUEST(Phase.DEPOSIT_REQUESTED),
DEPOSIT_PUBLISHED(Phase.DEPOSIT_PAID), TAKER_PUBLISHED_DEPOSIT_TX(Phase.DEPOSIT_PAID),
DEPOSIT_SEEN_IN_NETWORK(Phase.DEPOSIT_PAID), // triggered by balance update, used only in error cases DEPOSIT_SEEN_IN_NETWORK(Phase.DEPOSIT_PAID), // triggered by balance update, used only in error cases
DEPOSIT_PUBLISHED_MSG_SENT(Phase.DEPOSIT_PAID), TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG(Phase.DEPOSIT_PAID),
DEPOSIT_PUBLISHED_MSG_RECEIVED(Phase.DEPOSIT_PAID), OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG(Phase.DEPOSIT_PAID),
DEPOSIT_CONFIRMED(Phase.DEPOSIT_PAID), DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN(Phase.DEPOSIT_PAID),
FIAT_PAYMENT_STARTED(Phase.FIAT_SENT), BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED(Phase.FIAT_SENT),
FIAT_PAYMENT_STARTED_MSG_SENT(Phase.FIAT_SENT), BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG(Phase.FIAT_SENT),
FIAT_PAYMENT_STARTED_MSG_RECEIVED(Phase.FIAT_SENT), SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG(Phase.FIAT_SENT),
FIAT_PAYMENT_RECEIPT(Phase.FIAT_RECEIVED), SELLER_CONFIRMED_FIAT_PAYMENT_RECEIPT(Phase.FIAT_RECEIVED),
FIAT_PAYMENT_RECEIPT_MSG_SENT(Phase.FIAT_RECEIVED), SELLER_SENT_FIAT_PAYMENT_RECEIPT_MSG(Phase.FIAT_RECEIVED),
FIAT_PAYMENT_RECEIPT_MSG_RECEIVED(Phase.FIAT_RECEIVED), BUYER_RECEIVED_FIAT_PAYMENT_RECEIPT_MSG(Phase.FIAT_RECEIVED),
PAYOUT_TX_COMMITTED(Phase.PAYOUT_PAID), BUYER_COMMITTED_PAYOUT_TX(Phase.PAYOUT_PAID), //TODO needed?
PAYOUT_TX_SENT(Phase.PAYOUT_PAID), BUYER_STARTED_SEND_PAYOUT_TX(Phase.PAYOUT_PAID), // not from the success/arrived handler!
PAYOUT_TX_RECEIVED_AND_COMMITTED(Phase.PAYOUT_PAID), SELLER_RECEIVED_AND_COMMITTED_PAYOUT_TX(Phase.PAYOUT_PAID),
PAYOUT_BROAD_CASTED(Phase.PAYOUT_PAID), PAYOUT_BROAD_CASTED(Phase.PAYOUT_PAID),
WITHDRAW_COMPLETED(Phase.WITHDRAWN); WITHDRAW_COMPLETED(Phase.WITHDRAWN);
@ -569,7 +569,7 @@ public abstract class Trade implements Tradable, Model {
TransactionConfidence transactionConfidence = depositTx.getConfidence(); TransactionConfidence transactionConfidence = depositTx.getConfidence();
log.debug("transactionConfidence " + transactionConfidence.getDepthInBlocks()); log.debug("transactionConfidence " + transactionConfidence.getDepthInBlocks());
if (transactionConfidence.getDepthInBlocks() > 0) { if (transactionConfidence.getDepthInBlocks() > 0) {
handleConfidenceResult(); setConfirmedState();
} else { } else {
ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1); ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1);
Futures.addCallback(future, new FutureCallback<TransactionConfidence>() { Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@ -577,7 +577,7 @@ public abstract class Trade implements Tradable, Model {
public void onSuccess(TransactionConfidence result) { public void onSuccess(TransactionConfidence result) {
log.debug("transactionConfidence " + transactionConfidence.getDepthInBlocks()); log.debug("transactionConfidence " + transactionConfidence.getDepthInBlocks());
log.debug("state " + state); log.debug("state " + state);
handleConfidenceResult(); setConfirmedState();
} }
@Override @Override
@ -596,9 +596,10 @@ public abstract class Trade implements Tradable, Model {
abstract protected void createProtocol(); abstract protected void createProtocol();
private void handleConfidenceResult() { private void setConfirmedState() {
if (state.ordinal() < State.DEPOSIT_CONFIRMED.ordinal()) // we oly apply the state if we are not already further in the process
setState(State.DEPOSIT_CONFIRMED); if (state.ordinal() < State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN.ordinal())
setState(State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN);
} }
abstract protected void initStates(); abstract protected void initStates();

View file

@ -144,7 +144,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
// User clicked the "bank transfer started" button // User clicked the "bank transfer started" button
@Override @Override
public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
buyerAsOffererTrade.setState(Trade.State.FIAT_PAYMENT_STARTED); buyerAsOffererTrade.setState(Trade.State.BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade, TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
() -> { () -> {

View file

@ -133,7 +133,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
// User clicked the "bank transfer started" button // User clicked the "bank transfer started" button
@Override @Override
public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { public void onFiatPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
buyerAsTakerTrade.setState(Trade.State.FIAT_PAYMENT_STARTED); buyerAsTakerTrade.setState(Trade.State.BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade, TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
() -> { () -> {

View file

@ -18,6 +18,8 @@
package io.bitsquare.trade.protocol.trade; package io.bitsquare.trade.protocol.trade;
import io.bitsquare.common.handlers.ErrorMessageHandler;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.p2p.messaging.MailboxMessage; import io.bitsquare.p2p.messaging.MailboxMessage;
@ -159,12 +161,18 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
// User clicked the "bank transfer received" button, so we release the funds for pay out // User clicked the "bank transfer received" button, so we release the funds for pay out
@Override @Override
public void onFiatPaymentReceived() { public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
sellerAsOffererTrade.setState(Trade.State.FIAT_PAYMENT_RECEIPT); sellerAsOffererTrade.setState(Trade.State.SELLER_CONFIRMED_FIAT_PAYMENT_RECEIPT);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade, TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
() -> handleTaskRunnerSuccess("onFiatPaymentReceived"), () -> {
this::handleTaskRunnerFault); resultHandler.handleResult();
handleTaskRunnerSuccess("onFiatPaymentReceived");
},
(errorMessage) -> {
errorMessageHandler.handleErrorMessage(errorMessage);
handleTaskRunnerFault(errorMessage);
});
taskRunner.addTasks( taskRunner.addTasks(
VerifyTakeOfferFeePayment.class, VerifyTakeOfferFeePayment.class,

View file

@ -18,6 +18,8 @@
package io.bitsquare.trade.protocol.trade; package io.bitsquare.trade.protocol.trade;
import io.bitsquare.common.handlers.ErrorMessageHandler;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.NodeAddress;
import io.bitsquare.p2p.messaging.MailboxMessage; import io.bitsquare.p2p.messaging.MailboxMessage;
@ -157,13 +159,19 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
// User clicked the "bank transfer received" button, so we release the funds for pay out // User clicked the "bank transfer received" button, so we release the funds for pay out
@Override @Override
public void onFiatPaymentReceived() { public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
sellerAsTakerTrade.setState(Trade.State.FIAT_PAYMENT_RECEIPT); sellerAsTakerTrade.setState(Trade.State.SELLER_CONFIRMED_FIAT_PAYMENT_RECEIPT);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade, TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
() -> handleTaskRunnerSuccess("onFiatPaymentReceived"), () -> {
this::handleTaskRunnerFault); resultHandler.handleResult();
handleTaskRunnerSuccess("onFiatPaymentReceived");
},
(errorMessage) -> {
errorMessageHandler.handleErrorMessage(errorMessage);
handleTaskRunnerFault(errorMessage);
});
taskRunner.addTasks( taskRunner.addTasks(
VerifyOfferFeePayment.class, VerifyOfferFeePayment.class,
SignPayoutTx.class, SignPayoutTx.class,

View file

@ -17,6 +17,9 @@
package io.bitsquare.trade.protocol.trade; package io.bitsquare.trade.protocol.trade;
import io.bitsquare.common.handlers.ErrorMessageHandler;
import io.bitsquare.common.handlers.ResultHandler;
public interface SellerProtocol { public interface SellerProtocol {
void onFiatPaymentReceived(); void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler);
} }

View file

@ -136,7 +136,7 @@ public abstract class TradeProtocol {
Trade.State tradeState = trade.getState(); Trade.State tradeState = trade.getState();
log.debug("cleanupTradable tradeState=" + tradeState); log.debug("cleanupTradable tradeState=" + tradeState);
boolean isOffererTrade = trade instanceof OffererTrade; boolean isOffererTrade = trade instanceof OffererTrade;
if (isOffererTrade && (tradeState == Trade.State.DEPOSIT_PUBLISH_REQUESTED || tradeState == Trade.State.DEPOSIT_SEEN_IN_NETWORK)) if (isOffererTrade && (tradeState == Trade.State.OFFERER_SENT_PUBLISH_DEPOSIT_TX_REQUEST || tradeState == Trade.State.DEPOSIT_SEEN_IN_NETWORK))
processModel.getOpenOfferManager().closeOpenOffer(trade.getOffer()); processModel.getOpenOfferManager().closeOpenOffer(trade.getOffer());
boolean isTakerTrade = trade instanceof TakerTrade; boolean isTakerTrade = trade instanceof TakerTrade;

View file

@ -52,7 +52,7 @@ public class ProcessFinalizePayoutTxRequest extends TradeTask {
removeMailboxMessageAfterProcessing(); removeMailboxMessageAfterProcessing();
trade.setState(Trade.State.FIAT_PAYMENT_RECEIPT_MSG_RECEIVED); trade.setState(Trade.State.BUYER_RECEIVED_FIAT_PAYMENT_RECEIPT_MSG);
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {

View file

@ -48,14 +48,14 @@ public class SendFiatTransferStartedMessage extends TradeTask {
@Override @Override
public void onArrived() { public void onArrived() {
log.info("Message arrived at peer."); log.info("Message arrived at peer.");
trade.setState(Trade.State.FIAT_PAYMENT_STARTED_MSG_SENT); trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG);
complete(); complete();
} }
@Override @Override
public void onStoredInMailbox() { public void onStoredInMailbox() {
log.info("Message stored in mailbox."); log.info("Message stored in mailbox.");
trade.setState(Trade.State.FIAT_PAYMENT_STARTED_MSG_SENT); trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG);
complete(); complete();
} }

View file

@ -67,7 +67,7 @@ public class SendPayoutTxFinalizedMessage extends TradeTask {
); );
// state must not be set in onArrived or onStoredInMailbox handlers as we would get that // state must not be set in onArrived or onStoredInMailbox handlers as we would get that
// called delayed and would overwrite the broad cast state set by the next task // called delayed and would overwrite the broad cast state set by the next task
trade.setState(Trade.State.PAYOUT_TX_SENT); trade.setState(Trade.State.BUYER_STARTED_SEND_PAYOUT_TX);
} else { } else {
log.error("trade.getPayoutTx() = " + trade.getPayoutTx()); log.error("trade.getPayoutTx() = " + trade.getPayoutTx());
failed("PayoutTx is null"); failed("PayoutTx is null");

View file

@ -57,7 +57,7 @@ public class SignAndFinalizePayoutTx extends TradeTask {
); );
trade.setPayoutTx(transaction); trade.setPayoutTx(transaction);
trade.setState(Trade.State.PAYOUT_TX_COMMITTED); trade.setState(Trade.State.BUYER_COMMITTED_PAYOUT_TX);
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {

View file

@ -64,7 +64,7 @@ public class SignAndPublishDepositTxAsBuyer extends TradeTask {
trade.setDepositTx(transaction); trade.setDepositTx(transaction);
//trade.setTakeOfferDate(new Date()); //trade.setTakeOfferDate(new Date());
trade.setTakeOfferDateAsBlockHeight(processModel.getTradeWalletService().getBestChainHeight()); trade.setTakeOfferDateAsBlockHeight(processModel.getTradeWalletService().getBestChainHeight());
trade.setState(Trade.State.DEPOSIT_PUBLISHED); trade.setState(Trade.State.TAKER_PUBLISHED_DEPOSIT_TX);
complete(); complete();
} }

View file

@ -63,7 +63,7 @@ public class ProcessDepositTxPublishedMessage extends TradeTask {
removeMailboxMessageAfterProcessing(); removeMailboxMessageAfterProcessing();
trade.setState(Trade.State.DEPOSIT_PUBLISHED_MSG_RECEIVED); trade.setState(Trade.State.OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG);
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {

View file

@ -58,6 +58,7 @@ public class SendPublishDepositTxRequest extends TradeTask {
@Override @Override
public void onArrived() { public void onArrived() {
log.trace("Message arrived at peer."); log.trace("Message arrived at peer.");
trade.setState(Trade.State.OFFERER_SENT_PUBLISH_DEPOSIT_TX_REQUEST);
complete(); complete();
} }
@ -68,9 +69,6 @@ public class SendPublishDepositTxRequest extends TradeTask {
} }
} }
); );
//TODO should it be in success handler?
trade.setState(Trade.State.DEPOSIT_PUBLISH_REQUESTED);
} catch (Throwable t) { } catch (Throwable t) {
failed(t); failed(t);
} }

View file

@ -62,7 +62,7 @@ public class SetupDepositBalanceListener extends TradeTask {
tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> { tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> {
log.debug("tradeStateSubscription newValue " + newValue); log.debug("tradeStateSubscription newValue " + newValue);
if (newValue == Trade.State.DEPOSIT_PUBLISHED_MSG_RECEIVED if (newValue == Trade.State.OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG
|| newValue == Trade.State.DEPOSIT_SEEN_IN_NETWORK) { || newValue == Trade.State.DEPOSIT_SEEN_IN_NETWORK) {
walletService.removeBalanceListener(balanceListener); walletService.removeBalanceListener(balanceListener);
@ -91,7 +91,7 @@ public class SetupDepositBalanceListener extends TradeTask {
if (trade instanceof OffererTrade) { if (trade instanceof OffererTrade) {
processModel.getOpenOfferManager().closeOpenOffer(trade.getOffer()); processModel.getOpenOfferManager().closeOpenOffer(trade.getOffer());
if (tradeState == Trade.State.DEPOSIT_PUBLISH_REQUESTED) { if (tradeState == Trade.State.OFFERER_SENT_PUBLISH_DEPOSIT_TX_REQUEST) {
trade.setState(Trade.State.DEPOSIT_SEEN_IN_NETWORK); trade.setState(Trade.State.DEPOSIT_SEEN_IN_NETWORK);
} else if (tradeState.getPhase() == Trade.Phase.PREPARATION) { } else if (tradeState.getPhase() == Trade.Phase.PREPARATION) {
processModel.getTradeManager().removePreparedTrade(trade); processModel.getTradeManager().removePreparedTrade(trade);

View file

@ -51,7 +51,7 @@ public class ProcessFiatTransferStartedMessage extends TradeTask {
removeMailboxMessageAfterProcessing(); removeMailboxMessageAfterProcessing();
trade.setState(Trade.State.FIAT_PAYMENT_STARTED_MSG_RECEIVED); trade.setState(Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG);
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {

View file

@ -52,7 +52,7 @@ public class ProcessPayoutTxFinalizedMessage extends TradeTask {
removeMailboxMessageAfterProcessing(); removeMailboxMessageAfterProcessing();
trade.setState(Trade.State.PAYOUT_TX_RECEIVED_AND_COMMITTED); trade.setState(Trade.State.SELLER_RECEIVED_AND_COMMITTED_PAYOUT_TX);
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {

View file

@ -53,14 +53,14 @@ public class SendFinalizePayoutTxRequest extends TradeTask {
@Override @Override
public void onArrived() { public void onArrived() {
log.trace("Message arrived at peer."); log.trace("Message arrived at peer.");
trade.setState(Trade.State.FIAT_PAYMENT_RECEIPT_MSG_SENT); trade.setState(Trade.State.SELLER_SENT_FIAT_PAYMENT_RECEIPT_MSG);
complete(); complete();
} }
@Override @Override
public void onStoredInMailbox() { public void onStoredInMailbox() {
log.trace("Message stored in mailbox."); log.trace("Message stored in mailbox.");
trade.setState(Trade.State.FIAT_PAYMENT_RECEIPT_MSG_SENT); trade.setState(Trade.State.SELLER_SENT_FIAT_PAYMENT_RECEIPT_MSG);
complete(); complete();
} }

View file

@ -62,7 +62,7 @@ public class SignAndPublishDepositTxAsSeller extends TradeTask {
trade.setDepositTx(transaction); trade.setDepositTx(transaction);
//trade.setTakeOfferDate(new Date()); //trade.setTakeOfferDate(new Date());
trade.setTakeOfferDateAsBlockHeight(processModel.getTradeWalletService().getBestChainHeight()); trade.setTakeOfferDateAsBlockHeight(processModel.getTradeWalletService().getBestChainHeight());
trade.setState(Trade.State.DEPOSIT_PUBLISHED); trade.setState(Trade.State.TAKER_PUBLISHED_DEPOSIT_TX);
complete(); complete();
} }

View file

@ -49,14 +49,14 @@ public class SendDepositTxPublishedMessage extends TradeTask {
@Override @Override
public void onArrived() { public void onArrived() {
log.trace("Message arrived at peer."); log.trace("Message arrived at peer.");
trade.setState(Trade.State.DEPOSIT_PUBLISHED_MSG_SENT); trade.setState(Trade.State.TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG);
complete(); complete();
} }
@Override @Override
public void onStoredInMailbox() { public void onStoredInMailbox() {
log.trace("Message stored in mailbox."); log.trace("Message stored in mailbox.");
trade.setState(Trade.State.DEPOSIT_PUBLISHED_MSG_SENT); trade.setState(Trade.State.TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG);
complete(); complete();
} }

View file

@ -99,7 +99,7 @@ public class BlockChainForm extends PaymentMethodForm {
addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(blockChainAccount.getPaymentMethod().getId())); addLabelTextField(gridPane, ++gridRow, "Payment method:", BSResources.get(blockChainAccount.getPaymentMethod().getId()));
TextField field = addLabelTextField(gridPane, ++gridRow, "Cryptocurrency address:", blockChainAccount.getAddress()).second; TextField field = addLabelTextField(gridPane, ++gridRow, "Cryptocurrency address:", blockChainAccount.getAddress()).second;
field.setMouseTransparent(false); field.setMouseTransparent(false);
addLabelTextField(gridPane, ++gridRow, "Crypto currency:", blockChainAccount.getSingleTradeCurrency().getNameAndCode()); addLabelTextField(gridPane, ++gridRow, "Cryptocurrency:", blockChainAccount.getSingleTradeCurrency().getNameAndCode());
addAllowedPeriod(); addAllowedPeriod();
} }
@ -112,7 +112,7 @@ public class BlockChainForm extends PaymentMethodForm {
@Override @Override
protected void addTradeCurrencyComboBox() { protected void addTradeCurrencyComboBox() {
currencyComboBox = addLabelComboBox(gridPane, ++gridRow, "Crypto currency:", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second; currencyComboBox = addLabelComboBox(gridPane, ++gridRow, "Cryptocurrency:", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
currencyComboBox.setPromptText("Select cryptocurrency"); currencyComboBox.setPromptText("Select cryptocurrency");
currencyComboBox.setItems(FXCollections.observableArrayList(CurrencyUtil.getAllSortedCryptoCurrencies())); currencyComboBox.setItems(FXCollections.observableArrayList(CurrencyUtil.getAllSortedCryptoCurrencies()));
currencyComboBox.setVisibleRowCount(Math.min(currencyComboBox.getItems().size(), 20)); currencyComboBox.setVisibleRowCount(Math.min(currencyComboBox.getItems().size(), 20));

View file

@ -162,7 +162,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
} }
}); });
} else { } else {
feeFromFundingTxProperty.set(FeePolicy.getMinRequiredFeeForFundingTx()); // Simulate a bit of delay
UserThread.runAfter(() -> feeFromFundingTxProperty.set(FeePolicy.getMinRequiredFeeForFundingTx()), 1);
} }
} }
}; };

View file

@ -187,15 +187,12 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
public void initWithData(Offer.Direction direction, TradeCurrency tradeCurrency) { public void initWithData(Offer.Direction direction, TradeCurrency tradeCurrency) {
model.initWithData(direction, tradeCurrency); model.initWithData(direction, tradeCurrency);
ImageView iconView = new ImageView();
placeOfferButton.setGraphic(iconView);
if (direction == Offer.Direction.BUY) { if (direction == Offer.Direction.BUY) {
imageView.setId("image-buy-large"); imageView.setId("image-buy-large");
placeOfferButton.setId("buy-button-big"); placeOfferButton.setId("buy-button-big");
placeOfferButton.setText("Review place offer for buying bitcoin"); placeOfferButton.setText("Review place offer for buying bitcoin");
nextButton.setId("buy-button"); nextButton.setId("buy-button");
iconView.setId("image-buy-white");
} else { } else {
imageView.setId("image-sell-large"); imageView.setId("image-sell-large");
// only needed for sell // only needed for sell
@ -204,7 +201,6 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
placeOfferButton.setId("sell-button-big"); placeOfferButton.setId("sell-button-big");
placeOfferButton.setText("Review place offer for selling bitcoin"); placeOfferButton.setText("Review place offer for selling bitcoin");
nextButton.setId("sell-button"); nextButton.setId("sell-button");
iconView.setId("image-sell-white");
} }
} }
@ -250,6 +246,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
} }
private void onShowFundsScreen() { private void onShowFundsScreen() {
model.onShowFundsScreen();
amountTextField.setMouseTransparent(true); amountTextField.setMouseTransparent(true);
minAmountTextField.setMouseTransparent(true); minAmountTextField.setMouseTransparent(true);
priceTextField.setMouseTransparent(true); priceTextField.setMouseTransparent(true);
@ -257,7 +254,6 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
currencyComboBox.setMouseTransparent(true); currencyComboBox.setMouseTransparent(true);
paymentAccountsComboBox.setMouseTransparent(true); paymentAccountsComboBox.setMouseTransparent(true);
spinner.setVisible(true);
spinner.setProgress(-1); spinner.setProgress(-1);
if (!BitsquareApp.DEV_MODE) { if (!BitsquareApp.DEV_MODE) {
@ -388,7 +384,10 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
// buttons // buttons
placeOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled); placeOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled);
cancelButton2.disableProperty().bind(model.cancelButtonDisabled); cancelButton2.disableProperty().bind(model.cancelButtonDisabled);
spinner.visibleProperty().bind(model.isSpinnerVisible);
spinnerInfoLabel.visibleProperty().bind(model.isSpinnerVisible); spinnerInfoLabel.visibleProperty().bind(model.isSpinnerVisible);
spinnerInfoLabel.textProperty().bind(model.spinnerInfoText);
// payment account // payment account
currencyComboBox.prefWidthProperty().bind(paymentAccountsComboBox.widthProperty()); currencyComboBox.prefWidthProperty().bind(paymentAccountsComboBox.widthProperty());
@ -420,7 +419,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
volumeTextField.validationResultProperty().unbind(); volumeTextField.validationResultProperty().unbind();
placeOfferButton.disableProperty().unbind(); placeOfferButton.disableProperty().unbind();
cancelButton2.disableProperty().unbind(); cancelButton2.disableProperty().unbind();
spinner.visibleProperty().unbind();
spinnerInfoLabel.visibleProperty().unbind(); spinnerInfoLabel.visibleProperty().unbind();
spinnerInfoLabel.textProperty().unbind();
currencyComboBox.managedProperty().unbind(); currencyComboBox.managedProperty().unbind();
currencyComboBoxLabel.visibleProperty().unbind(); currencyComboBoxLabel.visibleProperty().unbind();
currencyComboBoxLabel.managedProperty().unbind(); currencyComboBoxLabel.managedProperty().unbind();
@ -476,10 +477,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
"Please try to restart you application and check your network connection to see if you can resolve the issue.") "Please try to restart you application and check your network connection to see if you can resolve the issue.")
.show(), 100, TimeUnit.MILLISECONDS); .show(), 100, TimeUnit.MILLISECONDS);
}; };
isSpinnerVisibleListener = (ov, oldValue, newValue) -> { isSpinnerVisibleListener = (ov, oldValue, newValue) -> spinner.setProgress(newValue ? -1 : 0);
spinner.setProgress(newValue ? -1 : 0);
spinner.setVisible(newValue);
};
feeFromFundingTxListener = (observable, oldValue, newValue) -> { feeFromFundingTxListener = (observable, oldValue, newValue) -> {
log.debug("feeFromFundingTxListener " + newValue); log.debug("feeFromFundingTxListener " + newValue);
@ -517,18 +515,25 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class); navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class);
} else if (newValue) { } else if (newValue) {
// We need a bit of delay to avoid issues with fade out/fade in of 2 popups // We need a bit of delay to avoid issues with fade out/fade in of 2 popups
UserThread.runAfter(() -> UserThread.runAfter(() -> {
String key = "createOfferSuccessInfo";
if (preferences.showAgain(key)) {
new Popup().headLine(BSResources.get("createOffer.success.headline")) new Popup().headLine(BSResources.get("createOffer.success.headline"))
.feedback(BSResources.get("createOffer.success.info")) .feedback(BSResources.get("createOffer.success.info"))
.dontShowAgainId(key, preferences)
.actionButtonText("Go to \"My open offers\"") .actionButtonText("Go to \"My open offers\"")
.onAction(() -> { .onAction(() -> {
close();
UserThread.runAfter(() -> UserThread.runAfter(() ->
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class), navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class),
100, TimeUnit.MILLISECONDS); 100, TimeUnit.MILLISECONDS);
close();
}) })
.onClose(this::close) .onClose(this::close)
.show(), .show();
} else {
close();
}
},
500, TimeUnit.MILLISECONDS); 500, TimeUnit.MILLISECONDS);
} }
}; };
@ -725,11 +730,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
spinner = placeOfferTuple.second; spinner = placeOfferTuple.second;
spinner.setProgress(0); spinner.setProgress(0);
spinner.setVisible(false); //spinner.setPrefSize(18, 18);
spinner.setPrefSize(18, 18);
spinnerInfoLabel = placeOfferTuple.third; spinnerInfoLabel = placeOfferTuple.third;
spinnerInfoLabel.textProperty().bind(model.spinnerInfoText);
spinnerInfoLabel.setVisible(false);
cancelButton2 = addButton(gridPane, ++gridRow, BSResources.get("shared.cancel")); cancelButton2 = addButton(gridPane, ++gridRow, BSResources.get("shared.cancel"));
cancelButton2.setOnAction(e -> close()); cancelButton2.setOnAction(e -> close());

View file

@ -70,7 +70,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
final BooleanProperty isPlaceOfferButtonDisabled = new SimpleBooleanProperty(true); final BooleanProperty isPlaceOfferButtonDisabled = new SimpleBooleanProperty(true);
final BooleanProperty cancelButtonDisabled = new SimpleBooleanProperty(); final BooleanProperty cancelButtonDisabled = new SimpleBooleanProperty();
final BooleanProperty isNextButtonDisabled = new SimpleBooleanProperty(true); final BooleanProperty isNextButtonDisabled = new SimpleBooleanProperty(true);
final BooleanProperty isSpinnerVisible = new SimpleBooleanProperty(true); final BooleanProperty isSpinnerVisible = new SimpleBooleanProperty();
final BooleanProperty showWarningAdjustedVolume = new SimpleBooleanProperty(); final BooleanProperty showWarningAdjustedVolume = new SimpleBooleanProperty();
final BooleanProperty showWarningInvalidFiatDecimalPlaces = new SimpleBooleanProperty(); final BooleanProperty showWarningInvalidFiatDecimalPlaces = new SimpleBooleanProperty();
final BooleanProperty showWarningInvalidBtcDecimalPlaces = new SimpleBooleanProperty(); final BooleanProperty showWarningInvalidBtcDecimalPlaces = new SimpleBooleanProperty();
@ -363,6 +363,9 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
dataModel.onCurrencySelected(tradeCurrency); dataModel.onCurrencySelected(tradeCurrency);
} }
public void onShowFundsScreen() {
isSpinnerVisible.set(true);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Handle focus // Handle focus

View file

@ -254,12 +254,12 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
private void onCreateOffer() { private void onCreateOffer() {
if (!model.hasPaymentAccount()) { if (!model.hasPaymentAccount()) {
openPopupForMissingAccountSetup("You have not setup a payment account", openPopupForMissingAccountSetup("You have not setup a payment account",
"You need to setup a national currency or crypto currency account before you can create an offer.\n" + "You need to setup a national currency or cryptocurrency account before you can create an offer.\n" +
"Do you want to setup an account?", FiatAccountsView.class, "\"Account\""); "Do you want to setup an account?", FiatAccountsView.class, "\"Account\"");
} else if (!model.hasPaymentAccountForCurrency()) { } else if (!model.hasPaymentAccountForCurrency()) {
openPopupForMissingAccountSetup("You don't have a payment account for the currency:\n" + openPopupForMissingAccountSetup("No matching payment account",
model.getSelectedTradeCurrency().getCodeAndName(), "You don't have a payment account for the currency required for that offer.\n" +
"You need to setup a payment account for the selected currency to be able to trade in that currency.\n" + "You need to setup a payment account for that currency to be able to take this offer.\n" +
"Do you want to do this now?", FiatAccountsView.class, "\"Account\""); "Do you want to do this now?", FiatAccountsView.class, "\"Account\"");
} else if (!model.hasAcceptedArbitrators()) { } else if (!model.hasAcceptedArbitrators()) {
openPopupForMissingAccountSetup("You don't have an arbitrator selected.", openPopupForMissingAccountSetup("You don't have an arbitrator selected.",
@ -277,8 +277,9 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
"You need to setup at least one arbitrator to be able to trade.\n" + "You need to setup at least one arbitrator to be able to trade.\n" +
"Do you want to do this now?", ArbitratorSelectionView.class, "\"Arbitrator selection\""); "Do you want to do this now?", ArbitratorSelectionView.class, "\"Arbitrator selection\"");
} else if (!isPaymentAccountValidForOffer) { } else if (!isPaymentAccountValidForOffer) {
openPopupForMissingAccountSetup("You don't have a payment account with the payment method required for that offer.", openPopupForMissingAccountSetup("No matching payment account",
"You need to setup a payment account with that payment method if you want to take that offer.\n" + "You don't have a payment account with the payment method required for that offer.\n" +
"You need to setup a payment account with that payment method if you want to take this offer.\n" +
"Do you want to do this now?", FiatAccountsView.class, "\"Account\""); "Do you want to do this now?", FiatAccountsView.class, "\"Account\"");
} else if (!hasSameProtocolVersion) { } else if (!hasSameProtocolVersion) {
new Popup().warning("That offer requires a different protocol version as the one used in your " + new Popup().warning("That offer requires a different protocol version as the one used in your " +

View file

@ -198,7 +198,8 @@ class TakeOfferDataModel extends ActivatableDataModel {
} }
}); });
} else { } else {
feeFromFundingTxProperty.set(FeePolicy.getMinRequiredFeeForFundingTx()); // Simulate a bit of delay
UserThread.runAfter(() -> feeFromFundingTxProperty.set(FeePolicy.getMinRequiredFeeForFundingTx()), 1);
} }
} }
}; };

View file

@ -205,17 +205,25 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class); navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
} else if (newValue && model.getTrade() != null && model.getTrade().errorMessageProperty().get() == null) { } else if (newValue && model.getTrade() != null && model.getTrade().errorMessageProperty().get() == null) {
UserThread.runAfter( UserThread.runAfter(
() -> new Popup().headLine(BSResources.get("takeOffer.success.headline")) () -> {
.feedback(BSResources.get("takeOffer.success.info")) String key = "takeOfferSuccessInfo";
.actionButtonText("Go to \"Open trades\"") if (preferences.showAgain(key)) {
.onAction(() -> { new Popup().headLine(BSResources.get("takeOffer.success.headline"))
close(); .feedback(BSResources.get("takeOffer.success.info"))
UserThread.runAfter( .actionButtonText("Go to \"Open trades\"")
() -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class) .dontShowAgainId(key, preferences)
, 100, TimeUnit.MILLISECONDS); .onAction(() -> {
}) UserThread.runAfter(
.onClose(this::close) () -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class)
.show(), 500, TimeUnit.MILLISECONDS); , 100, TimeUnit.MILLISECONDS);
close();
})
.onClose(this::close)
.show();
} else {
close();
}
}, 500, TimeUnit.MILLISECONDS);
} }
}); });
@ -294,8 +302,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
public void initWithData(Offer offer) { public void initWithData(Offer offer) {
model.initWithData(offer); model.initWithData(offer);
ImageView iconView = new ImageView();
takeOfferButton.setGraphic(iconView);
if (model.getOffer().getDirection() == Offer.Direction.SELL) { if (model.getOffer().getDirection() == Offer.Direction.SELL) {
imageView.setId("image-buy-large"); imageView.setId("image-buy-large");
directionLabel.setId("direction-icon-label-buy"); directionLabel.setId("direction-icon-label-buy");
@ -303,7 +309,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
takeOfferButton.setId("buy-button-big"); takeOfferButton.setId("buy-button-big");
takeOfferButton.setText("Review take offer for buying bitcoin"); takeOfferButton.setText("Review take offer for buying bitcoin");
nextButton.setId("buy-button"); nextButton.setId("buy-button");
iconView.setId("image-buy-white");
} else { } else {
imageView.setId("image-sell-large"); imageView.setId("image-sell-large");
directionLabel.setId("direction-icon-label-sell"); directionLabel.setId("direction-icon-label-sell");
@ -311,7 +316,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
takeOfferButton.setId("sell-button-big"); takeOfferButton.setId("sell-button-big");
nextButton.setId("sell-button"); nextButton.setId("sell-button");
takeOfferButton.setText("Review take offer for selling bitcoin"); takeOfferButton.setText("Review take offer for selling bitcoin");
iconView.setId("image-sell-white");
} }
balanceTextField.setup(model.address.get(), model.getFormatter()); balanceTextField.setup(model.address.get(), model.getFormatter());

View file

@ -327,10 +327,10 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
private void applyTradeState(Trade.State tradeState) { private void applyTradeState(Trade.State tradeState) {
log.debug("applyTradeState state = " + tradeState); log.debug("applyTradeState state = " + tradeState);
if (trade.getState() == Trade.State.DEPOSIT_PUBLISHED if (trade.getState() == Trade.State.TAKER_PUBLISHED_DEPOSIT_TX
|| trade.getState() == Trade.State.DEPOSIT_SEEN_IN_NETWORK || trade.getState() == Trade.State.DEPOSIT_SEEN_IN_NETWORK
|| trade.getState() == Trade.State.DEPOSIT_PUBLISHED_MSG_SENT || trade.getState() == Trade.State.TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG
|| trade.getState() == Trade.State.DEPOSIT_PUBLISHED_MSG_RECEIVED) { || trade.getState() == Trade.State.OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG) {
if (trade.getDepositTx() != null) { if (trade.getDepositTx() != null) {
if (takeOfferSucceededHandler != null) if (takeOfferSucceededHandler != null)
takeOfferSucceededHandler.run(); takeOfferSucceededHandler.run();

View file

@ -307,10 +307,9 @@ public abstract class Overlay<T extends Overlay> {
scene.getStylesheets().setAll(rootScene.getStylesheets()); scene.getStylesheets().setAll(rootScene.getStylesheets());
scene.setFill(Color.TRANSPARENT); scene.setFill(Color.TRANSPARENT);
stage.setScene(scene); stage.setScene(scene);
Window window = rootScene.getWindow();
setModality(); setModality();
stage.initStyle(StageStyle.TRANSPARENT); stage.initStyle(StageStyle.TRANSPARENT);
Window window = rootScene.getWindow();
stage.initOwner(window);
stage.show(); stage.show();
layout(); layout();
@ -342,6 +341,7 @@ public abstract class Overlay<T extends Overlay> {
} }
protected void setModality() { protected void setModality() {
stage.initOwner(owner.getScene().getWindow());
stage.initModality(Modality.WINDOW_MODAL); stage.initModality(Modality.WINDOW_MODAL);
} }

View file

@ -32,7 +32,7 @@ public class Notification extends Overlay<Notification> {
public void onReadyForDisplay() { public void onReadyForDisplay() {
super.display(); super.display();
if (autoClose && autoCloseTimer == null) if (autoClose && autoCloseTimer == null)
autoCloseTimer = UserThread.runAfter(this::hide, 5); autoCloseTimer = UserThread.runAfter(this::hide, 4);
} }
@Override @Override

View file

@ -147,10 +147,10 @@ public class NotificationCenter {
String message = null; String message = null;
if (tradeManager.isBuyer(trade.getOffer())) { if (tradeManager.isBuyer(trade.getOffer())) {
switch (tradeState) { switch (tradeState) {
case DEPOSIT_PUBLISHED_MSG_RECEIVED: case OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG:
message = "Your offer has been accepted by a seller."; message = "Your offer has been accepted by a seller.";
break; break;
case DEPOSIT_CONFIRMED: case DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN:
message = "Your trade has at least one blockchain confirmation.\n" + message = "Your trade has at least one blockchain confirmation.\n" +
"You can start the payment now."; "You can start the payment now.";
@ -164,10 +164,10 @@ public class NotificationCenter {
} }
} else { } else {
switch (tradeState) { switch (tradeState) {
case DEPOSIT_PUBLISHED_MSG_RECEIVED: case OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG:
message = "Your offer has been accepted by a buyer."; message = "Your offer has been accepted by a buyer.";
break; break;
case FIAT_PAYMENT_STARTED_MSG_RECEIVED: case SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG:
message = "The bitcoin buyer has started the payment."; message = "The bitcoin buyer has started the payment.";
break; break;
/* case FIAT_PAYMENT_RECEIPT_MSG_SENT: /* case FIAT_PAYMENT_RECEIPT_MSG_SENT:

View file

@ -242,12 +242,15 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++rowIndex, isPlaceOffer ? placeOfferButtonText : takeOfferButtonText); Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++rowIndex, isPlaceOffer ? placeOfferButtonText : takeOfferButtonText);
Button button = placeOfferTuple.first; Button button = placeOfferTuple.first;
button.setMinHeight(40);
button.setPadding(new Insets(0, 20, 0, 20));
button.setGraphic(iconView); button.setGraphic(iconView);
button.setId(isBuyerRole ? "buy-button" : "sell-button"); button.setGraphicTextGap(10);
button.setId(isBuyerRole ? "buy-button-big" : "sell-button-big");
button.setText(isPlaceOffer ? placeOfferButtonText : takeOfferButtonText); button.setText(isPlaceOffer ? placeOfferButtonText : takeOfferButtonText);
spinner = placeOfferTuple.second; spinner = placeOfferTuple.second;
spinner.setPrefSize(18, 18); //spinner.setPrefSize(18, 18);
spinner.setVisible(false); spinner.setVisible(false);
Label spinnerInfoLabel = placeOfferTuple.third; Label spinnerInfoLabel = placeOfferTuple.third;

View file

@ -140,11 +140,11 @@ public class PendingTradesDataModel extends ActivatableDataModel {
((BuyerTrade) getTrade()).onFiatPaymentStarted(resultHandler, errorMessageHandler); ((BuyerTrade) getTrade()).onFiatPaymentStarted(resultHandler, errorMessageHandler);
} }
public void onFiatPaymentReceived() { public void onFiatPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
checkNotNull(getTrade(), "trade must not be null"); checkNotNull(getTrade(), "trade must not be null");
checkArgument(getTrade() instanceof SellerTrade, "Check failed: trade instanceof SellerTrade"); checkArgument(getTrade() instanceof SellerTrade, "Check failed: trade instanceof SellerTrade");
if (getTrade().getDisputeState() == Trade.DisputeState.NONE) if (getTrade().getDisputeState() == Trade.DisputeState.NONE)
((SellerTrade) getTrade()).onFiatPaymentReceived(); ((SellerTrade) getTrade()).onFiatPaymentReceived(resultHandler, errorMessageHandler);
} }
public void onWithdrawRequest(String toAddress, ResultHandler resultHandler, FaultHandler faultHandler) { public void onWithdrawRequest(String toAddress, ResultHandler resultHandler, FaultHandler faultHandler) {

View file

@ -263,6 +263,9 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
private void onTradeStateChanged(Trade.State tradeState) { private void onTradeStateChanged(Trade.State tradeState) {
Log.traceCall(tradeState.toString()); Log.traceCall(tradeState.toString());
// TODO what is first valid state for trade?
switch (tradeState) { switch (tradeState) {
case PREPARATION: case PREPARATION:
sellerState.set(UNDEFINED); sellerState.set(UNDEFINED);
@ -270,44 +273,37 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
break; break;
case TAKER_FEE_PAID: case TAKER_FEE_PAID:
break; case OFFERER_SENT_PUBLISH_DEPOSIT_TX_REQUEST:
case TAKER_PUBLISHED_DEPOSIT_TX:
case DEPOSIT_PUBLISH_REQUESTED:
break;
case DEPOSIT_PUBLISHED:
case DEPOSIT_SEEN_IN_NETWORK: case DEPOSIT_SEEN_IN_NETWORK:
case DEPOSIT_PUBLISHED_MSG_SENT: case TAKER_SENT_DEPOSIT_TX_PUBLISHED_MSG:
case DEPOSIT_PUBLISHED_MSG_RECEIVED: case OFFERER_RECEIVED_DEPOSIT_TX_PUBLISHED_MSG:
sellerState.set(WAIT_FOR_BLOCKCHAIN_CONFIRMATION); sellerState.set(WAIT_FOR_BLOCKCHAIN_CONFIRMATION);
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_BLOCKCHAIN_CONFIRMATION); buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_BLOCKCHAIN_CONFIRMATION);
break; break;
case DEPOSIT_CONFIRMED: case DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN:
buyerState.set(PendingTradesViewModel.BuyerState.REQUEST_START_FIAT_PAYMENT);
sellerState.set(WAIT_FOR_FIAT_PAYMENT_STARTED); sellerState.set(WAIT_FOR_FIAT_PAYMENT_STARTED);
buyerState.set(PendingTradesViewModel.BuyerState.REQUEST_START_FIAT_PAYMENT);
case BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED: // we stick with the state until we get the msg sent success
buyerState.set(PendingTradesViewModel.BuyerState.REQUEST_START_FIAT_PAYMENT);
break; break;
case FIAT_PAYMENT_STARTED: case BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG:
case FIAT_PAYMENT_STARTED_MSG_SENT:
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_FIAT_PAYMENT_RECEIPT); buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_FIAT_PAYMENT_RECEIPT);
break; break;
case FIAT_PAYMENT_STARTED_MSG_RECEIVED: case SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG: // seller
case FIAT_PAYMENT_RECEIPT: // In case the msg sending failed we stick in that view state case SELLER_CONFIRMED_FIAT_PAYMENT_RECEIPT: // we stick with the state until we get the msg sent success
sellerState.set(REQUEST_CONFIRM_FIAT_PAYMENT_RECEIVED); sellerState.set(REQUEST_CONFIRM_FIAT_PAYMENT_RECEIVED);
break; break;
case SELLER_SENT_FIAT_PAYMENT_RECEIPT_MSG:
case FIAT_PAYMENT_RECEIPT_MSG_SENT:
sellerState.set(WAIT_FOR_PAYOUT_TX); sellerState.set(WAIT_FOR_PAYOUT_TX);
break; break;
case FIAT_PAYMENT_RECEIPT_MSG_RECEIVED: case BUYER_RECEIVED_FIAT_PAYMENT_RECEIPT_MSG:
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_FIAT_PAYMENT_RECEIPT); case BUYER_COMMITTED_PAYOUT_TX:
break; case BUYER_STARTED_SEND_PAYOUT_TX:
case PAYOUT_TX_COMMITTED:
case PAYOUT_TX_SENT:
buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK); buyerState.set(PendingTradesViewModel.BuyerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
break; break;
case PAYOUT_TX_RECEIVED_AND_COMMITTED: case SELLER_RECEIVED_AND_COMMITTED_PAYOUT_TX:
sellerState.set(SellerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK); sellerState.set(SellerState.WAIT_FOR_BROADCAST_AFTER_UNLOCK);
break; break;
case PAYOUT_BROAD_CASTED: case PAYOUT_BROAD_CASTED:

View file

@ -44,7 +44,7 @@ import static io.bitsquare.gui.util.FormBuilder.*;
public class BuyerStep2View extends TradeStepView { public class BuyerStep2View extends TradeStepView {
private Button paymentStartedButton; private Button confirmButton;
private Label statusLabel; private Label statusLabel;
private ProgressIndicator statusProgressIndicator; private ProgressIndicator statusProgressIndicator;
private Subscription tradeStatePropertySubscription; private Subscription tradeStatePropertySubscription;
@ -65,7 +65,7 @@ public class BuyerStep2View extends TradeStepView {
//TODO we get called twice, check why //TODO we get called twice, check why
if (tradeStatePropertySubscription == null) { if (tradeStatePropertySubscription == null) {
tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> { tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> {
if (state.equals(Trade.State.DEPOSIT_CONFIRMED)) { if (state == Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN) {
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData(); PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
String key = "StartPaymentPopup_" + trade.getId(); String key = "StartPaymentPopup_" + trade.getId();
if (attentionRequiredPopup == null && !BitsquareApp.DEV_MODE) { if (attentionRequiredPopup == null && !BitsquareApp.DEV_MODE) {
@ -96,6 +96,11 @@ public class BuyerStep2View extends TradeStepView {
attentionRequiredPopup.show(); attentionRequiredPopup.show();
} }
} else if (state == Trade.State.BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED) {
showStatusInfo();
statusLabel.setText("Sending confirmation...");
} else if (state == Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG) {
hideStatusInfo();
} }
}); });
} }
@ -105,7 +110,7 @@ public class BuyerStep2View extends TradeStepView {
public void deactivate() { public void deactivate() {
super.deactivate(); super.deactivate();
removeStatusProgressIndicator(); hideStatusInfo();
if (tradeStatePropertySubscription != null) { if (tradeStatePropertySubscription != null) {
tradeStatePropertySubscription.unsubscribe(); tradeStatePropertySubscription.unsubscribe();
tradeStatePropertySubscription = null; tradeStatePropertySubscription = null;
@ -169,10 +174,12 @@ public class BuyerStep2View extends TradeStepView {
GridPane.setRowSpan(accountTitledGroupBg, gridRow - 3); GridPane.setRowSpan(accountTitledGroupBg, gridRow - 3);
Tuple3<Button, ProgressIndicator, Label> tuple3 = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "Payment started"); Tuple3<Button, ProgressIndicator, Label> tuple3 = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "Payment started");
paymentStartedButton = tuple3.first; confirmButton = tuple3.first;
paymentStartedButton.setOnAction(e -> onPaymentStarted()); confirmButton.setOnAction(e -> onPaymentStarted());
statusProgressIndicator = tuple3.second; statusProgressIndicator = tuple3.second;
statusLabel = tuple3.third; statusLabel = tuple3.third;
hideStatusInfo();
} }
@ -203,7 +210,7 @@ public class BuyerStep2View extends TradeStepView {
@Override @Override
protected void applyOnDisputeOpened() { protected void applyOnDisputeOpened() {
paymentStartedButton.setDisable(true); confirmButton.setDisable(true);
} }
@ -235,41 +242,31 @@ public class BuyerStep2View extends TradeStepView {
} }
private void confirmPaymentStarted() { private void confirmPaymentStarted() {
paymentStartedButton.setDisable(true); confirmButton.setDisable(true);
paymentStartedButton.setMinWidth(130);
statusProgressIndicator.setVisible(true);
statusProgressIndicator.setManaged(true);
statusProgressIndicator.setProgress(-1);
statusLabel.setWrapText(true);
statusLabel.setPrefWidth(160);
statusLabel.setText("Sending message to your trading partner.\n" +
"Please wait until you get the confirmation that the message has arrived.");
model.dataModel.onPaymentStarted(() -> { model.dataModel.onPaymentStarted(() -> {
// We would not really need an update as the success triggers a screen change
removeStatusProgressIndicator();
statusLabel.setText("");
// In case the first send failed we got the support button displayed. // In case the first send failed we got the support button displayed.
// If it succeeds at a second try we remove the support button again. // If it succeeds at a second try we remove the support button again.
//TODO check for support. in case of a dispute we dont want to hid ethe button //TODO check for support. in case of a dispute we dont want to hide the button
/*if (notificationGroup != null) { //if (notificationGroup != null)
notificationGroup.setButtonVisible(false); // notificationGroup.setButtonVisible(false);
}*/
}, errorMessage -> { }, errorMessage -> {
removeStatusProgressIndicator(); confirmButton.setDisable(false);
statusLabel.setText("Sending message to your trading partner failed.\n" + hideStatusInfo();
"Please try again and if it continue to fail report a bug."); new Popup().warning("Sending message to your trading partner failed.\n" +
paymentStartedButton.setDisable(false); "Please try again and if it continue to fail report a bug.").show();
}); });
} }
private void removeStatusProgressIndicator() { private void showStatusInfo() {
statusProgressIndicator.setVisible(false); statusProgressIndicator.setVisible(true);
statusProgressIndicator.setProgress(0); statusProgressIndicator.setManaged(true);
statusProgressIndicator.setManaged(false); statusProgressIndicator.setProgress(-1);
} }
private void hideStatusInfo() {
statusProgressIndicator.setVisible(false);
statusProgressIndicator.setManaged(false);
statusProgressIndicator.setProgress(0);
statusLabel.setText("");
}
} }

View file

@ -45,7 +45,7 @@ import static io.bitsquare.gui.util.FormBuilder.*;
public class SellerStep3View extends TradeStepView { public class SellerStep3View extends TradeStepView {
private Button confirmFiatReceivedButton; private Button confirmButton;
private Label statusLabel; private Label statusLabel;
private ProgressIndicator statusProgressIndicator; private ProgressIndicator statusProgressIndicator;
private Subscription tradeStatePropertySubscription; private Subscription tradeStatePropertySubscription;
@ -65,7 +65,7 @@ public class SellerStep3View extends TradeStepView {
super.activate(); super.activate();
tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> { tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> {
if (state.equals(Trade.State.FIAT_PAYMENT_STARTED_MSG_RECEIVED)) { if (state == Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG) {
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData(); PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
String key = "ConfirmPaymentPopup_" + trade.getId(); String key = "ConfirmPaymentPopup_" + trade.getId();
if (attentionRequiredPopup == null && !BitsquareApp.DEV_MODE) { if (attentionRequiredPopup == null && !BitsquareApp.DEV_MODE) {
@ -95,6 +95,11 @@ public class SellerStep3View extends TradeStepView {
attentionRequiredPopup.show(); attentionRequiredPopup.show();
} }
} else if (state == Trade.State.SELLER_CONFIRMED_FIAT_PAYMENT_RECEIPT) {
showStatusInfo();
statusLabel.setText("Sending confirmation...");
} else if (state == Trade.State.SELLER_SENT_FIAT_PAYMENT_RECEIPT_MSG) {
hideStatusInfo();
} }
}); });
} }
@ -103,9 +108,12 @@ public class SellerStep3View extends TradeStepView {
public void deactivate() { public void deactivate() {
super.deactivate(); super.deactivate();
if (tradeStatePropertySubscription != null) if (tradeStatePropertySubscription != null) {
tradeStatePropertySubscription.unsubscribe(); tradeStatePropertySubscription.unsubscribe();
statusProgressIndicator.setProgress(0); tradeStatePropertySubscription = null;
}
hideStatusInfo();
} }
@ -151,10 +159,12 @@ public class SellerStep3View extends TradeStepView {
} }
Tuple3<Button, ProgressIndicator, Label> tuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "Confirm payment receipt"); Tuple3<Button, ProgressIndicator, Label> tuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "Confirm payment receipt");
confirmFiatReceivedButton = tuple.first; confirmButton = tuple.first;
confirmFiatReceivedButton.setOnAction(e -> onPaymentReceived()); confirmButton.setOnAction(e -> onPaymentReceived());
statusProgressIndicator = tuple.second; statusProgressIndicator = tuple.second;
statusLabel = tuple.third; statusLabel = tuple.third;
hideStatusInfo();
} }
@ -208,7 +218,7 @@ public class SellerStep3View extends TradeStepView {
@Override @Override
protected void applyOnDisputeOpened() { protected void applyOnDisputeOpened() {
confirmFiatReceivedButton.setDisable(true); confirmButton.setDisable(true);
} }
@ -243,13 +253,33 @@ public class SellerStep3View extends TradeStepView {
} }
private void confirmPaymentReceived() { private void confirmPaymentReceived() {
confirmFiatReceivedButton.setDisable(true); confirmButton.setDisable(true);
model.dataModel.onFiatPaymentReceived(() -> {
// In case the first send failed we got the support button displayed.
// If it succeeds at a second try we remove the support button again.
//TODO check for support. in case of a dispute we dont want to hide the button
//if (notificationGroup != null)
// notificationGroup.setButtonVisible(false);
}, errorMessage -> {
confirmButton.setDisable(false);
hideStatusInfo();
new Popup().warning("Sending message to your trading partner failed.\n" +
"Please try again and if it continue to fail report a bug.").show();
});
}
private void showStatusInfo() {
statusProgressIndicator.setVisible(true); statusProgressIndicator.setVisible(true);
statusProgressIndicator.setManaged(true);
statusProgressIndicator.setProgress(-1); statusProgressIndicator.setProgress(-1);
statusLabel.setText("Sending message to trading partner..."); }
model.dataModel.onFiatPaymentReceived(); private void hideStatusInfo() {
statusProgressIndicator.setVisible(false);
statusProgressIndicator.setManaged(false);
statusProgressIndicator.setProgress(0);
statusLabel.setText("");
} }
} }

View file

@ -260,7 +260,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
Tuple2<Label, ComboBox> labelComboBoxTuple2 = addLabelComboBox(root, gridRow); Tuple2<Label, ComboBox> labelComboBoxTuple2 = addLabelComboBox(root, gridRow);
cryptoCurrenciesComboBox = labelComboBoxTuple2.second; cryptoCurrenciesComboBox = labelComboBoxTuple2.second;
GridPane.setColumnIndex(cryptoCurrenciesComboBox, 3); GridPane.setColumnIndex(cryptoCurrenciesComboBox, 3);
cryptoCurrenciesComboBox.setPromptText("Add crypto currency"); cryptoCurrenciesComboBox.setPromptText("Add cryptocurrency");
cryptoCurrenciesComboBox.setConverter(new StringConverter<CryptoCurrency>() { cryptoCurrenciesComboBox.setConverter(new StringConverter<CryptoCurrency>() {
@Override @Override
public String toString(CryptoCurrency tradeCurrency) { public String toString(CryptoCurrency tradeCurrency) {