mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Improve state handling of trade
This commit is contained in:
parent
6099f36b53
commit
5768b93cdf
32 changed files with 179 additions and 249 deletions
|
@ -375,12 +375,13 @@ public class TradeWalletService {
|
|||
Futures.addCallback(broadcastComplete, callback);
|
||||
}
|
||||
|
||||
public void takerCommitsDepositTx(Transaction depositTx) throws WalletException {
|
||||
// Returns local transaction which has a different state as the serialized depositTx we get from the offerer
|
||||
public Transaction takerCommitsDepositTx(Transaction depositTx) throws WalletException {
|
||||
log.trace("takerCommitsDepositTx called");
|
||||
log.trace("depositTx " + depositTx.toString());
|
||||
|
||||
// We need to recreate the tx we get a null pointer otherwise
|
||||
depositTx = new Transaction(params, depositTx.bitcoinSerialize());
|
||||
Transaction localDepositTx = new Transaction(params, depositTx.bitcoinSerialize());
|
||||
|
||||
try {
|
||||
// TODO check if that is correct
|
||||
|
@ -390,6 +391,7 @@ public class TradeWalletService {
|
|||
t.printStackTrace();
|
||||
throw new WalletException(t);
|
||||
}
|
||||
return localDepositTx;
|
||||
}
|
||||
|
||||
public byte[] offererCreatesAndSignsPayoutTx(Transaction depositTx,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package io.bitsquare.gui.main.portfolio.offer;
|
||||
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
|
||||
/**
|
||||
* We could remove that wrapper if it is not needed for additional UI only fields.
|
||||
|
@ -26,8 +27,8 @@ class OfferListItem {
|
|||
|
||||
private final Offer offer;
|
||||
|
||||
public OfferListItem(Offer offer) {
|
||||
this.offer = offer;
|
||||
public OfferListItem(Trade trade) {
|
||||
this.offer = trade.getOffer();
|
||||
}
|
||||
|
||||
public Offer getOffer() {
|
||||
|
|
|
@ -23,6 +23,7 @@ import io.bitsquare.common.viewfx.model.Activatable;
|
|||
import io.bitsquare.common.viewfx.model.DataModel;
|
||||
import io.bitsquare.offer.Direction;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
|
@ -44,7 +45,7 @@ class OffersDataModel implements Activatable, DataModel {
|
|||
private final User user;
|
||||
|
||||
private final ObservableList<OfferListItem> list = FXCollections.observableArrayList();
|
||||
private final MapChangeListener<String, Offer> offerMapChangeListener;
|
||||
private final MapChangeListener<String, Trade> offerMapChangeListener;
|
||||
|
||||
|
||||
@Inject
|
||||
|
@ -63,17 +64,17 @@ class OffersDataModel implements Activatable, DataModel {
|
|||
@Override
|
||||
public void activate() {
|
||||
list.clear();
|
||||
list.addAll(tradeManager.getOpenOffers().values().stream().map(OfferListItem::new).collect(Collectors.toList()));
|
||||
list.addAll(tradeManager.getOpenOfferTrades().values().stream().map(OfferListItem::new).collect(Collectors.toList()));
|
||||
|
||||
// we sort by date, earliest first
|
||||
list.sort((o1, o2) -> o2.getOffer().getCreationDate().compareTo(o1.getOffer().getCreationDate()));
|
||||
|
||||
tradeManager.getOpenOffers().addListener(offerMapChangeListener);
|
||||
tradeManager.getOpenOfferTrades().addListener(offerMapChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
tradeManager.getOpenOffers().removeListener(offerMapChangeListener);
|
||||
tradeManager.getOpenOfferTrades().removeListener(offerMapChangeListener);
|
||||
}
|
||||
|
||||
void removeOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
|
|
|
@ -66,11 +66,11 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
private boolean isOfferer;
|
||||
private Trade closedTrade;
|
||||
|
||||
private final ChangeListener<Trade.State> tradeStateChangeListener;
|
||||
private final ChangeListener<Trade.ProcessState> tradeStateChangeListener;
|
||||
private final MapChangeListener<String, Trade> mapChangeListener;
|
||||
|
||||
final StringProperty txId = new SimpleStringProperty();
|
||||
final ObjectProperty<Trade.State> tradeState = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<Trade.ProcessState> tradeState = new SimpleObjectProperty<>();
|
||||
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
|
||||
|
||||
@Inject
|
||||
|
@ -146,9 +146,9 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
isOfferer = getTrade().getOffer().getP2PSigPubKey().equals(user.getP2PSigPubKey());
|
||||
|
||||
Trade trade = getTrade();
|
||||
trade.stateProperty().addListener(tradeStateChangeListener);
|
||||
tradeState.set(trade.stateProperty().get());
|
||||
log.trace("selectTrade trade.stateProperty().get() " + trade.stateProperty().get());
|
||||
trade.processStateProperty().addListener(tradeStateChangeListener);
|
||||
tradeState.set(trade.processStateProperty().get());
|
||||
log.trace("selectTrade trade.stateProperty().get() " + trade.processStateProperty().get());
|
||||
|
||||
if (trade.getDepositTx() != null)
|
||||
txId.set(trade.getDepositTx().getHashAsString());
|
||||
|
@ -277,7 +277,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
|
||||
private void cleanUpSelectedTrade() {
|
||||
if (selectedItem != null) {
|
||||
selectedItem.getTrade().stateProperty().removeListener(tradeStateChangeListener);
|
||||
selectedItem.getTrade().processStateProperty().removeListener(tradeStateChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -181,6 +181,7 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
|
|||
@FXML
|
||||
void onPaymentStarted() {
|
||||
model.fiatPaymentStarted();
|
||||
confirmPaymentReceiptButton.setDisable(true);
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
|
|
@ -218,10 +218,10 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
|
|||
|
||||
|
||||
private void updateState() {
|
||||
Trade.State tradeState = dataModel.tradeState.get();
|
||||
log.trace("tradeState " + tradeState);
|
||||
if (tradeState != null) {
|
||||
switch (tradeState) {
|
||||
Trade.ProcessState tradeProcessState = dataModel.tradeState.get();
|
||||
log.trace("tradeState " + tradeProcessState);
|
||||
if (tradeProcessState != null) {
|
||||
switch (tradeProcessState) {
|
||||
case DEPOSIT_PUBLISHED:
|
||||
state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_WAIT_TX_CONF : State.TAKER_SELLER_WAIT_TX_CONF);
|
||||
break;
|
||||
|
@ -240,7 +240,7 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
|
|||
// TODO error states not implemented yet
|
||||
break;
|
||||
default:
|
||||
log.warn("unhandled state " + tradeState);
|
||||
log.warn("unhandled state " + tradeProcessState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,12 +127,6 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||
// for irc demo
|
||||
showAdvancedSettingsButton.setVisible(false);
|
||||
showAdvancedSettingsButton.setManaged(false);
|
||||
|
||||
//TODO temp for testing
|
||||
|
||||
amountTextField.setText("1");
|
||||
priceTextField.setText("1");
|
||||
volumeTextField.setText("1");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -150,6 +144,11 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||
priceColumn.setSortType((model.getDirection() == Direction.BUY) ?
|
||||
TableColumn.SortType.ASCENDING : TableColumn.SortType.DESCENDING);
|
||||
table.sort();
|
||||
|
||||
//TODO temp for testing
|
||||
amountTextField.setText("1");
|
||||
priceTextField.setText("300");
|
||||
volumeTextField.setText("300");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -208,14 +208,14 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
|||
isTakeOfferSpinnerVisible.set(true);
|
||||
|
||||
dataModel.takeOffer((trade) -> {
|
||||
trade.stateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
trade.processStateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
log.debug("trade state = " + newValue);
|
||||
String msg = "";
|
||||
if (newValue.getErrorMessage() != null)
|
||||
msg = "\nError message: " + newValue.getErrorMessage();
|
||||
|
||||
switch (newValue) {
|
||||
case OPEN:
|
||||
case INIT:
|
||||
break;
|
||||
case TAKE_OFFER_FEE_TX_CREATED:
|
||||
break;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package io.bitsquare.trade;
|
||||
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
@ -38,8 +39,16 @@ public class Trade implements Serializable {
|
|||
// Enum
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public static enum State {
|
||||
OPEN,
|
||||
public static enum LifeCycleState {
|
||||
OPEN_OFFER,
|
||||
CANCELED,
|
||||
PENDING,
|
||||
COMPLETED,
|
||||
FAILED
|
||||
}
|
||||
|
||||
public static enum ProcessState {
|
||||
INIT,
|
||||
TAKE_OFFER_FEE_PUBLISH_FAILED,
|
||||
TAKE_OFFER_FEE_TX_CREATED,
|
||||
DEPOSIT_PUBLISHED,
|
||||
|
@ -64,7 +73,7 @@ public class Trade implements Serializable {
|
|||
|
||||
private final Offer offer;
|
||||
private final Date date;
|
||||
private State state;
|
||||
private ProcessState processState;
|
||||
private Coin tradeAmount;
|
||||
private Contract contract;
|
||||
private String contractAsJson;
|
||||
|
@ -72,13 +81,14 @@ public class Trade implements Serializable {
|
|||
private String offererContractSignature;
|
||||
private Transaction depositTx;
|
||||
private Transaction payoutTx;
|
||||
private Peer tradingPeer;
|
||||
|
||||
// For changing values we use properties to get binding support in the UI (table)
|
||||
// When serialized those transient properties are not instantiated, so we instantiate them in the getters at first
|
||||
// access. Only use the accessor not the private field.
|
||||
transient private ObjectProperty<Coin> _tradeAmount;
|
||||
transient private ObjectProperty<Fiat> _tradeVolume;
|
||||
transient private ObjectProperty<State> _state;
|
||||
transient private ObjectProperty<ProcessState> _state;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -89,7 +99,7 @@ public class Trade implements Serializable {
|
|||
this.offer = offer;
|
||||
date = new Date();
|
||||
|
||||
setState(State.OPEN);
|
||||
setProcessState(ProcessState.INIT);
|
||||
}
|
||||
|
||||
|
||||
|
@ -97,6 +107,10 @@ public class Trade implements Serializable {
|
|||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setTradingPeer(Peer tradingPeer) {
|
||||
this.tradingPeer = tradingPeer;
|
||||
}
|
||||
|
||||
public void setTakerContractSignature(String takerSignature) {
|
||||
this.takerContractSignature = takerSignature;
|
||||
}
|
||||
|
@ -135,9 +149,9 @@ public class Trade implements Serializable {
|
|||
this.payoutTx = tx;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
stateProperty().set(state);
|
||||
public void setProcessState(ProcessState processState) {
|
||||
this.processState = processState;
|
||||
processStateProperty().set(processState);
|
||||
}
|
||||
|
||||
|
||||
|
@ -165,8 +179,8 @@ public class Trade implements Serializable {
|
|||
return payoutTx;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
public ProcessState getProcessState() {
|
||||
return processState;
|
||||
}
|
||||
|
||||
public Coin getSecurityDeposit() {
|
||||
|
@ -189,6 +203,11 @@ public class Trade implements Serializable {
|
|||
return date;
|
||||
}
|
||||
|
||||
public Peer getTradingPeer() {
|
||||
return tradingPeer;
|
||||
}
|
||||
|
||||
|
||||
// When serialized those transient properties are not instantiated, so we need to instantiate them at first access
|
||||
public ObjectProperty<Coin> tradeAmountProperty() {
|
||||
if (_tradeAmount == null)
|
||||
|
@ -204,9 +223,9 @@ public class Trade implements Serializable {
|
|||
return _tradeVolume;
|
||||
}
|
||||
|
||||
public ObjectProperty<State> stateProperty() {
|
||||
public ObjectProperty<ProcessState> processStateProperty() {
|
||||
if (_state == null)
|
||||
_state = new SimpleObjectProperty<>(state);
|
||||
_state = new SimpleObjectProperty<>(processState);
|
||||
|
||||
return _state;
|
||||
}
|
||||
|
@ -216,7 +235,7 @@ public class Trade implements Serializable {
|
|||
return "Trade{" +
|
||||
"offer=" + offer +
|
||||
", date=" + date +
|
||||
", state=" + state +
|
||||
", state=" + processState +
|
||||
", tradeAmount=" + tradeAmount +
|
||||
", contract=" + contract +
|
||||
", contractAsJson='" + contractAsJson + '\'' +
|
||||
|
|
|
@ -90,7 +90,7 @@ public class TradeManager {
|
|||
private final Map<String, OffererAsBuyerProtocol> offererAsBuyerProtocolMap = new HashMap<>();
|
||||
private final Map<String, CheckOfferAvailabilityProtocol> checkOfferAvailabilityProtocolMap = new HashMap<>();
|
||||
|
||||
private final ObservableMap<String, Offer> openOffers = FXCollections.observableHashMap();
|
||||
private final ObservableMap<String, Trade> openOfferTrades = FXCollections.observableHashMap();
|
||||
private final ObservableMap<String, Trade> pendingTrades = FXCollections.observableHashMap();
|
||||
private final ObservableMap<String, Trade> closedTrades = FXCollections.observableHashMap();
|
||||
private final Map<String, MailboxMessage> mailboxMessages = new HashMap<>();
|
||||
|
@ -119,9 +119,9 @@ public class TradeManager {
|
|||
this.encryptionService = encryptionService;
|
||||
this.offerBookService = offerBookService;
|
||||
|
||||
Serializable openOffersObject = persistence.read(this, "openOffers");
|
||||
if (openOffersObject instanceof Map<?, ?>) {
|
||||
openOffers.putAll((Map<String, Offer>) openOffersObject);
|
||||
Serializable openOfferTradesObject = persistence.read(this, "openOfferTrades");
|
||||
if (openOfferTradesObject instanceof Map<?, ?>) {
|
||||
openOfferTrades.putAll((Map<String, Trade>) openOfferTradesObject);
|
||||
}
|
||||
|
||||
Serializable pendingTradesObject = persistence.read(this, "pendingTrades");
|
||||
|
@ -143,33 +143,19 @@ public class TradeManager {
|
|||
// When all services are initialized we create the protocols for our open offers and persisted not completed pendingTrades
|
||||
// BuyerAcceptsOfferProtocol listens for take offer requests, so we need to instantiate it early.
|
||||
public void onAllServicesInitialized() {
|
||||
for (Map.Entry<String, Offer> entry : openOffers.entrySet()) {
|
||||
for (Map.Entry<String, Trade> entry : openOfferTrades.entrySet()) {
|
||||
createOffererAsBuyerProtocol(entry.getValue());
|
||||
}
|
||||
for (Map.Entry<String, Trade> entry : pendingTrades.entrySet()) {
|
||||
// We continue an interrupted trade.
|
||||
// TODO if the peer has changed its IP address, we need to make another findPeer request. At the moment we use the peer stored in trade to
|
||||
// continue the trade, but that might fail.
|
||||
Trade trade = entry.getValue();
|
||||
if (trade.getState() == Trade.State.FAULT) {
|
||||
closeTrade(trade);
|
||||
if (isMyOffer(trade.getOffer())) {
|
||||
createOffererAsBuyerProtocol(trade);
|
||||
}
|
||||
else {
|
||||
Offer offer = trade.getOffer();
|
||||
if (isMyOffer(offer)) {
|
||||
createOffererAsBuyerProtocol(offer);
|
||||
}
|
||||
else {
|
||||
CheckOfferAvailabilityModel model = new CheckOfferAvailabilityModel(offer, messageService, addressService);
|
||||
CheckOfferAvailabilityProtocol protocol = new CheckOfferAvailabilityProtocol(model,
|
||||
() -> {
|
||||
disposeCheckOfferAvailabilityRequest(offer);
|
||||
// TODO need to check that trade hijacking is not possible (taking trades form other peers)
|
||||
if (offer.getState() == Offer.State.AVAILABLE || offer.getState() == Offer.State.RESERVED) {
|
||||
createTakerAsSellerProtocol(trade, model.getPeer());
|
||||
}
|
||||
},
|
||||
(errorMessage) -> disposeCheckOfferAvailabilityRequest(offer));
|
||||
checkOfferAvailabilityProtocolMap.put(offer.getId(), protocol);
|
||||
protocol.checkOfferAvailability();
|
||||
}
|
||||
createTakerAsSellerProtocol(trade);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,9 +206,10 @@ public class TradeManager {
|
|||
PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(
|
||||
model,
|
||||
(transaction) -> {
|
||||
openOffers.put(offer.getId(), offer);
|
||||
Trade trade = new Trade(offer);
|
||||
openOfferTrades.put(trade.getId(), trade);
|
||||
persistOpenOffers();
|
||||
createOffererAsBuyerProtocol(offer);
|
||||
createOffererAsBuyerProtocol(trade);
|
||||
resultHandler.handleResult(transaction);
|
||||
},
|
||||
(message) -> errorMessageHandler.handleErrorMessage(message)
|
||||
|
@ -340,8 +327,8 @@ public class TradeManager {
|
|||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public ObservableMap<String, Offer> getOpenOffers() {
|
||||
return openOffers;
|
||||
public ObservableMap<String, Trade> getOpenOfferTrades() {
|
||||
return openOfferTrades;
|
||||
}
|
||||
|
||||
public ObservableMap<String, Trade> getPendingTrades() {
|
||||
|
@ -372,8 +359,8 @@ public class TradeManager {
|
|||
String offerId = offer.getId();
|
||||
offerBookService.removeOffer(offer,
|
||||
() -> {
|
||||
if (openOffers.containsKey(offerId)) {
|
||||
openOffers.remove(offerId);
|
||||
if (openOfferTrades.containsKey(offerId)) {
|
||||
openOfferTrades.remove(offerId);
|
||||
disposeCheckOfferAvailabilityRequest(offer);
|
||||
persistOpenOffers();
|
||||
if (removeFromBuyerAcceptsOfferProtocolMap && offererAsBuyerProtocolMap.containsKey(offerId)) {
|
||||
|
@ -413,8 +400,9 @@ public class TradeManager {
|
|||
private Trade takeAvailableOffer(Coin amount, Offer offer, Peer peer) {
|
||||
Trade trade = createTrade(offer);
|
||||
trade.setTradeAmount(amount);
|
||||
trade.setTradingPeer(peer);
|
||||
|
||||
TakerAsSellerProtocol sellerTakesOfferProtocol = createTakerAsSellerProtocol(trade, peer);
|
||||
TakerAsSellerProtocol sellerTakesOfferProtocol = createTakerAsSellerProtocol(trade);
|
||||
sellerTakesOfferProtocol.takeAvailableOffer();
|
||||
return trade;
|
||||
}
|
||||
|
@ -432,11 +420,11 @@ public class TradeManager {
|
|||
return trade;
|
||||
}
|
||||
|
||||
private TakerAsSellerProtocol createTakerAsSellerProtocol(Trade trade, Peer peer) {
|
||||
trade.stateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
private TakerAsSellerProtocol createTakerAsSellerProtocol(Trade trade) {
|
||||
trade.processStateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
log.debug("trade state = " + newValue);
|
||||
switch (newValue) {
|
||||
case OPEN:
|
||||
case INIT:
|
||||
break;
|
||||
case TAKE_OFFER_FEE_TX_CREATED:
|
||||
case DEPOSIT_PUBLISHED:
|
||||
|
@ -458,7 +446,6 @@ public class TradeManager {
|
|||
|
||||
TakerAsSellerModel model = new TakerAsSellerModel(
|
||||
trade,
|
||||
peer,
|
||||
messageService,
|
||||
mailboxService,
|
||||
walletService,
|
||||
|
@ -478,17 +465,7 @@ public class TradeManager {
|
|||
}
|
||||
|
||||
|
||||
private void createOffererAsBuyerProtocol(Offer offer) {
|
||||
Trade trade;
|
||||
if (pendingTrades.containsKey(offer.getId())) {
|
||||
trade = pendingTrades.get(offer.getId());
|
||||
currentPendingTrade = trade;
|
||||
}
|
||||
else {
|
||||
trade = new Trade(offer);
|
||||
// don't save it in pendingTrades. It is only a potential trade
|
||||
}
|
||||
|
||||
private void createOffererAsBuyerProtocol(Trade trade) {
|
||||
OffererAsBuyerModel model = new OffererAsBuyerModel(
|
||||
trade,
|
||||
messageService,
|
||||
|
@ -501,16 +478,16 @@ public class TradeManager {
|
|||
|
||||
|
||||
// TODO check, remove listener
|
||||
trade.stateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
trade.processStateProperty().addListener((ov, oldValue, newValue) -> {
|
||||
log.debug("trade state = " + newValue);
|
||||
switch (newValue) {
|
||||
case OPEN:
|
||||
case INIT:
|
||||
break;
|
||||
case TAKE_OFFER_FEE_TX_CREATED:
|
||||
persistPendingTrades();
|
||||
break;
|
||||
case DEPOSIT_PUBLISHED:
|
||||
removeOpenOffer(offer,
|
||||
removeOpenOffer(trade.getOffer(),
|
||||
() -> log.debug("remove offer was successful"),
|
||||
(message) -> log.error(message),
|
||||
false);
|
||||
|
@ -531,7 +508,6 @@ public class TradeManager {
|
|||
case MESSAGE_SENDING_FAILED:
|
||||
case FAULT:
|
||||
closeTrade(trade);
|
||||
offererAsBuyerProtocolMap.get(trade.getId()).cleanup();
|
||||
break;
|
||||
default:
|
||||
log.warn("Unhandled trade state: " + newValue);
|
||||
|
@ -540,7 +516,7 @@ public class TradeManager {
|
|||
});
|
||||
|
||||
OffererAsBuyerProtocol protocol = new OffererAsBuyerProtocol(model);
|
||||
offererAsBuyerProtocolMap.put(offer.getId(), protocol);
|
||||
offererAsBuyerProtocolMap.put(trade.getId(), protocol);
|
||||
if (mailboxMessages.containsKey(trade.getId())) {
|
||||
log.debug("OffererAsBuyerProtocol setMailboxMessage " + trade.getId());
|
||||
protocol.setMailboxMessage(mailboxMessages.get(trade.getId()));
|
||||
|
@ -612,13 +588,13 @@ public class TradeManager {
|
|||
}
|
||||
|
||||
boolean isOfferOpen(String offerId) {
|
||||
return openOffers.containsKey(offerId)
|
||||
&& (openOffers.get(offerId).getState() == Offer.State.UNKNOWN
|
||||
|| openOffers.get(offerId).getState() == Offer.State.AVAILABLE);
|
||||
return openOfferTrades.containsKey(offerId)
|
||||
&& (openOfferTrades.get(offerId).getOffer().getState() == Offer.State.UNKNOWN
|
||||
|| openOfferTrades.get(offerId).getOffer().getState() == Offer.State.AVAILABLE);
|
||||
}
|
||||
|
||||
private void persistOpenOffers() {
|
||||
persistence.write(this, "openOffers", (Map<String, Offer>) new HashMap<>(openOffers));
|
||||
persistence.write(this, "openOfferTrades", (Map<String, Trade>) new HashMap<>(openOfferTrades));
|
||||
}
|
||||
|
||||
private void persistPendingTrades() {
|
||||
|
|
|
@ -22,7 +22,6 @@ import io.bitsquare.p2p.MailboxMessage;
|
|||
import io.bitsquare.p2p.Message;
|
||||
import io.bitsquare.p2p.MessageHandler;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.messages.PayoutTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestDepositTxInputsMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestOffererPublishDepositTxMessage;
|
||||
|
@ -42,8 +41,6 @@ import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyAndSignContract;
|
|||
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakeOfferFeePayment;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakerAccount;
|
||||
|
||||
import org.bitcoinj.core.TransactionConfidence;
|
||||
|
||||
import javafx.application.Platform;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -57,8 +54,6 @@ public class OffererAsBuyerProtocol {
|
|||
private final OffererAsBuyerModel model;
|
||||
private final MessageHandler messageHandler;
|
||||
|
||||
private TransactionConfidence.Listener transactionConfidenceListener;
|
||||
private TransactionConfidence transactionConfidence;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
|
@ -87,18 +82,13 @@ public class OffererAsBuyerProtocol {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void cleanup() {
|
||||
log.debug("cleanup " + this);
|
||||
|
||||
// tradeMessageService and transactionConfidence use CopyOnWriteArrayList as listeners, but be safe and delay remove a bit.
|
||||
Platform.runLater(() -> {
|
||||
model.messageService.removeMessageHandler(messageHandler);
|
||||
|
||||
if (transactionConfidence != null) {
|
||||
if (!transactionConfidence.removeEventListener(transactionConfidenceListener))
|
||||
throw new RuntimeException("Remove transactionConfidenceListener failed at BuyerAsOffererProtocol.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -109,16 +99,11 @@ public class OffererAsBuyerProtocol {
|
|||
private void handleRequestDepositTxInputsMessage(RequestDepositTxInputsMessage tradeMessage, Peer taker) {
|
||||
checkTradeId(model.id, tradeMessage);
|
||||
model.setTradeMessage(tradeMessage);
|
||||
model.taker.peer = taker;
|
||||
model.trade.setTradingPeer(taker);
|
||||
|
||||
TaskRunner<OffererAsBuyerModel> taskRunner = new TaskRunner<>(model,
|
||||
() -> {
|
||||
log.debug("sequence at handleTakeOfferFeePayedMessage completed");
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
() -> log.debug("sequence at handleTakeOfferFeePayedMessage completed"),
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
taskRunner.addTasks(
|
||||
ProcessRequestDepositTxInputsMessage.class,
|
||||
CreateOffererDepositTxInputs.class,
|
||||
|
@ -131,23 +116,8 @@ public class OffererAsBuyerProtocol {
|
|||
model.setTradeMessage(tradeMessage);
|
||||
|
||||
TaskRunner<OffererAsBuyerModel> taskRunner = new TaskRunner<>(model,
|
||||
() -> {
|
||||
log.debug("taskRunner at handleRequestOffererPublishDepositTxMessage completed");
|
||||
transactionConfidenceListener = (tx, reason) -> {
|
||||
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||
if (reason == TransactionConfidence.Listener.ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence
|
||||
.ConfidenceType.BUILDING) {
|
||||
|
||||
model.trade.setState(Trade.State.DEPOSIT_CONFIRMED);
|
||||
}
|
||||
};
|
||||
transactionConfidence = model.trade.getDepositTx().getConfidence();
|
||||
transactionConfidence.addEventListener(transactionConfidenceListener);
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
() -> log.debug("taskRunner at handleRequestOffererPublishDepositTxMessage completed"),
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
taskRunner.addTasks(
|
||||
ProcessRequestOffererPublishDepositTxMessage.class,
|
||||
VerifyTakerAccount.class,
|
||||
|
@ -167,13 +137,8 @@ public class OffererAsBuyerProtocol {
|
|||
// User clicked the "bank transfer started" button
|
||||
public void onFiatPaymentStarted() {
|
||||
TaskRunner<OffererAsBuyerModel> taskRunner = new TaskRunner<>(model,
|
||||
() -> {
|
||||
log.debug("sequence at handleBankTransferStartedUIEvent completed");
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
() -> log.debug("sequence at handleBankTransferStartedUIEvent completed"),
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
taskRunner.addTasks(
|
||||
CreateAndSignPayoutTx.class,
|
||||
VerifyTakeOfferFeePayment.class,
|
||||
|
@ -193,14 +158,11 @@ public class OffererAsBuyerProtocol {
|
|||
TaskRunner<OffererAsBuyerModel> taskRunner = new TaskRunner<>(model,
|
||||
() -> {
|
||||
log.debug("sequence at handlePayoutTxPublishedMessage completed");
|
||||
|
||||
// we are done!
|
||||
model.onComplete();
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
|
||||
taskRunner.addTasks(ProcessPayoutTxPublishedMessage.class);
|
||||
taskRunner.run();
|
||||
}
|
||||
|
@ -233,4 +195,8 @@ public class OffererAsBuyerProtocol {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTaskRunnerFault(String errorMessage) {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
package io.bitsquare.trade.protocol.trade.offerer.models;
|
||||
|
||||
import io.bitsquare.fiat.FiatAccount;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
@ -34,7 +33,6 @@ public class Taker implements Serializable {
|
|||
private static final long serialVersionUID = 2660909397210346486L;
|
||||
|
||||
// written by tasks
|
||||
public Peer peer;
|
||||
public String accountId;
|
||||
public FiatAccount fiatAccount;
|
||||
public PublicKey p2pSigPublicKey;
|
||||
|
|
|
@ -43,7 +43,7 @@ public class ProcessPayoutTxPublishedMessage extends Task<OffererAsBuyerModel> {
|
|||
|
||||
model.trade.setPayoutTx(checkNotNull(((PayoutTxPublishedMessage) model.getTradeMessage()).payoutTx));
|
||||
|
||||
model.trade.setState(Trade.State.PAYOUT_PUBLISHED);
|
||||
model.trade.setProcessState(Trade.ProcessState.PAYOUT_PUBLISHED);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -45,7 +45,7 @@ public class RequestTakerDepositPayment extends Task<OffererAsBuyerModel> {
|
|||
model.offerer.fiatAccount,
|
||||
model.offerer.accountId);
|
||||
|
||||
model.messageService.sendMessage(model.taker.peer, tradeMessage, new SendMessageListener() {
|
||||
model.messageService.sendMessage(model.trade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");
|
||||
|
|
|
@ -43,26 +43,26 @@ public class SendBankTransferStartedMessage extends Task<OffererAsBuyerModel> {
|
|||
model.taker.payoutAmount,
|
||||
model.offerer.addressEntry.getAddressString());
|
||||
|
||||
model.messageService.sendMessage(model.taker.peer, tradeMessage,
|
||||
model.messageService.sendMessage(model.trade.getTradingPeer(), tradeMessage,
|
||||
model.taker.p2pSigPublicKey,
|
||||
model.taker.p2pEncryptPubKey,
|
||||
new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("Sending BankTransferInitedMessage succeeded.");
|
||||
model.trade.setState(Trade.State.FIAT_PAYMENT_STARTED);
|
||||
model.trade.setProcessState(Trade.ProcessState.FIAT_PAYMENT_STARTED);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFault() {
|
||||
failed("Sending BankTransferInitedMessage failed.");
|
||||
model.trade.setState(Trade.State.FAULT);
|
||||
model.trade.setProcessState(Trade.ProcessState.FAULT);
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
failed("Sending BankTransferInitedMessage failed.");
|
||||
model.trade.setState(Trade.State.FAULT);
|
||||
model.trade.setProcessState(Trade.ProcessState.FAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class SendDepositTxToTaker extends Task<OffererAsBuyerModel> {
|
|||
protected void doRun() {
|
||||
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(model.id, model.trade.getDepositTx());
|
||||
|
||||
model.messageService.sendMessage(model.taker.peer, tradeMessage, new SendMessageListener() {
|
||||
model.messageService.sendMessage(model.trade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("DepositTxPublishedMessage successfully arrived at peer");
|
||||
|
|
|
@ -48,7 +48,7 @@ public class SetupListenerForBlockChainConfirmation extends Task<OffererAsBuyerM
|
|||
public void onConfidenceChanged(Transaction tx, ChangeReason reason) {
|
||||
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
|
||||
model.trade.setState(Trade.State.DEPOSIT_CONFIRMED);
|
||||
model.trade.setProcessState(Trade.ProcessState.DEPOSIT_CONFIRMED);
|
||||
|
||||
// transactionConfidence use CopyOnWriteArrayList as listeners, but be safe and delay remove a bit.
|
||||
Platform.runLater(() -> removeEventListener());
|
||||
|
@ -62,6 +62,6 @@ public class SetupListenerForBlockChainConfirmation extends Task<OffererAsBuyerM
|
|||
|
||||
private void removeEventListener() {
|
||||
if (!transactionConfidence.removeEventListener(transactionConfidenceListener))
|
||||
throw new RuntimeException("Remove transactionConfidenceListener failed at SetupListenerForBlockChainConfirmation.");
|
||||
log.error("Remove transactionConfidenceListener failed at SetupListenerForBlockChainConfirmation.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ public class SignAndPublishDepositTx extends Task<OffererAsBuyerModel> {
|
|||
log.trace("offererSignAndPublishTx succeeded " + transaction);
|
||||
|
||||
model.trade.setDepositTx(transaction);
|
||||
model.trade.setState(Trade.State.DEPOSIT_PUBLISHED);
|
||||
model.trade.setProcessState(Trade.ProcessState.DEPOSIT_PUBLISHED);
|
||||
|
||||
complete();
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
|
|||
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.RequestTakerDepositPaymentMessage;
|
||||
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.tasks.SetupListenerForBlockChainConfirmation;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.SetupListenerForBlockChainConfirmation;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerAsSellerModel;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.BroadcastTakeOfferFeeTx;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.CreateAndSignContract;
|
||||
|
@ -43,11 +43,6 @@ import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCommitDepositTx;
|
|||
import io.bitsquare.trade.protocol.trade.taker.tasks.TakerCreatesAndSignsDepositTx;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.VerifyOfferFeePayment;
|
||||
import io.bitsquare.trade.protocol.trade.taker.tasks.VerifyOffererAccount;
|
||||
import io.bitsquare.util.Utilities;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -56,11 +51,9 @@ import static io.bitsquare.util.Validator.nonEmptyStringOf;
|
|||
|
||||
public class TakerAsSellerProtocol {
|
||||
private static final Logger log = LoggerFactory.getLogger(TakerAsSellerProtocol.class);
|
||||
private static final int TIMEOUT_DELAY = 10000;
|
||||
|
||||
private final TakerAsSellerModel model;
|
||||
private final MessageHandler messageHandler;
|
||||
private AnimationTimer timeoutTimer;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -72,8 +65,6 @@ public class TakerAsSellerProtocol {
|
|||
this.model = model;
|
||||
messageHandler = this::handleMessage;
|
||||
model.messageService.addMessageHandler(messageHandler);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -105,10 +96,8 @@ public class TakerAsSellerProtocol {
|
|||
() -> {
|
||||
log.debug("taskRunner at takeAvailableOffer completed");
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
|
||||
taskRunner.addTasks(
|
||||
CreateTakeOfferFeeTx.class,
|
||||
BroadcastTakeOfferFeeTx.class,
|
||||
|
@ -129,10 +118,8 @@ public class TakerAsSellerProtocol {
|
|||
() -> {
|
||||
log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed");
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessRequestTakerDepositPaymentMessage.class,
|
||||
VerifyOffererAccount.class,
|
||||
|
@ -150,10 +137,8 @@ public class TakerAsSellerProtocol {
|
|||
() -> {
|
||||
log.debug("taskRunner at handleDepositTxPublishedMessage completed");
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
|
||||
taskRunner.addTasks(
|
||||
ProcessDepositTxPublishedMessage.class,
|
||||
TakerCommitDepositTx.class,
|
||||
|
@ -169,23 +154,21 @@ public class TakerAsSellerProtocol {
|
|||
() -> {
|
||||
log.debug("taskRunner at handleFiatTransferStartedMessage completed");
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
|
||||
taskRunner.addTasks(ProcessFiatTransferStartedMessage.class);
|
||||
taskRunner.run();
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Called from UI
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||
public void onFiatPaymentReceived() {
|
||||
model.trade.setState(Trade.State.FIAT_PAYMENT_RECEIVED);
|
||||
|
||||
model.trade.setProcessState(Trade.ProcessState.FIAT_PAYMENT_RECEIVED);
|
||||
|
||||
TaskRunner<TakerAsSellerModel> taskRunner = new TaskRunner<>(model,
|
||||
() -> {
|
||||
log.debug("taskRunner at handleFiatReceivedUIEvent completed");
|
||||
|
@ -193,10 +176,8 @@ public class TakerAsSellerProtocol {
|
|||
// we are done!
|
||||
model.onComplete();
|
||||
},
|
||||
(errorMessage) -> {
|
||||
log.error(errorMessage);
|
||||
}
|
||||
);
|
||||
(errorMessage) -> handleTaskRunnerFault(errorMessage));
|
||||
|
||||
taskRunner.addTasks(
|
||||
SignAndPublishPayoutTx.class,
|
||||
VerifyOfferFeePayment.class,
|
||||
|
@ -232,22 +213,8 @@ public class TakerAsSellerProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Timeout
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void startTimeout(Function<AnimationTimer, Void> callback) {
|
||||
stopTimeout();
|
||||
timeoutTimer = Utilities.setTimeout(TIMEOUT_DELAY, callback);
|
||||
timeoutTimer.start();
|
||||
}
|
||||
|
||||
private void stopTimeout() {
|
||||
if (timeoutTimer != null) {
|
||||
timeoutTimer.stop();
|
||||
timeoutTimer = null;
|
||||
}
|
||||
private void handleTaskRunnerFault(String errorMessage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
package io.bitsquare.trade.protocol.trade.taker.models;
|
||||
|
||||
import io.bitsquare.fiat.FiatAccount;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
|
@ -32,10 +31,6 @@ import java.util.List;
|
|||
public class Offerer implements Serializable {
|
||||
private static final long serialVersionUID = 1582902150121576205L;
|
||||
|
||||
// Those fields are set at constructor but not declared as final because constructor is not called in case model gets created from a persisted model
|
||||
// Declared transient as they will be provided in any case at construction time
|
||||
public Peer peer;
|
||||
|
||||
// written by tasks
|
||||
public byte[] tradeWalletPubKey;
|
||||
public Coin payoutAmount;
|
||||
|
|
|
@ -22,7 +22,6 @@ import io.bitsquare.btc.WalletService;
|
|||
import io.bitsquare.crypto.SignatureService;
|
||||
import io.bitsquare.p2p.MailboxService;
|
||||
import io.bitsquare.p2p.MessageService;
|
||||
import io.bitsquare.p2p.Peer;
|
||||
import io.bitsquare.persistence.Persistence;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.SharedTradeModel;
|
||||
|
@ -48,7 +47,6 @@ public class TakerAsSellerModel extends SharedTradeModel implements Serializable
|
|||
private Transaction payoutTx;
|
||||
|
||||
public TakerAsSellerModel(Trade trade,
|
||||
Peer offererPeer,
|
||||
MessageService messageService,
|
||||
MailboxService mailboxService,
|
||||
WalletService walletService,
|
||||
|
@ -82,8 +80,6 @@ public class TakerAsSellerModel extends SharedTradeModel implements Serializable
|
|||
offerer = new Offerer();
|
||||
}
|
||||
|
||||
offerer.peer = offererPeer;
|
||||
|
||||
taker.registrationPubKey = walletService.getRegistrationAddressEntry().getPubKey();
|
||||
taker.registrationKeyPair = walletService.getRegistrationAddressEntry().getKeyPair();
|
||||
taker.addressEntry = walletService.getAddressEntry(id);
|
||||
|
|
|
@ -47,14 +47,14 @@ public class BroadcastTakeOfferFeeTx extends Task<TakerAsSellerModel> {
|
|||
public void onSuccess(Transaction transaction) {
|
||||
log.debug("Take offer fee published successfully. Transaction ID = " + transaction.getHashAsString());
|
||||
|
||||
model.trade.setState(Trade.State.TAKE_OFFER_FEE_PUBLISHED);
|
||||
model.trade.setProcessState(Trade.ProcessState.TAKE_OFFER_FEE_PUBLISHED);
|
||||
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Throwable t) {
|
||||
model.trade.setState(Trade.State.TAKE_OFFER_FEE_PUBLISH_FAILED);
|
||||
model.trade.setProcessState(Trade.ProcessState.TAKE_OFFER_FEE_PUBLISH_FAILED);
|
||||
|
||||
failed(t);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public class BroadcastTakeOfferFeeTx extends Task<TakerAsSellerModel> {
|
|||
appendToErrorMessage("Take offer fee payment failed. Maybe your network connection was lost. Please try again.");
|
||||
appendToErrorMessage(e.getMessage());
|
||||
|
||||
model.trade.setState(Trade.State.FAULT);
|
||||
model.trade.setProcessState(Trade.ProcessState.FAULT);
|
||||
|
||||
failed(e);
|
||||
}
|
||||
|
|
|
@ -40,13 +40,13 @@ public class CreateTakeOfferFeeTx extends Task<TakerAsSellerModel> {
|
|||
Transaction createTakeOfferFeeTx = model.tradeWalletService.createTakeOfferFeeTx(model.taker.addressEntry);
|
||||
|
||||
model.setTakeOfferFeeTx(createTakeOfferFeeTx);
|
||||
model.trade.setState(Trade.State.TAKE_OFFER_FEE_TX_CREATED);
|
||||
model.trade.setProcessState(Trade.ProcessState.TAKE_OFFER_FEE_TX_CREATED);
|
||||
|
||||
complete();
|
||||
} catch (Exception e) {
|
||||
appendToErrorMessage(e.getMessage());
|
||||
|
||||
model.trade.setState(Trade.State.FAULT);
|
||||
model.trade.setProcessState(Trade.ProcessState.FAULT);
|
||||
|
||||
failed(e);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public class ProcessDepositTxPublishedMessage extends Task<TakerAsSellerModel> {
|
|||
|
||||
DepositTxPublishedMessage message = (DepositTxPublishedMessage) model.getTradeMessage();
|
||||
model.trade.setDepositTx(checkNotNull(message.depositTx));
|
||||
model.trade.setState(Trade.State.DEPOSIT_PUBLISHED);
|
||||
model.trade.setProcessState(Trade.ProcessState.DEPOSIT_PUBLISHED);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
|
|
|
@ -46,11 +46,11 @@ public class ProcessFiatTransferStartedMessage extends Task<TakerAsSellerModel>
|
|||
model.offerer.payoutAmount = positiveCoinOf(nonZeroCoinOf(message.offererPayoutAmount));
|
||||
model.taker.payoutAmount = positiveCoinOf(nonZeroCoinOf(message.takerPayoutAmount));
|
||||
model.offerer.payoutAddressString = nonEmptyStringOf(message.offererPayoutAddress);
|
||||
model.trade.setState(Trade.State.FIAT_PAYMENT_STARTED);
|
||||
model.trade.setProcessState(Trade.ProcessState.FIAT_PAYMENT_STARTED);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
model.trade.setState(Trade.State.FAULT);
|
||||
model.trade.setProcessState(Trade.ProcessState.FAULT);
|
||||
failed(t);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class SendPayoutTxToOfferer extends Task<TakerAsSellerModel> {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(model.id, model.getPayoutTx());
|
||||
model.messageService.sendMessage(model.offerer.peer,
|
||||
model.messageService.sendMessage(model.trade.getTradingPeer(),
|
||||
tradeMessage,
|
||||
model.offerer.p2pSigPublicKey,
|
||||
model.offerer.p2pEncryptPubKey,
|
||||
|
|
|
@ -47,7 +47,7 @@ public class SendRequestDepositTxInputsMessage extends Task<TakerAsSellerModel>
|
|||
model.taker.tradeWalletPubKey
|
||||
);
|
||||
|
||||
model.messageService.sendMessage(model.offerer.peer, msg, new SendMessageListener() {
|
||||
model.messageService.sendMessage(model.trade.getTradingPeer(), msg, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
log.trace("Sending TakeOfferFeePayedMessage succeeded.");
|
||||
|
@ -67,7 +67,7 @@ public class SendRequestDepositTxInputsMessage extends Task<TakerAsSellerModel>
|
|||
"connection. " +
|
||||
"We persisted the state of the trade, please try again later or cancel that trade.");
|
||||
|
||||
model.trade.setState(Trade.State.MESSAGE_SENDING_FAILED);
|
||||
model.trade.setProcessState(Trade.ProcessState.MESSAGE_SENDING_FAILED);
|
||||
|
||||
failed();
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class SendSignedTakerDepositTx extends Task<TakerAsSellerModel> {
|
|||
model.taker.outputs
|
||||
);
|
||||
|
||||
model.messageService.sendMessage(model.offerer.peer, tradeMessage, new SendMessageListener() {
|
||||
model.messageService.sendMessage(model.trade.getTradingPeer(), tradeMessage, new SendMessageListener() {
|
||||
@Override
|
||||
public void handleResult() {
|
||||
complete();
|
||||
|
|
|
@ -20,7 +20,7 @@ package io.bitsquare.trade.protocol.trade.taker.tasks;
|
|||
import io.bitsquare.common.taskrunner.Task;
|
||||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.trade.offerer.models.OffererAsBuyerModel;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerAsSellerModel;
|
||||
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionConfidence;
|
||||
|
@ -30,38 +30,43 @@ import javafx.application.Platform;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SetupListenerForBlockChainConfirmation extends Task<OffererAsBuyerModel> {
|
||||
public class SetupListenerForBlockChainConfirmation extends Task<TakerAsSellerModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
|
||||
|
||||
private TransactionConfidence.Listener transactionConfidenceListener;
|
||||
private TransactionConfidence transactionConfidence;
|
||||
|
||||
public SetupListenerForBlockChainConfirmation(TaskRunner taskHandler, OffererAsBuyerModel model) {
|
||||
public SetupListenerForBlockChainConfirmation(TaskRunner taskHandler, TakerAsSellerModel model) {
|
||||
super(taskHandler, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRun() {
|
||||
transactionConfidence = model.trade.getDepositTx().getConfidence();
|
||||
transactionConfidenceListener = new TransactionConfidence.Listener() {
|
||||
@Override
|
||||
public void onConfidenceChanged(Transaction tx, ChangeReason reason) {
|
||||
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
|
||||
model.trade.setState(Trade.State.DEPOSIT_CONFIRMED);
|
||||
try {
|
||||
transactionConfidence = model.trade.getDepositTx().getConfidence();
|
||||
transactionConfidenceListener = new TransactionConfidence.Listener() {
|
||||
@Override
|
||||
public void onConfidenceChanged(Transaction tx, ChangeReason reason) {
|
||||
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
|
||||
model.trade.setProcessState(Trade.ProcessState.DEPOSIT_CONFIRMED);
|
||||
|
||||
// transactionConfidence use CopyOnWriteArrayList as listeners, but be safe and delay remove a bit.
|
||||
Platform.runLater(() -> removeEventListener());
|
||||
// transactionConfidence use CopyOnWriteArrayList as listeners, but be safe and delay remove a bit.
|
||||
Platform.runLater(() -> removeEventListener());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
transactionConfidence.addEventListener(transactionConfidenceListener);
|
||||
};
|
||||
transactionConfidence.addEventListener(transactionConfidenceListener);
|
||||
|
||||
complete();
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
log.error(t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void removeEventListener() {
|
||||
if (!transactionConfidence.removeEventListener(transactionConfidenceListener))
|
||||
throw new RuntimeException("Remove transactionConfidenceListener failed at SetupListenerForBlockChainConfirmation.");
|
||||
log.error("Remove transactionConfidenceListener failed at SetupListenerForBlockChainConfirmation.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public class SignAndPublishPayoutTx extends Task<TakerAsSellerModel> {
|
|||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
model.setPayoutTx(transaction);
|
||||
model.trade.setState(Trade.State.PAYOUT_PUBLISHED);
|
||||
model.trade.setProcessState(Trade.ProcessState.PAYOUT_PUBLISHED);
|
||||
|
||||
complete();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import io.bitsquare.common.taskrunner.Task;
|
|||
import io.bitsquare.common.taskrunner.TaskRunner;
|
||||
import io.bitsquare.trade.protocol.trade.taker.models.TakerAsSellerModel;
|
||||
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -34,8 +36,10 @@ public class TakerCommitDepositTx extends Task<TakerAsSellerModel> {
|
|||
@Override
|
||||
protected void doRun() {
|
||||
try {
|
||||
model.tradeWalletService.takerCommitsDepositTx(model.trade.getDepositTx());
|
||||
|
||||
// We need to put the tx into our wallet to have a fully setup tx
|
||||
Transaction localDepositTx = model.tradeWalletService.takerCommitsDepositTx(model.trade.getDepositTx());
|
||||
model.trade.setDepositTx(localDepositTx);
|
||||
|
||||
complete();
|
||||
} catch (Throwable t) {
|
||||
failed(t);
|
||||
|
|
|
@ -59,9 +59,9 @@ public class TakerCreatesAndSignsDepositTx extends Task<TakerAsSellerModel> {
|
|||
|
||||
complete();
|
||||
} catch (Exception e) {
|
||||
Trade.State state = Trade.State.FAULT;
|
||||
state.setErrorMessage(errorMessage);
|
||||
model.trade.setState(state);
|
||||
Trade.ProcessState processState = Trade.ProcessState.FAULT;
|
||||
processState.setErrorMessage(errorMessage);
|
||||
model.trade.setProcessState(processState);
|
||||
|
||||
failed(e);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue