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

@ -38,7 +38,7 @@ public class FiatAccount implements Serializable {
public static final long WEEK_IN_BLOCKS = DAY_IN_BLOCKS * 7;
public enum Type {
IRC("", "", 1),
IRC("", "", 0),
SEPA("IBAN", "BIC", WEEK_IN_BLOCKS),
WIRE("primary ID", "secondary ID", WEEK_IN_BLOCKS),
INTERNATIONAL("primary ID", "secondary ID", 2 * WEEK_IN_BLOCKS),

View File

@ -169,8 +169,8 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
private void setupReplyHandler() {
peerDHT.peer().objectDataReply((sender, message) -> {
log.debug("Incoming message with peerAddress " + sender);
log.debug("Incoming message with type " + message);
//log.debug("Incoming message with peerAddress " + sender);
//log.debug("Incoming message with type " + message);
int messageSize = 0;
if (message != null)
@ -189,7 +189,7 @@ public class TomP2PMessageService extends TomP2PService implements MessageServic
MessageWithPubKey messageWithPubKey = null;
try {
messageWithPubKey = getDecryptedMessageWithPubKey((SealedAndSignedMessage) message);
log.debug("decrypted message " + messageWithPubKey.getMessage());
//log.debug("decrypted message " + messageWithPubKey.getMessage());
e.handleMessage(messageWithPubKey, new TomP2PPeer(sender));
} catch (CryptoException e1) {
e1.printStackTrace();

View File

@ -29,6 +29,8 @@ import org.bitcoinj.core.Coin;
import java.io.Serializable;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,8 +52,10 @@ public abstract class BuyerTrade extends Trade implements Serializable {
@Override
protected void initStates() {
processState = BuyerTradeState.ProcessState.UNDEFINED;
lifeCycleState = Trade.LifeCycleState.PREPARATION;
if (processState == null)
processState = BuyerTradeState.ProcessState.UNDEFINED;
if (lifeCycleState == null)
lifeCycleState = Trade.LifeCycleState.PREPARATION;
initStateProperties();
}
@ -69,12 +73,28 @@ public abstract class BuyerTrade extends Trade implements Serializable {
public void setProcessState(TradeState.ProcessState processState) {
super.setProcessState(processState);
/* switch ((BuyerTradeState.ProcessState) processState) {
case EXCEPTION:
switch ((BuyerTradeState.ProcessState) processState) {
case DEPOSIT_PUBLISHED:
takeOfferDate = new Date();
if (this instanceof OffererTrade)
openOfferManager.closeOpenOffer(getOffer());
break;
case TIMEOUT:
disposeProtocol();
setLifeCycleState(Trade.LifeCycleState.FAILED);
tradeManager.removeFailedTrade(this);
break;
}*/
case FAULT:
disposeProtocol();
setLifeCycleState(Trade.LifeCycleState.FAILED);
tradeManager.removeFailedTrade(this);
break;
}
}
@Override

View File

@ -29,6 +29,8 @@ import org.bitcoinj.core.Coin;
import java.io.Serializable;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,8 +52,10 @@ public abstract class SellerTrade extends Trade implements Serializable {
@Override
protected void initStates() {
processState = SellerTradeState.ProcessState.UNDEFINED;
lifeCycleState = Trade.LifeCycleState.PENDING;
if (processState == null)
processState = SellerTradeState.ProcessState.UNDEFINED;
if (lifeCycleState == null)
lifeCycleState = Trade.LifeCycleState.PENDING;
initStateProperties();
}
@ -68,12 +72,28 @@ public abstract class SellerTrade extends Trade implements Serializable {
public void setProcessState(TradeState.ProcessState processState) {
super.setProcessState(processState);
/* switch ((SellerTradeState.ProcessState) processState) {
case EXCEPTION:
switch ((SellerTradeState.ProcessState) processState) {
case DEPOSIT_PUBLISHED_MSG_RECEIVED:
takeOfferDate = new Date();
if (this instanceof OffererTrade)
openOfferManager.closeOpenOffer(getOffer());
break;
case TIMEOUT:
disposeProtocol();
setLifeCycleState(Trade.LifeCycleState.FAILED);
tradeManager.removeFailedTrade(this);
break;
}*/
case FAULT:
disposeProtocol();
setLifeCycleState(Trade.LifeCycleState.FAILED);
tradeManager.removeFailedTrade(this);
break;
}
}
@Override

View File

@ -31,6 +31,7 @@ import io.bitsquare.p2p.MessageService;
import io.bitsquare.p2p.Peer;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.offer.Offer;
import io.bitsquare.trade.offer.OpenOfferManager;
import io.bitsquare.trade.protocol.trade.ProcessModel;
import io.bitsquare.trade.protocol.trade.TradeProtocol;
import io.bitsquare.trade.states.BuyerTradeState;
@ -75,6 +76,7 @@ abstract public class Trade implements Tradable, Model, Serializable {
private transient static final Logger log = LoggerFactory.getLogger(Trade.class);
public enum LifeCycleState {
PREPARATION,
PENDING,
@ -100,6 +102,9 @@ abstract public class Trade implements Tradable, Model, Serializable {
transient private Storage<? extends TradableList> storage;
transient protected TradeProtocol tradeProtocol;
transient protected TradeManager tradeManager;
transient protected OpenOfferManager openOfferManager;
// Immutable
private final Offer offer;
private final ProcessModel processModel;
@ -107,7 +112,7 @@ abstract public class Trade implements Tradable, Model, Serializable {
// Mutable
private MessageWithPubKey messageWithPubKey;
private Date takeOfferDate;
protected Date takeOfferDate;
protected TradeState.ProcessState processState;
protected Trade.LifeCycleState lifeCycleState;
private Transaction depositTx;
@ -169,9 +174,14 @@ abstract public class Trade implements Tradable, Model, Serializable {
BlockChainService blockChainService,
CryptoService cryptoService,
ArbitrationRepository arbitrationRepository,
TradeManager tradeManager,
OpenOfferManager openOfferManager,
User user,
KeyRing keyRing) {
this.tradeManager = tradeManager;
this.openOfferManager = openOfferManager;
processModel.onAllServicesInitialized(offer,
messageService,
addressService,
@ -254,6 +264,21 @@ abstract public class Trade implements Tradable, Model, Serializable {
setProcessState(BuyerTradeState.ProcessState.FAULT);
}
public boolean isFaultState() {
return processState == BuyerTradeState.ProcessState.FAULT || processState == SellerTradeState.ProcessState.FAULT;
}
/* public void resetFault() {
if (this instanceof SellerTrade)
setProcessState(SellerTradeState.ProcessState.UNDEFINED);
else if (this instanceof BuyerTrade)
setProcessState(BuyerTradeState.ProcessState.UNDEFINED);
setLifeCycleState(LifeCycleState.PREPARATION);
errorMessage = null;
throwable = null;
}*/
public void setLifeCycleState(Trade.LifeCycleState lifeCycleState) {
this.lifeCycleState = lifeCycleState;
lifeCycleStateProperty.set(lifeCycleState);

View File

@ -45,8 +45,6 @@ import io.bitsquare.trade.protocol.availability.OfferAvailabilityModel;
import io.bitsquare.trade.protocol.trade.messages.DepositTxInputsRequest;
import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.SellerTradeState;
import io.bitsquare.user.User;
import org.bitcoinj.core.AddressFormatException;
@ -187,10 +185,9 @@ public class TradeManager {
trade = new SellerAsOffererTrade(offer, pendingTradesStorage);
trade.setStorage(pendingTradesStorage);
pendingTrades.add(trade);
initTrade(trade);
pendingTrades.add(trade);
((OffererTrade) trade).handleTakeOfferRequest(message, sender);
setupDepositPublishedListener(trade);
}
else {
// TODO respond
@ -208,22 +205,12 @@ public class TradeManager {
blockChainService,
cryptoService,
arbitrationRepository,
this,
openOfferManager,
user,
keyRing);
}
// Only after published we consider the openOffer as closed and the trade as completely initialized
private void setupDepositPublishedListener(Trade trade) {
trade.processStateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("setupDepositPublishedListener state = " + newValue);
if (newValue == BuyerTradeState.ProcessState.DEPOSIT_PUBLISHED ||
newValue == SellerTradeState.ProcessState.DEPOSIT_PUBLISHED_MSG_RECEIVED) {
openOfferManager.closeOpenOffer(trade.getOffer());
trade.setTakeOfferDate(new Date());
}
});
}
private void setMailboxMessagesToTrades(List<SealedAndSignedMessage> encryptedMessages) {
log.trace("applyMailboxMessage encryptedMailboxMessage.size=" + encryptedMessages.size());
for (SealedAndSignedMessage encrypted : encryptedMessages) {
@ -268,9 +255,9 @@ public class TradeManager {
initTrade(trade);
}
}
for (Trade trade : failedTrades) {
pendingTrades.remove(trade);
closedTradableManager.add(trade);
removeFailedTrade(trade);
}
}
@ -367,7 +354,13 @@ public class TradeManager {
}
}
// In a fault case we remove it and add it to the closed trades
public void removeFailedTrade(Trade trade) {
pendingTrades.remove(trade);
closedTradableManager.add(trade);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
@ -380,5 +373,8 @@ public class TradeManager {
return offer.isMyOffer(keyRing);
}
private Optional<Trade> findTrade(String id) {
return pendingTrades.stream().filter(trade -> trade.getId().equals(id)).findAny();
}
}

View File

@ -167,6 +167,10 @@ public class Offer implements Serializable {
// TODO check upper and lower bounds for fiat
}
public void resetState() {
setState(State.UNDEFINED);
}
public boolean isMyOffer(KeyRing keyRing) {
return getPubKeyRing().getHashString().equals(keyRing.getPubKeyRing().getHashString());
}

View File

@ -84,7 +84,6 @@ public class OpenOffer implements Tradable, Serializable {
startTimeout();
else
stopTimeout();
}
public State getState() {

View File

@ -231,7 +231,7 @@ public class OpenOfferManager {
}
public Optional<OpenOffer> findOpenOffer(String offerId) {
return openOffers.stream().filter(openOffer -> openOffer.getOffer().getId().equals(offerId)).findAny();
return openOffers.stream().filter(openOffer -> openOffer.getId().equals(offerId)).findAny();
}
// Close openOffer after deposit published

View File

@ -60,7 +60,6 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
public BuyerAsOffererProtocol(BuyerAsOffererTrade trade) {
super(trade.getProcessModel());
log.debug("New OffererProtocol " + this);
this.buyerAsOffererTrade = trade;
// If we are after the timelock state we need to setup the listener again
@ -68,10 +67,10 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
if (state == BuyerTradeState.ProcessState.PAYOUT_TX_COMMITTED ||
state == BuyerTradeState.ProcessState.PAYOUT_TX_SENT ||
state == BuyerTradeState.ProcessState.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
log.debug("taskRunner completed");
// we are done!
handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);
@ -83,29 +82,9 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
// Mailbox
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, Peer taker) {
checkTradeId(processModel.getId(), message);
processModel.setTradeMessage(message);
buyerAsOffererTrade.setTradingPeer(taker);
//buyerAsOffererTrade.setLifeCycleState(OffererTradeState.LifeCycleState.OFFER_RESERVED);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
() -> log.debug("taskRunner at handleRequestDepositTxInputsMessage completed"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
ProcessDepositTxInputsRequest.class,
CreateDepositTxInputs.class,
SendPayDepositRequest.class
);
startTimeout();
taskRunner.run();
}
@Override
public void doApplyMailboxMessage(Message message, Trade trade) {
this.trade = trade;
@ -121,6 +100,29 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
log.error(errorMessage);
}));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Start trade
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, Peer taker) {
checkTradeId(processModel.getId(), message);
processModel.setTradeMessage(message);
buyerAsOffererTrade.setTradingPeer(taker);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
() -> handleTaskRunnerSuccess("handleTakeOfferRequest"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
ProcessDepositTxInputsRequest.class,
CreateDepositTxInputs.class,
SendPayDepositRequest.class
);
startTimeout();
taskRunner.run();
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -132,7 +134,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
() -> log.debug("taskRunner at handleRequestPublishDepositTxMessage completed"),
() -> handleTaskRunnerSuccess("PublishDepositTxRequest"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
ProcessPublishDepositTxRequest.class,
@ -155,7 +157,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
buyerAsOffererTrade.setProcessState(BuyerTradeState.ProcessState.FIAT_PAYMENT_STARTED);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
() -> log.debug("taskRunner at handleBankTransferStartedUIEvent completed"),
() -> handleTaskRunnerSuccess("onFiatPaymentStarted"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
VerifyTakeOfferFeePayment.class,
@ -175,8 +177,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade,
() -> {
log.debug("taskRunner at handlePayoutTxPublishedMessage completed");
// we are done!
handleTaskRunnerSuccess("FinalizePayoutTxRequest");
processModel.onComplete();
},
this::handleTaskRunnerFault);

View File

@ -60,7 +60,6 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
public BuyerAsTakerProtocol(BuyerAsTakerTrade trade) {
super(trade.getProcessModel());
log.debug("New SellerAsTakerProtocol " + this);
this.buyerAsTakerTrade = trade;
processModel.tradingPeer.setPubKeyRing(trade.getOffer().getPubKeyRing());
@ -72,8 +71,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
state == BuyerTradeState.ProcessState.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
log.debug("taskRunner completed");
// we are done!
handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);
@ -85,7 +83,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
// Mailbox
///////////////////////////////////////////////////////////////////////////////////////////
@Override
@ -104,10 +102,15 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
}));
}
///////////////////////////////////////////////////////////////////////////////////////////
// Start trade
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() {
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
() -> log.debug("taskRunner at takeAvailableOffer completed"),
() -> handleTaskRunnerSuccess("takeAvailableOffer"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
@ -130,7 +133,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
() -> log.debug("taskRunner at handleRequestPublishDepositTxMessage completed"),
() -> handleTaskRunnerSuccess("PublishDepositTxRequest"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
ProcessPublishDepositTxRequest.class,
@ -152,9 +155,8 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
public void onFiatPaymentStarted() {
buyerAsTakerTrade.setProcessState(BuyerTradeState.ProcessState.FIAT_PAYMENT_STARTED);
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
() -> log.debug("taskRunner at onFiatPaymentStarted completed"),
() -> handleTaskRunnerSuccess("onFiatPaymentStarted"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
VerifyOfferFeePayment.class,
@ -174,8 +176,7 @@ public class BuyerAsTakerProtocol extends TradeProtocol implements BuyerProtocol
TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsTakerTrade,
() -> {
log.debug("taskRunner at handlePayoutTxPublishedMessage completed");
// we are done!
handleTaskRunnerSuccess("FinalizePayoutTxRequest");
processModel.onComplete();
},
this::handleTaskRunnerFault);

View File

@ -58,7 +58,6 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
public SellerAsOffererProtocol(SellerAsOffererTrade trade) {
super(trade.getProcessModel());
log.debug("New OffererProtocol " + this);
this.sellerAsOffererTrade = trade;
// If we are after the timelock state we need to setup the listener again
@ -68,8 +67,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
state == SellerTradeState.ProcessState.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
log.debug("taskRunner completed");
// we are done!
handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);
@ -81,29 +79,9 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
// Mailbox
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, Peer taker) {
processModel.setTradeMessage(message);
sellerAsOffererTrade.setTradingPeer(taker);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
() -> log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
ProcessPayDepositRequest.class,
VerifyTakerAccount.class,
CreateAndSignContract.class,
CreateAndSignDepositTx.class,
SendPublishDepositTxRequest.class
);
startTimeout();
taskRunner.run();
}
@Override
public void doApplyMailboxMessage(Message message, Trade trade) {
this.trade = trade;
@ -129,6 +107,31 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
}
///////////////////////////////////////////////////////////////////////////////////////////
// Start trade
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void handleTakeOfferRequest(TradeMessage message, Peer taker) {
processModel.setTradeMessage(message);
sellerAsOffererTrade.setTradingPeer(taker);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
() -> handleTaskRunnerSuccess("handleTakeOfferRequest"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
ProcessPayDepositRequest.class,
VerifyTakerAccount.class,
CreateAndSignContract.class,
CreateAndSignDepositTx.class,
SendPublishDepositTxRequest.class
);
startTimeout();
taskRunner.run();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Incoming message handling
///////////////////////////////////////////////////////////////////////////////////////////
@ -138,7 +141,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
() -> log.debug("taskRunner at handleDepositTxPublishedMessage completed"),
() -> handleTaskRunnerSuccess("DepositTxPublishedMessage"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
@ -157,7 +160,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
() -> log.debug("taskRunner at handleFiatTransferStartedMessage completed"),
() -> handleTaskRunnerSuccess("FiatTransferStartedMessage"),
this::handleTaskRunnerFault);
taskRunner.addTasks(ProcessFiatTransferStartedMessage.class);
@ -175,12 +178,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
sellerAsOffererTrade.setProcessState(SellerTradeState.ProcessState.FIAT_PAYMENT_RECEIPT);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
() -> {
log.debug("taskRunner at handleFiatReceivedUIEvent completed");
// we are done!
processModel.onComplete();
},
() -> handleTaskRunnerSuccess("onFiatPaymentReceived"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
@ -188,14 +186,19 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt
SignPayoutTx.class,
SendFinalizePayoutTxRequest.class
);
startTimeout();
taskRunner.run();
}
private void handle(PayoutTxFinalizedMessage tradeMessage) {
stopTimeout();
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade,
() -> log.debug("taskRunner at handleFiatTransferStartedMessage completed"),
() -> {
handleTaskRunnerSuccess("PayoutTxFinalizedMessage");
processModel.onComplete();
},
this::handleTaskRunnerFault);
taskRunner.addTasks(

View File

@ -63,7 +63,6 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
public SellerAsTakerProtocol(SellerAsTakerTrade trade) {
super(trade.getProcessModel());
log.debug("New SellerAsTakerProtocol " + this);
this.sellerAsTakerTrade = trade;
processModel.tradingPeer.setPubKeyRing(trade.getOffer().getPubKeyRing());
@ -76,8 +75,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
state == SellerTradeState.ProcessState.PAYOUT_BROAD_CASTED) {
TradeTaskRunner taskRunner = new TradeTaskRunner(trade,
() -> {
log.debug("taskRunner completed");
// we are done!
handleTaskRunnerSuccess("SetupPayoutTxLockTimeReachedListener");
processModel.onComplete();
},
this::handleTaskRunnerFault);
@ -90,7 +88,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
///////////////////////////////////////////////////////////////////////////////////////////
// Public methods
// Mailbox
///////////////////////////////////////////////////////////////////////////////////////////
@Override
@ -117,10 +115,15 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Start trade
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void takeAvailableOffer() {
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
() -> log.debug("taskRunner at takeAvailableOffer completed"),
() -> handleTaskRunnerSuccess("takeAvailableOffer"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
@ -143,7 +146,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
() -> log.debug("taskRunner at RequestPayDepositMessage completed"),
() -> handleTaskRunnerSuccess("PayDepositRequest"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
@ -162,7 +165,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
() -> log.debug("taskRunner at DepositTxPublishedMessage completed"),
() -> handleTaskRunnerSuccess("DepositTxPublishedMessage"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
@ -181,7 +184,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
() -> log.debug("taskRunner at FiatTransferStartedMessage completed"),
() -> handleTaskRunnerSuccess("FiatTransferStartedMessage"),
this::handleTaskRunnerFault);
taskRunner.addTasks(ProcessFiatTransferStartedMessage.class);
@ -199,12 +202,7 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
sellerAsTakerTrade.setProcessState(SellerTradeState.ProcessState.FIAT_PAYMENT_RECEIPT);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
() -> {
log.debug("taskRunner at onFiatPaymentReceived completed");
// we are done!
processModel.onComplete();
},
() -> handleTaskRunnerSuccess("onFiatPaymentReceived"),
this::handleTaskRunnerFault);
taskRunner.addTasks(
@ -212,15 +210,19 @@ public class SellerAsTakerProtocol extends TradeProtocol implements SellerProtoc
SignPayoutTx.class,
SendFinalizePayoutTxRequest.class
);
startTimeout();
taskRunner.run();
}
private void handle(PayoutTxFinalizedMessage tradeMessage) {
log.debug("handle PayoutTxFinalizedMessage");
stopTimeout();
processModel.setTradeMessage(tradeMessage);
TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsTakerTrade,
() -> log.debug("taskRunner at PayoutTxFinalizedMessage completed"),
() -> {
handleTaskRunnerSuccess("PayoutTxFinalizedMessage");
processModel.onComplete();
},
this::handleTaskRunnerFault);
taskRunner.addTasks(

View File

@ -157,6 +157,10 @@ public abstract class TradeProtocol {
}
}
protected void handleTaskRunnerSuccess(String info) {
log.debug("handleTaskRunnerSuccess " + info);
}
protected void handleTaskRunnerFault(String errorMessage) {
log.error(errorMessage);
cleanup();

View File

@ -32,4 +32,5 @@ public class TradeTaskRunner extends TaskRunner<Trade> {
public TradeTaskRunner(Trade sharedModel, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
super(sharedModel, (Class<? extends Model>) sharedModel.getClass().getSuperclass().getSuperclass(), resultHandler, errorMessageHandler);
}
}

View File

@ -35,6 +35,7 @@ public class PayDepositRequest extends TradeMessage implements Serializable {
// That object is sent over the wire, so we need to take care of version compatibility.
private static final long serialVersionUID = Version.NETWORK_PROTOCOL_VERSION;
public final Coin tradeAmount;
public final List<TransactionOutput> buyerConnectedOutputsForAllInputs;
public final List<TransactionOutput> buyerOutputs;
public final byte[] buyerTradeWalletPubKey;
@ -42,7 +43,7 @@ public class PayDepositRequest extends TradeMessage implements Serializable {
public final PubKeyRing buyerPubKeyRing;
public final FiatAccount buyerFiatAccount;
public final String buyerAccountId;
public final Coin tradeAmount;
public final String takeOfferFeeTxId;
public PayDepositRequest(String tradeId,
Coin tradeAmount,
@ -52,7 +53,8 @@ public class PayDepositRequest extends TradeMessage implements Serializable {
byte[] buyerTradeWalletPubKey,
PubKeyRing buyerPubKeyRing,
FiatAccount buyerFiatAccount,
String buyerAccountId) {
String buyerAccountId,
String takeOfferFeeTxId) {
super(tradeId);
this.tradeAmount = tradeAmount;
this.isInitialRequest = isInitialRequest;
@ -62,5 +64,6 @@ public class PayDepositRequest extends TradeMessage implements Serializable {
this.buyerTradeWalletPubKey = buyerTradeWalletPubKey;
this.buyerFiatAccount = buyerFiatAccount;
this.buyerAccountId = buyerAccountId;
this.takeOfferFeeTxId = takeOfferFeeTxId;
}
}

View File

@ -15,11 +15,12 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol.trade;
package io.bitsquare.trade.protocol.trade.tasks;
import io.bitsquare.common.taskrunner.Task;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.ProcessModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -21,7 +21,7 @@ import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.TradeWalletService;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import org.bitcoinj.core.Coin;

View File

@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.DepositTxInputsRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import org.slf4j.Logger;

View File

@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.FinalizePayoutTxRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.StateUtil;

View File

@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import org.slf4j.Logger;

View File

@ -20,8 +20,8 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.StateUtil;

View File

@ -20,8 +20,8 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.StateUtil;

View File

@ -21,8 +21,8 @@ import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.BuyerAsTakerTrade;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import org.slf4j.Logger;
@ -49,7 +49,8 @@ public class SendPayDepositRequest extends TradeTask {
processModel.getTradeWalletPubKey(),
processModel.getPubKeyRing(),
processModel.getFiatAccount(),
processModel.getAccountId());
processModel.getAccountId(),
processModel.getTakeOfferFeeTxId());
processModel.getMessageService().sendEncryptedMessage(
trade.getTradingPeer(),

View File

@ -20,8 +20,8 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.StateUtil;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;

View File

@ -21,7 +21,7 @@ import io.bitsquare.btc.FeePolicy;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.BuyerTrade;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.BuyerTradeState;
import org.bitcoinj.core.Coin;

View File

@ -20,7 +20,7 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Contract;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import io.bitsquare.util.Utilities;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.offerer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.offerer;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import org.slf4j.Logger;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.bitcoinj.core.Transaction;

View File

@ -20,7 +20,7 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Contract;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.util.Utilities;
import org.slf4j.Logger;

View File

@ -21,7 +21,7 @@ import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.TradeWalletService;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.bitcoinj.core.Coin;

View File

@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.SellerTradeState;
import org.slf4j.Logger;

View File

@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.SellerTradeState;
import org.slf4j.Logger;

View File

@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.PayDepositRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -50,6 +50,7 @@ public class ProcessPayDepositRequest extends TradeTask {
processModel.tradingPeer.setPubKeyRing(checkNotNull(message.buyerPubKeyRing));
processModel.tradingPeer.setFiatAccount(checkNotNull(message.buyerFiatAccount));
processModel.tradingPeer.setAccountId(nonEmptyStringOf(message.buyerAccountId));
processModel.setTakeOfferFeeTxId(nonEmptyStringOf(message.takeOfferFeeTxId));
trade.setTradeAmount(positiveCoinOf(nonZeroCoinOf(message.tradeAmount)));
complete();

View File

@ -19,8 +19,8 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.SellerTradeState;
import org.slf4j.Logger;

View File

@ -20,8 +20,8 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.DepositTxInputsRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import org.bitcoinj.utils.Threading;

View File

@ -20,8 +20,8 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.FinalizePayoutTxRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.SellerTradeState;
import io.bitsquare.trade.states.StateUtil;

View File

@ -20,8 +20,8 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.messages.PublishDepositTxRequest;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.StateUtil;
import org.slf4j.Logger;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.seller;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.bitcoinj.core.Coin;

View File

@ -21,7 +21,7 @@ import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.BuyerTrade;
import io.bitsquare.trade.SellerTrade;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.SellerTradeState;

View File

@ -21,7 +21,7 @@ import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.BuyerTrade;
import io.bitsquare.trade.SellerTrade;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import io.bitsquare.trade.states.BuyerTradeState;
import io.bitsquare.trade.states.SellerTradeState;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.taker;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.bitcoinj.core.Transaction;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.taker;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.bitcoinj.core.Transaction;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.taker;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -19,7 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.taker;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.TradeTask;
import io.bitsquare.trade.protocol.trade.tasks.TradeTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -1,26 +0,0 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.states;
public enum TradePhase {
PREPARATION, // No damage
TAKE_OFFER__FEE_PAID, // Offer fee can be lost
DEPOSIT_BROAD_CASTED, // Need arbitrator
PAYOUT_BROAD_CASTED // Only charge back risk open
}

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;