From 95e23dc8a98b380b80eba934747f94dcaa4d8646 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Mon, 13 Apr 2015 20:38:29 +0200 Subject: [PATCH] Separate open offer --- .../java/io/bitsquare/fiat/FiatAccount.java | 2 +- .../p2p/tomp2p/BootstrappedPeerBuilder.java | 2 + .../p2p/tomp2p/TomP2PMailboxService.java | 2 +- .../bitsquare/trade/BuyerAsOffererTrade.java | 4 +- .../io/bitsquare/trade/BuyerAsTakerTrade.java | 4 +- .../java/io/bitsquare/trade/Contract.java | 2 +- .../java/io/bitsquare/trade/OffererTrade.java | 19 +- .../bitsquare/trade/SellerAsOffererTrade.java | 4 +- .../bitsquare/trade/SellerAsTakerTrade.java | 4 +- .../java/io/bitsquare/trade/TakerTrade.java | 12 +- .../java/io/bitsquare/trade/Tradable.java | 32 ++ .../{TradeList.java => TradableList.java} | 23 +- .../main/java/io/bitsquare/trade/Trade.java | 27 +- .../java/io/bitsquare/trade/TradeManager.java | 243 +++++++-------- .../java/io/bitsquare/trade/TradeModule.java | 7 +- .../trade/closed/ClosedTradableManager.java | 62 ++++ .../io/bitsquare/{ => trade}/offer/Offer.java | 18 +- .../{ => trade}/offer/OfferBookService.java | 2 +- .../{ => trade}/offer/OfferModule.java | 16 +- .../io/bitsquare/trade/offer/OpenOffer.java | 124 ++++++++ .../trade/offer/OpenOfferManager.java | 287 ++++++++++++++++++ .../offer/tomp2p/TomP2POfferBookService.java | 6 +- .../offer/tomp2p/TomP2POfferModule.java | 6 +- ...Model.java => OfferAvailabilityModel.java} | 10 +- ...ol.java => OfferAvailabilityProtocol.java} | 30 +- ...age.java => OfferAvailabilityRequest.java} | 15 +- ...ge.java => OfferAvailabilityResponse.java} | 8 +- .../availability/tasks/GetPeerAddress.java | 10 +- ... => ProcessOfferAvailabilityResponse.java} | 20 +- ...java => SendOfferAvailabilityRequest.java} | 17 +- .../protocol/placeoffer/PlaceOfferModel.java | 4 +- .../trade/BuyerAsOffererProtocol.java | 88 ++---- .../trade/protocol/trade/OffererProtocol.java | 4 + .../trade/protocol/trade/ProcessModel.java | 2 +- .../trade/SellerAsOffererProtocol.java | 96 ++---- .../messages/RequestPayDepositMessage.java | 3 + .../buyer/SendRequestPayDepositMessage.java | 3 + .../tasks/buyer/SignAndPublishDepositTx.java | 11 +- .../trade/states/OffererTradeState.java | 13 +- .../io/bitsquare/trade/states/StateUtil.java | 2 +- .../trade/states/TakerTradeState.java | 6 - .../io/bitsquare/trade/states/TradeState.java | 3 - .../placeoffer/PlaceOfferProtocolTest.java | 2 +- .../io/bitsquare/app/BitsquareAppModule.java | 4 +- .../io/bitsquare/gui/main/MainViewModel.java | 6 +- .../bitsquare/gui/main/debug/DebugView.java | 12 +- .../gui/main/funds/reserved/ReservedView.java | 9 +- .../main/funds/withdrawal/WithdrawalView.java | 9 +- .../bitsquare/gui/main/offer/OfferView.java | 2 +- .../createoffer/CreateOfferDataModel.java | 15 +- .../offer/createoffer/CreateOfferView.java | 4 +- .../createoffer/CreateOfferViewModel.java | 6 +- .../gui/main/offer/offerbook/OfferBook.java | 6 +- .../offer/offerbook/OfferBookDataModel.java | 14 +- .../offer/offerbook/OfferBookListItem.java | 2 +- .../main/offer/offerbook/OfferBookView.java | 2 +- .../offer/offerbook/OfferBookViewModel.java | 2 +- .../offer/takeoffer/TakeOfferDataModel.java | 2 +- .../main/offer/takeoffer/TakeOfferView.java | 2 +- .../offer/takeoffer/TakeOfferViewModel.java | 10 +- .../closedtrades/ClosedTradesDataModel.java | 27 +- .../closedtrades/ClosedTradesListItem.java | 12 +- .../closedtrades/ClosedTradesViewModel.java | 59 ++-- .../openoffer/OpenOfferListItem.java | 15 +- .../openoffer/OpenOffersDataModel.java | 29 +- .../portfolio/openoffer/OpenOffersView.java | 8 +- .../openoffer/OpenOffersViewModel.java | 6 +- .../pendingtrades/PendingTradesDataModel.java | 2 +- .../io/bitsquare/gui/util/BSFormatter.java | 2 +- 69 files changed, 976 insertions(+), 546 deletions(-) create mode 100644 core/src/main/java/io/bitsquare/trade/Tradable.java rename core/src/main/java/io/bitsquare/trade/{TradeList.java => TradableList.java} (80%) create mode 100644 core/src/main/java/io/bitsquare/trade/closed/ClosedTradableManager.java rename core/src/main/java/io/bitsquare/{ => trade}/offer/Offer.java (96%) rename core/src/main/java/io/bitsquare/{ => trade}/offer/OfferBookService.java (97%) rename core/src/main/java/io/bitsquare/{ => trade}/offer/OfferModule.java (67%) create mode 100644 core/src/main/java/io/bitsquare/trade/offer/OpenOffer.java create mode 100644 core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java rename core/src/main/java/io/bitsquare/{ => trade}/offer/tomp2p/TomP2POfferBookService.java (99%) rename core/src/main/java/io/bitsquare/{ => trade}/offer/tomp2p/TomP2POfferModule.java (88%) rename core/src/main/java/io/bitsquare/trade/protocol/availability/{CheckOfferAvailabilityModel.java => OfferAvailabilityModel.java} (85%) rename core/src/main/java/io/bitsquare/trade/protocol/availability/{CheckOfferAvailabilityProtocol.java => OfferAvailabilityProtocol.java} (80%) rename core/src/main/java/io/bitsquare/trade/protocol/availability/messages/{RequestIsOfferAvailableMessage.java => OfferAvailabilityRequest.java} (72%) rename core/src/main/java/io/bitsquare/trade/protocol/availability/messages/{ReportOfferAvailabilityMessage.java => OfferAvailabilityResponse.java} (79%) rename core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/{ProcessReportOfferAvailabilityMessage.java => ProcessOfferAvailabilityResponse.java} (63%) rename core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/{SendRequestIsOfferAvailableMessage.java => SendOfferAvailabilityRequest.java} (72%) diff --git a/core/src/main/java/io/bitsquare/fiat/FiatAccount.java b/core/src/main/java/io/bitsquare/fiat/FiatAccount.java index d5493d1c38..81f488f244 100644 --- a/core/src/main/java/io/bitsquare/fiat/FiatAccount.java +++ b/core/src/main/java/io/bitsquare/fiat/FiatAccount.java @@ -37,7 +37,7 @@ public class FiatAccount implements Serializable { public static final long WEEK_IN_BLOCKS = DAY_IN_BLOCKS * 7; public enum Type { - IRC("", "", 0), + IRC("", "", 2), SEPA("IBAN", "BIC", WEEK_IN_BLOCKS), WIRE("primary ID", "secondary ID", WEEK_IN_BLOCKS), INTERNATIONAL("primary ID", "secondary ID", 2 * WEEK_IN_BLOCKS), diff --git a/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java b/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java index ba5e56ee31..1f573976b0 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/BootstrappedPeerBuilder.java @@ -252,11 +252,13 @@ public class BootstrappedPeerBuilder { } private void bootstrap() { + log.trace("start bootstrap"); FutureBootstrap futureBootstrap = peer.bootstrap().peerAddress(getBootstrapAddress()).start(); futureBootstrap.addListener(new BaseFutureListener() { @Override public void operationComplete(BaseFuture future) throws Exception { if (futureBootstrap.isSuccess()) { + log.trace("bootstrap complete"); settableFuture.set(peerDHT); } else { diff --git a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PMailboxService.java b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PMailboxService.java index 9f7b5641a7..026d7679ea 100644 --- a/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PMailboxService.java +++ b/core/src/main/java/io/bitsquare/p2p/tomp2p/TomP2PMailboxService.java @@ -22,9 +22,9 @@ import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.crypto.KeyRing; import io.bitsquare.crypto.PubKeyRing; import io.bitsquare.crypto.SealedAndSignedMessage; -import io.bitsquare.offer.OfferBookService; import io.bitsquare.p2p.MailboxMessagesResultHandler; import io.bitsquare.p2p.MailboxService; +import io.bitsquare.trade.offer.OfferBookService; import java.io.IOException; diff --git a/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java b/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java index 26b737e0fb..d23641fcbf 100644 --- a/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java +++ b/core/src/main/java/io/bitsquare/trade/BuyerAsOffererTrade.java @@ -17,8 +17,8 @@ package io.bitsquare.trade; -import io.bitsquare.offer.Offer; import io.bitsquare.storage.Storage; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.protocol.trade.BuyerAsOffererProtocol; import io.bitsquare.trade.protocol.trade.BuyerProtocol; @@ -42,7 +42,7 @@ public class BuyerAsOffererTrade extends OffererTrade implements BuyerTrade, Ser // Constructor, initialization /////////////////////////////////////////////////////////////////////////////////////////// - public BuyerAsOffererTrade(Offer offer, Storage storage) { + public BuyerAsOffererTrade(Offer offer, Storage storage) { super(offer, storage); log.trace("Created by constructor"); } diff --git a/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java b/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java index 549bc9fe52..22a0997d0b 100644 --- a/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/io/bitsquare/trade/BuyerAsTakerTrade.java @@ -17,9 +17,9 @@ package io.bitsquare.trade; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.Peer; import io.bitsquare.storage.Storage; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.protocol.trade.BuyerAsTakerProtocol; import io.bitsquare.trade.protocol.trade.BuyerProtocol; @@ -43,7 +43,7 @@ public class BuyerAsTakerTrade extends TakerTrade implements BuyerTrade, Seriali // Constructor, initialization /////////////////////////////////////////////////////////////////////////////////////////// - public BuyerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { + public BuyerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { super(offer, tradeAmount, tradingPeer, storage); log.trace("Created by constructor"); } diff --git a/core/src/main/java/io/bitsquare/trade/Contract.java b/core/src/main/java/io/bitsquare/trade/Contract.java index 096beb8ab1..b57f68bc2d 100644 --- a/core/src/main/java/io/bitsquare/trade/Contract.java +++ b/core/src/main/java/io/bitsquare/trade/Contract.java @@ -19,7 +19,7 @@ package io.bitsquare.trade; import io.bitsquare.crypto.PubKeyRing; import io.bitsquare.fiat.FiatAccount; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import org.bitcoinj.core.Coin; diff --git a/core/src/main/java/io/bitsquare/trade/OffererTrade.java b/core/src/main/java/io/bitsquare/trade/OffererTrade.java index 526ea54120..c4d32fb7f5 100644 --- a/core/src/main/java/io/bitsquare/trade/OffererTrade.java +++ b/core/src/main/java/io/bitsquare/trade/OffererTrade.java @@ -17,8 +17,11 @@ package io.bitsquare.trade; -import io.bitsquare.offer.Offer; +import io.bitsquare.p2p.Peer; import io.bitsquare.storage.Storage; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.protocol.trade.OffererProtocol; +import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.states.OffererTradeState; import io.bitsquare.trade.states.TradeState; @@ -33,7 +36,7 @@ public abstract class OffererTrade extends Trade implements Serializable { transient private static final Logger log = LoggerFactory.getLogger(BuyerAsOffererTrade.class); - public OffererTrade(Offer offer, Storage storage) { + public OffererTrade(Offer offer, Storage storage) { super(offer, storage); log.trace("Created by constructor"); } @@ -41,10 +44,14 @@ public abstract class OffererTrade extends Trade implements Serializable { @Override protected void initStates() { processState = OffererTradeState.ProcessState.UNDEFINED; - lifeCycleState = OffererTradeState.LifeCycleState.OFFER_OPEN; + lifeCycleState = Trade.LifeCycleState.PREPARATION; initStateProperties(); } + public void handleTakeOfferRequest(TradeMessage message, Peer taker) { + ((OffererProtocol) tradeProtocol).handleTakeOfferRequest(message, taker); + } + /////////////////////////////////////////////////////////////////////////////////////////// // Setter for Mutable objects @@ -57,16 +64,16 @@ public abstract class OffererTrade extends Trade implements Serializable { switch ((OffererTradeState.ProcessState) processState) { case EXCEPTION: disposeProtocol(); - setLifeCycleState(OffererTradeState.LifeCycleState.FAILED); + setLifeCycleState(Trade.LifeCycleState.FAILED); break; } } @Override - public void setLifeCycleState(TradeState.LifeCycleState lifeCycleState) { + public void setLifeCycleState(Trade.LifeCycleState lifeCycleState) { super.setLifeCycleState(lifeCycleState); - switch ((OffererTradeState.LifeCycleState) lifeCycleState) { + switch (lifeCycleState) { case FAILED: disposeProtocol(); break; diff --git a/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java b/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java index d1dbd9681a..c5d2b385b4 100644 --- a/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java +++ b/core/src/main/java/io/bitsquare/trade/SellerAsOffererTrade.java @@ -17,8 +17,8 @@ package io.bitsquare.trade; -import io.bitsquare.offer.Offer; import io.bitsquare.storage.Storage; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.protocol.trade.SellerAsOffererProtocol; import io.bitsquare.trade.protocol.trade.SellerProtocol; @@ -40,7 +40,7 @@ public class SellerAsOffererTrade extends OffererTrade implements SellerTrade, S // Constructor, initialization /////////////////////////////////////////////////////////////////////////////////////////// - public SellerAsOffererTrade(Offer offer, Storage storage) { + public SellerAsOffererTrade(Offer offer, Storage storage) { super(offer, storage); log.trace("Created by constructor"); } diff --git a/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java b/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java index d43459a1e5..9375c23975 100644 --- a/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/io/bitsquare/trade/SellerAsTakerTrade.java @@ -17,9 +17,9 @@ package io.bitsquare.trade; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.Peer; import io.bitsquare.storage.Storage; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.protocol.trade.SellerAsTakerProtocol; import io.bitsquare.trade.protocol.trade.SellerProtocol; import io.bitsquare.trade.states.TakerTradeState; @@ -43,7 +43,7 @@ public class SellerAsTakerTrade extends TakerTrade implements SellerTrade, Seria // Constructor, initialization /////////////////////////////////////////////////////////////////////////////////////////// - public SellerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { + public SellerAsTakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { super(offer, tradeAmount, tradingPeer, storage); log.trace("Created by constructor"); } diff --git a/core/src/main/java/io/bitsquare/trade/TakerTrade.java b/core/src/main/java/io/bitsquare/trade/TakerTrade.java index bc15d1a84b..44f5ce7ff2 100644 --- a/core/src/main/java/io/bitsquare/trade/TakerTrade.java +++ b/core/src/main/java/io/bitsquare/trade/TakerTrade.java @@ -17,9 +17,9 @@ package io.bitsquare.trade; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.Peer; import io.bitsquare.storage.Storage; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.protocol.trade.TakerProtocol; import io.bitsquare.trade.states.TakerTradeState; import io.bitsquare.trade.states.TradeState; @@ -37,7 +37,7 @@ public abstract class TakerTrade extends Trade implements Serializable { transient private static final Logger log = LoggerFactory.getLogger(BuyerAsTakerTrade.class); - public TakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { + public TakerTrade(Offer offer, Coin tradeAmount, Peer tradingPeer, Storage storage) { super(offer, tradeAmount, tradingPeer, storage); log.trace("Created by constructor"); } @@ -45,7 +45,7 @@ public abstract class TakerTrade extends Trade implements Serializable { @Override protected void initStates() { processState = TakerTradeState.ProcessState.UNDEFINED; - lifeCycleState = TakerTradeState.LifeCycleState.PENDING; + lifeCycleState = Trade.LifeCycleState.PENDING; initStateProperties(); } @@ -66,16 +66,16 @@ public abstract class TakerTrade extends Trade implements Serializable { switch ((TakerTradeState.ProcessState) processState) { case EXCEPTION: disposeProtocol(); - setLifeCycleState(TakerTradeState.LifeCycleState.FAILED); + setLifeCycleState(Trade.LifeCycleState.FAILED); break; } } @Override - public void setLifeCycleState(TradeState.LifeCycleState lifeCycleState) { + public void setLifeCycleState(Trade.LifeCycleState lifeCycleState) { super.setLifeCycleState(lifeCycleState); - switch ((TakerTradeState.LifeCycleState) lifeCycleState) { + switch (lifeCycleState) { case FAILED: disposeProtocol(); break; diff --git a/core/src/main/java/io/bitsquare/trade/Tradable.java b/core/src/main/java/io/bitsquare/trade/Tradable.java new file mode 100644 index 0000000000..1309b935ea --- /dev/null +++ b/core/src/main/java/io/bitsquare/trade/Tradable.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ + +package io.bitsquare.trade; + +import io.bitsquare.trade.offer.Offer; + +import java.io.Serializable; + +import java.util.Date; + +public interface Tradable extends Serializable { + Offer getOffer(); + + Date getDate(); + + String getId(); +} diff --git a/core/src/main/java/io/bitsquare/trade/TradeList.java b/core/src/main/java/io/bitsquare/trade/TradableList.java similarity index 80% rename from core/src/main/java/io/bitsquare/trade/TradeList.java rename to core/src/main/java/io/bitsquare/trade/TradableList.java index b2a3c50a84..4891a9bae7 100644 --- a/core/src/main/java/io/bitsquare/trade/TradeList.java +++ b/core/src/main/java/io/bitsquare/trade/TradableList.java @@ -31,13 +31,13 @@ import javafx.collections.ObservableList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class TradeList extends ArrayList implements Serializable { +public class TradableList extends ArrayList implements Serializable { // That object is saved to disc. We need to take care of changes to not break deserialization. private static final long serialVersionUID = 1L; - transient private static final Logger log = LoggerFactory.getLogger(TradeList.class); + transient private static final Logger log = LoggerFactory.getLogger(TradableList.class); - transient final private Storage storage; + transient final private Storage> storage; // Use getObservableList() also class locally, to be sure that object exists in case we use the object as deserialized form transient private ObservableList observableList; @@ -47,11 +47,12 @@ public class TradeList extends ArrayList implements Serializable { // Constructor /////////////////////////////////////////////////////////////////////////////////////////// - public TradeList(Storage storage, String fileName) { + public TradableList(Storage> storage, String fileName) { log.trace("Created by constructor"); + this.storage = storage; - TradeList persisted = storage.initAndGetPersisted(this, fileName); + TradableList persisted = storage.initAndGetPersisted(this, fileName); if (persisted != null) { this.addAll(persisted); } @@ -64,17 +65,17 @@ public class TradeList extends ArrayList implements Serializable { } @Override - public boolean add(T trade) { - boolean result = super.add(trade); - getObservableList().add(trade); + public boolean add(T tradable) { + boolean result = super.add(tradable); + getObservableList().add(tradable); storage.queueUpForSave(); return result; } @Override - public boolean remove(Object trade) { - boolean result = super.remove(trade); - getObservableList().remove(trade); + public boolean remove(Object tradable) { + boolean result = super.remove(tradable); + getObservableList().remove(tradable); storage.queueUpForSave(); return result; } diff --git a/core/src/main/java/io/bitsquare/trade/Trade.java b/core/src/main/java/io/bitsquare/trade/Trade.java index f49d782f88..e11f2f1653 100644 --- a/core/src/main/java/io/bitsquare/trade/Trade.java +++ b/core/src/main/java/io/bitsquare/trade/Trade.java @@ -25,11 +25,11 @@ import io.bitsquare.common.taskrunner.Model; import io.bitsquare.crypto.CryptoService; import io.bitsquare.crypto.KeyRing; import io.bitsquare.crypto.MessageWithPubKey; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.AddressService; 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.protocol.trade.ProcessModel; import io.bitsquare.trade.protocol.trade.TradeProtocol; import io.bitsquare.trade.states.TradeState; @@ -66,12 +66,19 @@ import org.slf4j.LoggerFactory; * Holds all data which are relevant to the trade, but not those which are only needed in the trade process as shared data between tasks. Those data are * stored in the task model. */ -abstract public class Trade implements Model, Serializable { +abstract public class Trade implements Tradable, Model, Serializable { // That object is saved to disc. We need to take care of changes to not break deserialization. private static final long serialVersionUID = 1L; private transient static final Logger log = LoggerFactory.getLogger(Trade.class); + public enum LifeCycleState { + PREPARATION, + PENDING, + COMPLETED, + FAILED + } + // Mutable private Coin tradeAmount; private Peer tradingPeer; @@ -85,9 +92,9 @@ abstract public class Trade implements Model, Serializable { // Transient/Immutable private transient ObjectProperty processStateProperty; - private transient ObjectProperty lifeCycleStateProperty; + private transient ObjectProperty lifeCycleStateProperty; // Trades are saved in the TradeList - transient private Storage storage; + transient private Storage storage; transient protected TradeProtocol tradeProtocol; // Immutable @@ -99,7 +106,7 @@ abstract public class Trade implements Model, Serializable { private MessageWithPubKey messageWithPubKey; private Date takeOfferDate; protected TradeState.ProcessState processState; - protected TradeState.LifeCycleState lifeCycleState; + protected Trade.LifeCycleState lifeCycleState; private Transaction depositTx; private Contract contract; private String contractAsJson; @@ -117,7 +124,7 @@ abstract public class Trade implements Model, Serializable { // Constructor, initialization /////////////////////////////////////////////////////////////////////////////////////////// - protected Trade(Offer offer, Storage storage) { + protected Trade(Offer offer, Storage storage) { log.trace("Created by constructor"); this.offer = offer; this.storage = storage; @@ -135,7 +142,7 @@ abstract public class Trade implements Model, Serializable { // taker protected Trade(Offer offer, Coin tradeAmount, Peer tradingPeer, - Storage storage) { + Storage storage) { this(offer, storage); this.tradeAmount = tradeAmount; @@ -227,7 +234,7 @@ abstract public class Trade implements Model, Serializable { this.messageWithPubKey = messageWithPubKey; } - public void setStorage(Storage storage) { + public void setStorage(Storage storage) { this.storage = storage; } @@ -237,7 +244,7 @@ abstract public class Trade implements Model, Serializable { storage.queueUpForSave(); } - public void setLifeCycleState(TradeState.LifeCycleState lifeCycleState) { + public void setLifeCycleState(Trade.LifeCycleState lifeCycleState) { this.lifeCycleState = lifeCycleState; lifeCycleStateProperty.set(lifeCycleState); storage.queueUpForSave(); @@ -302,7 +309,7 @@ abstract public class Trade implements Model, Serializable { return processStateProperty; } - public ReadOnlyObjectProperty lifeCycleStateProperty() { + public ReadOnlyObjectProperty lifeCycleStateProperty() { return lifeCycleStateProperty; } diff --git a/core/src/main/java/io/bitsquare/trade/TradeManager.java b/core/src/main/java/io/bitsquare/trade/TradeManager.java index 961d67f4ab..8ee8b0955d 100644 --- a/core/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/core/src/main/java/io/bitsquare/trade/TradeManager.java @@ -22,39 +22,37 @@ import io.bitsquare.btc.AddressEntry; import io.bitsquare.btc.BlockChainService; import io.bitsquare.btc.TradeWalletService; import io.bitsquare.btc.WalletService; -import io.bitsquare.common.handlers.ErrorMessageHandler; import io.bitsquare.common.handlers.FaultHandler; import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.crypto.CryptoService; import io.bitsquare.crypto.KeyRing; import io.bitsquare.crypto.MessageWithPubKey; import io.bitsquare.crypto.SealedAndSignedMessage; -import io.bitsquare.fiat.FiatAccount; -import io.bitsquare.offer.Offer; -import io.bitsquare.offer.OfferBookService; import io.bitsquare.p2p.AddressService; +import io.bitsquare.p2p.DecryptedMessageHandler; import io.bitsquare.p2p.MailboxMessage; import io.bitsquare.p2p.MailboxService; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.MessageService; +import io.bitsquare.p2p.Peer; import io.bitsquare.storage.Storage; +import io.bitsquare.trade.closed.ClosedTradableManager; import io.bitsquare.trade.handlers.TakeOfferResultHandler; -import io.bitsquare.trade.handlers.TransactionResultHandler; -import io.bitsquare.trade.protocol.availability.CheckOfferAvailabilityModel; -import io.bitsquare.trade.protocol.availability.CheckOfferAvailabilityProtocol; -import io.bitsquare.trade.protocol.placeoffer.PlaceOfferModel; -import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.offer.OpenOffer; +import io.bitsquare.trade.offer.OpenOfferManager; +import io.bitsquare.trade.protocol.availability.OfferAvailabilityModel; +import io.bitsquare.trade.protocol.availability.OfferAvailabilityProtocol; +import io.bitsquare.trade.protocol.trade.messages.RequestDepositTxInputsMessage; +import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage; import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.states.OffererTradeState; -import io.bitsquare.trade.states.TakerTradeState; -import io.bitsquare.user.AccountSettings; import io.bitsquare.user.User; import org.bitcoinj.core.AddressFormatException; import org.bitcoinj.core.Coin; import org.bitcoinj.core.InsufficientMoneyException; import org.bitcoinj.core.Transaction; -import org.bitcoinj.utils.Fiat; import com.google.common.util.concurrent.FutureCallback; @@ -77,12 +75,13 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static io.bitsquare.util.Validator.nonEmptyStringOf; + public class TradeManager { private static final Logger log = LoggerFactory.getLogger(TradeManager.class); private final User user; - private KeyRing keyRing; - private final AccountSettings accountSettings; + private final KeyRing keyRing; private final MessageService messageService; private final MailboxService mailboxService; private final AddressService addressService; @@ -90,17 +89,13 @@ public class TradeManager { private final WalletService walletService; private final TradeWalletService tradeWalletService; private final CryptoService cryptoService; - private final OfferBookService offerBookService; + private OpenOfferManager openOfferManager; + private ClosedTradableManager closedTradableManager; private final ArbitrationRepository arbitrationRepository; - private final Map checkOfferAvailabilityProtocolMap = new HashMap<>(); - private final Storage pendingTradesStorage; - private final Storage openOfferTradesStorage; - private final TradeList openOfferTrades; - private final TradeList pendingTrades; - private final TradeList closedTrades; - - private boolean shutDownRequested; + private final Map checkOfferAvailabilityProtocolMap = new HashMap<>(); + private final Storage> pendingTradesStorage; + private final TradableList pendingTrades; /////////////////////////////////////////////////////////////////////////////////////////// @@ -110,7 +105,6 @@ public class TradeManager { @Inject public TradeManager(User user, KeyRing keyRing, - AccountSettings accountSettings, MessageService messageService, MailboxService mailboxService, AddressService addressService, @@ -118,12 +112,12 @@ public class TradeManager { WalletService walletService, TradeWalletService tradeWalletService, CryptoService cryptoService, - OfferBookService offerBookService, + OpenOfferManager openOfferManager, + ClosedTradableManager closedTradableManager, ArbitrationRepository arbitrationRepository, @Named("storage.dir") File storageDir) { this.user = user; this.keyRing = keyRing; - this.accountSettings = accountSettings; this.messageService = messageService; this.mailboxService = mailboxService; this.addressService = addressService; @@ -131,20 +125,12 @@ public class TradeManager { this.walletService = walletService; this.tradeWalletService = tradeWalletService; this.cryptoService = cryptoService; - this.offerBookService = offerBookService; + this.openOfferManager = openOfferManager; + this.closedTradableManager = closedTradableManager; this.arbitrationRepository = arbitrationRepository; - openOfferTradesStorage = new Storage<>(storageDir); pendingTradesStorage = new Storage<>(storageDir); - - this.openOfferTrades = new TradeList<>(openOfferTradesStorage, "OpenOfferTrades"); - this.pendingTrades = new TradeList<>(pendingTradesStorage, "PendingTrades"); - this.closedTrades = new TradeList<>(new Storage<>(storageDir), "ClosedTrades"); - - - // In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook - Thread shutDownHookThread = new Thread(TradeManager.this::shutDown, "TradeManager.ShutDownHook"); - Runtime.getRuntime().addShutdownHook(shutDownHookThread); + this.pendingTrades = new TradableList<>(pendingTradesStorage, "PendingTrades"); } @@ -156,16 +142,6 @@ public class TradeManager { // OffererAsBuyerProtocol listens for take offer requests, so we need to instantiate it early. public void onAllServicesInitialized() { log.trace("onAllServicesInitialized"); - for (Trade trade : openOfferTrades) { - Offer offer = trade.getOffer(); - // We add own offers to offerbook when we go online again - offerBookService.addOffer(offer, - () -> log.debug("Successful removed open offer from DHT"), - (message, throwable) -> log.error("Remove open offer from DHT failed. " + message)); - setupDepositPublishedListener(trade); - trade.setStorage(openOfferTradesStorage); - initTrade(trade); - } // If there are messages in our mailbox we apply it and remove them from the DHT // We run that before initializing the pending trades to be sure the state is correct @@ -173,10 +149,69 @@ public class TradeManager { (encryptedMailboxMessages) -> { log.trace("mailboxService.getAllMessages success"); setMailboxMessagesToTrades(encryptedMailboxMessages); - //TODO testing - //emptyMailbox(); + emptyMailbox(); initPendingTrades(); }); + + // Handler for incoming initial messages from taker + messageService.addDecryptedMessageHandler(new DecryptedMessageHandler() { + @Override + public void handleMessage(MessageWithPubKey messageWithPubKey, Peer sender) { + // We get an encrypted message but don't do the signature check as we don't know the peer yet. + // A basic sig check is in done also at decryption time + Message message = messageWithPubKey.getMessage(); + // Those 2 messages are initial request form the taker. + // RequestPayDepositMessage is used also in case of SellerAsTaker but there it is handled in the protocol as it is not an initial request + if (message instanceof RequestDepositTxInputsMessage || + (message instanceof RequestPayDepositMessage && ((RequestPayDepositMessage) message).isInitialRequest)) + handleInitialTakeOfferRequest((TradeMessage) message, sender); + } + }); + } + + private void handleInitialTakeOfferRequest(TradeMessage message, Peer sender) { + log.trace("handleNewMessage: message = " + message.getClass().getSimpleName() + " from " + sender); + try { + nonEmptyStringOf(message.tradeId); + } catch (Throwable t) { + log.warn("Invalid requestDepositTxInputsMessage " + message.toString()); + return; + } + + Optional openOfferOptional = openOfferManager.findOpenOffer(message.tradeId); + if (openOfferOptional.isPresent() && openOfferOptional.get().getState() == OpenOffer.State.AVAILABLE) { + Offer offer = openOfferOptional.get().getOffer(); + openOfferManager.reserveOpenOffer(openOfferOptional.get()); + + OffererTrade trade; + if (offer.getDirection() == Offer.Direction.BUY) + trade = new BuyerAsOffererTrade(offer, pendingTradesStorage); + else + trade = new SellerAsOffererTrade(offer, pendingTradesStorage); + + trade.setStorage(pendingTradesStorage); + pendingTrades.add(trade); + initTrade(trade); + trade.handleTakeOfferRequest(message, sender); + setupDepositPublishedListener(trade); + } + else { + // TODO respond + //(RequestDepositTxInputsMessage)message. + // messageService.sendEncryptedMessage(sender,messageWithPubKey.getMessage().); + log.info("We received a take offer request but don't have that offer anymore."); + } + } + + // 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 == OffererTradeState.ProcessState.DEPOSIT_PUBLISHED) { + openOfferManager.closeOpenOffer(trade.getOffer()); + trade.setTakeOfferDate(new Date()); + } + }); } private void setMailboxMessagesToTrades(List encryptedMessages) { @@ -208,20 +243,13 @@ public class TradeManager { } private void initPendingTrades() { - log.trace("initPendingTrades"); List failedTrades = new ArrayList<>(); for (Trade trade : pendingTrades) { // 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. - boolean failed = false; - if (trade instanceof TakerTrade) - failed = trade.lifeCycleState == TakerTradeState.LifeCycleState.FAILED; - else if (trade instanceof OffererTrade) - failed = trade.lifeCycleState == OffererTradeState.LifeCycleState.FAILED; - - if (failed) { + if (trade.lifeCycleState == Trade.LifeCycleState.FAILED) { failedTrades.add(trade); } else { @@ -232,63 +260,21 @@ public class TradeManager { } for (Trade trade : failedTrades) { pendingTrades.remove(trade); - closedTrades.add(trade); - } - } - - public void shutDown() { - if (!shutDownRequested) { - log.debug("shutDown"); - shutDownRequested = true; - // we remove own offers form offerbook when we go offline - for (Trade trade : openOfferTrades) { - Offer offer = trade.getOffer(); - offerBookService.removeOfferAtShutDown(offer); - } + closedTradableManager.add(trade); } } /////////////////////////////////////////////////////////////////////////////////////////// - // Offer + // Called from Offerbook when offer gets removed from DHT /////////////////////////////////////////////////////////////////////////////////////////// - public void placeOffer(String id, - Offer.Direction direction, - Fiat price, - Coin amount, - Coin minAmount, - TransactionResultHandler resultHandler, - ErrorMessageHandler errorMessageHandler) { - - FiatAccount fiatAccount = user.currentFiatAccountProperty().get(); - Offer offer = new Offer(id, - keyRing.getPubKeyRing(), - direction, - price.getValue(), - amount, - minAmount, - fiatAccount.type, - fiatAccount.currencyCode, - fiatAccount.country, - fiatAccount.id, - accountSettings.getAcceptedArbitratorIds(), - accountSettings.getSecurityDeposit(), - accountSettings.getAcceptedCountries(), - accountSettings.getAcceptedLanguageLocaleCodes()); - - PlaceOfferModel model = new PlaceOfferModel(offer, walletService, tradeWalletService, offerBookService); - - PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol( - model, - transaction -> handlePlaceOfferResult(transaction, offer, resultHandler), - errorMessageHandler::handleErrorMessage - ); - - placeOfferProtocol.placeOffer(); + public void onOfferRemovedFromRemoteOfferBook(Offer offer) { + disposeCheckOfferAvailabilityRequest(offer); } - private void handlePlaceOfferResult(Transaction transaction, Offer offer, TransactionResultHandler resultHandler) { + + /* private void handlePlaceOfferResult(Transaction transaction, Offer offer, TransactionResultHandler resultHandler) { Trade trade; if (offer.getDirection() == Offer.Direction.BUY) trade = new BuyerAsOffererTrade(offer, openOfferTradesStorage); @@ -299,9 +285,9 @@ public class TradeManager { initTrade(trade); setupDepositPublishedListener(trade); resultHandler.handleResult(transaction); - } + }*/ - private void setupDepositPublishedListener(Trade trade) { + /* private void setupDepositPublishedListener(Trade trade) { trade.processStateProperty().addListener((ov, oldValue, newValue) -> { log.debug("setupDepositPublishedListener state = " + newValue); if (newValue == OffererTradeState.ProcessState.DEPOSIT_PUBLISHED) { @@ -314,13 +300,13 @@ public class TradeManager { trade.setStorage(pendingTradesStorage); } }); - } + }*/ - public void onCancelOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + /* public void onCancelOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { removeOpenOffer(offer, resultHandler, errorMessageHandler, true); } - - private void removeOpenOffer(Offer offer, +*/ + /* private void removeOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, boolean isCancelRequest) { @@ -345,7 +331,7 @@ public class TradeManager { resultHandler.handleResult(); }, (message, throwable) -> errorMessageHandler.handleErrorMessage(message)); - } + }*/ /////////////////////////////////////////////////////////////////////////////////////////// @@ -354,13 +340,13 @@ public class TradeManager { public void checkOfferAvailability(Offer offer) { if (!checkOfferAvailabilityProtocolMap.containsKey(offer.getId())) { - CheckOfferAvailabilityModel model = new CheckOfferAvailabilityModel( + OfferAvailabilityModel model = new OfferAvailabilityModel( offer, keyRing.getPubKeyRing(), messageService, addressService); - CheckOfferAvailabilityProtocol protocol = new CheckOfferAvailabilityProtocol(model, + OfferAvailabilityProtocol protocol = new OfferAvailabilityProtocol(model, () -> disposeCheckOfferAvailabilityRequest(offer), (errorMessage) -> disposeCheckOfferAvailabilityRequest(offer)); checkOfferAvailabilityProtocolMap.put(offer.getId(), protocol); @@ -378,15 +364,15 @@ public class TradeManager { // First we check if offer is still available then we create the trade with the protocol public void requestTakeOffer(Coin amount, Offer offer, TakeOfferResultHandler takeOfferResultHandler) { - CheckOfferAvailabilityModel model = new CheckOfferAvailabilityModel(offer, keyRing.getPubKeyRing(), messageService, addressService); - CheckOfferAvailabilityProtocol availabilityProtocol = new CheckOfferAvailabilityProtocol(model, + OfferAvailabilityModel model = new OfferAvailabilityModel(offer, keyRing.getPubKeyRing(), messageService, addressService); + OfferAvailabilityProtocol availabilityProtocol = new OfferAvailabilityProtocol(model, () -> createTrade(amount, offer, model, takeOfferResultHandler), (errorMessage) -> disposeCheckOfferAvailabilityRequest(offer)); checkOfferAvailabilityProtocolMap.put(offer.getId(), availabilityProtocol); availabilityProtocol.checkOfferAvailability(); } - private void createTrade(Coin amount, Offer offer, CheckOfferAvailabilityModel model, TakeOfferResultHandler + private void createTrade(Coin amount, Offer offer, OfferAvailabilityModel model, TakeOfferResultHandler takeOfferResultHandler) { disposeCheckOfferAvailabilityRequest(offer); if (offer.getState() == Offer.State.AVAILABLE) { @@ -419,13 +405,10 @@ public class TradeManager { public void onSuccess(@javax.annotation.Nullable Transaction transaction) { if (transaction != null) { log.info("onWithdraw onSuccess tx ID:" + transaction.getHashAsString()); - if (trade instanceof OffererTrade) - trade.setLifeCycleState(OffererTradeState.LifeCycleState.COMPLETED); - else if (trade instanceof TakerTrade) - trade.setLifeCycleState(TakerTradeState.LifeCycleState.COMPLETED); + trade.setLifeCycleState(Trade.LifeCycleState.COMPLETED); pendingTrades.remove(trade); - closedTrades.add(trade); + closedTradableManager.add(trade); resultHandler.handleResult(); } @@ -452,27 +435,27 @@ public class TradeManager { // Called from Offerbook when offer gets removed from DHT /////////////////////////////////////////////////////////////////////////////////////////// - public void onOfferRemovedFromRemoteOfferBook(Offer offer) { + /* public void onOfferRemovedFromRemoteOfferBook(Offer offer) { disposeCheckOfferAvailabilityRequest(offer); } - +*/ /////////////////////////////////////////////////////////////////////////////////////////// // Getters /////////////////////////////////////////////////////////////////////////////////////////// - public ObservableList getOpenOfferTrades() { + /* public ObservableList getOpenOfferTrades() { return openOfferTrades.getObservableList(); - } + }*/ public ObservableList getPendingTrades() { return pendingTrades.getObservableList(); } - public ObservableList getClosedTrades() { + /* public ObservableList getClosedTrades() { return closedTrades.getObservableList(); } - +*/ /////////////////////////////////////////////////////////////////////////////////////////// // Misc @@ -480,7 +463,7 @@ public class TradeManager { private void disposeCheckOfferAvailabilityRequest(Offer offer) { if (checkOfferAvailabilityProtocolMap.containsKey(offer.getId())) { - CheckOfferAvailabilityProtocol protocol = checkOfferAvailabilityProtocolMap.get(offer.getId()); + OfferAvailabilityProtocol protocol = checkOfferAvailabilityProtocolMap.get(offer.getId()); protocol.cancel(); checkOfferAvailabilityProtocolMap.remove(offer.getId()); } @@ -499,6 +482,6 @@ public class TradeManager { } public boolean isMyOffer(Offer offer) { - return offer.getPubKeyRing().getHashString().equals(keyRing.getPubKeyRing().getHashString()); + return offer.isMyOffer(keyRing); } } \ No newline at end of file diff --git a/core/src/main/java/io/bitsquare/trade/TradeModule.java b/core/src/main/java/io/bitsquare/trade/TradeModule.java index 9a4f122805..17f2519fab 100644 --- a/core/src/main/java/io/bitsquare/trade/TradeModule.java +++ b/core/src/main/java/io/bitsquare/trade/TradeModule.java @@ -18,8 +18,8 @@ package io.bitsquare.trade; import io.bitsquare.BitsquareModule; +import io.bitsquare.trade.closed.ClosedTradableManager; -import com.google.inject.Injector; import com.google.inject.Singleton; import org.slf4j.Logger; @@ -37,11 +37,12 @@ public class TradeModule extends BitsquareModule { @Override protected void configure() { bind(TradeManager.class).in(Singleton.class); + bind(ClosedTradableManager.class).in(Singleton.class); } - @Override + /* @Override protected void doClose(Injector injector) { log.trace("doClose " + getClass().getSimpleName()); injector.getInstance(TradeManager.class).shutDown(); - } + }*/ } diff --git a/core/src/main/java/io/bitsquare/trade/closed/ClosedTradableManager.java b/core/src/main/java/io/bitsquare/trade/closed/ClosedTradableManager.java new file mode 100644 index 0000000000..107b59b1cb --- /dev/null +++ b/core/src/main/java/io/bitsquare/trade/closed/ClosedTradableManager.java @@ -0,0 +1,62 @@ +/* + * 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 . + */ + +package io.bitsquare.trade.closed; + +import io.bitsquare.crypto.KeyRing; +import io.bitsquare.storage.Storage; +import io.bitsquare.trade.Tradable; +import io.bitsquare.trade.TradableList; +import io.bitsquare.trade.offer.Offer; + +import com.google.inject.Inject; + +import java.io.File; + +import javax.inject.Named; + +import javafx.collections.ObservableList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ClosedTradableManager { + private static final Logger log = LoggerFactory.getLogger(ClosedTradableManager.class); + private final TradableList closedTrades; + private KeyRing keyRing; + + @Inject + public ClosedTradableManager(KeyRing keyRing, @Named("storage.dir") File storageDir) { + this.keyRing = keyRing; + this.closedTrades = new TradableList<>(new Storage<>(storageDir), "ClosedTrades"); + + } + + public void add(Tradable tradable) { + closedTrades.add(tradable); + } + + public boolean wasMyOffer(Offer offer) { + return offer.isMyOffer(keyRing); + } + + public ObservableList getClosedTrades() { + return closedTrades.getObservableList(); + } + + +} diff --git a/core/src/main/java/io/bitsquare/offer/Offer.java b/core/src/main/java/io/bitsquare/trade/offer/Offer.java similarity index 96% rename from core/src/main/java/io/bitsquare/offer/Offer.java rename to core/src/main/java/io/bitsquare/trade/offer/Offer.java index 36b2cb03f4..161e95737e 100644 --- a/core/src/main/java/io/bitsquare/offer/Offer.java +++ b/core/src/main/java/io/bitsquare/trade/offer/Offer.java @@ -15,9 +15,10 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.offer; +package io.bitsquare.trade.offer; import io.bitsquare.btc.Restrictions; +import io.bitsquare.crypto.KeyRing; import io.bitsquare.crypto.PubKeyRing; import io.bitsquare.fiat.FiatAccount; import io.bitsquare.locale.Country; @@ -51,12 +52,11 @@ public class Offer implements Serializable { public enum Direction {BUY, SELL} public enum State { - UNKNOWN, + UNDEFINED, AVAILABLE, - RESERVED, + NOT_AVAILABLE, REMOVED, - OFFERER_OFFLINE, - FAULT + OFFERER_OFFLINE } @@ -83,7 +83,7 @@ public class Offer implements Serializable { // Mutable property. Has to be set before offer is save in DHT as it changes the objects hash! private String offerFeePaymentTxID; - private State state = State.UNKNOWN; + private State state = State.UNDEFINED; // Those state properties are transient and only used at runtime! // don't access directly as it might be null; use getStateProperty() which creates an object if not instantiated @@ -125,7 +125,7 @@ public class Offer implements Serializable { this.acceptedLanguageCodes = acceptedLanguageCodes; creationDate = new Date(); - setState(State.UNKNOWN); + setState(State.UNDEFINED); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { @@ -160,6 +160,10 @@ public class Offer implements Serializable { // TODO check upper and lower bounds for fiat } + public boolean isMyOffer(KeyRing keyRing) { + return getPubKeyRing().getHashString().equals(keyRing.getPubKeyRing().getHashString()); + } + public Fiat getVolumeByAmount(Coin amount) { if (fiatPrice != 0 && amount != null && !amount.isZero()) return new ExchangeRate(Fiat.valueOf(currencyCode, fiatPrice)).coinToFiat(amount); diff --git a/core/src/main/java/io/bitsquare/offer/OfferBookService.java b/core/src/main/java/io/bitsquare/trade/offer/OfferBookService.java similarity index 97% rename from core/src/main/java/io/bitsquare/offer/OfferBookService.java rename to core/src/main/java/io/bitsquare/trade/offer/OfferBookService.java index f52f5da95b..0938071f56 100644 --- a/core/src/main/java/io/bitsquare/offer/OfferBookService.java +++ b/core/src/main/java/io/bitsquare/trade/offer/OfferBookService.java @@ -15,7 +15,7 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.offer; +package io.bitsquare.trade.offer; import io.bitsquare.common.handlers.FaultHandler; import io.bitsquare.common.handlers.ResultHandler; diff --git a/core/src/main/java/io/bitsquare/offer/OfferModule.java b/core/src/main/java/io/bitsquare/trade/offer/OfferModule.java similarity index 67% rename from core/src/main/java/io/bitsquare/offer/OfferModule.java rename to core/src/main/java/io/bitsquare/trade/offer/OfferModule.java index ff5a21bb11..3fdb247670 100644 --- a/core/src/main/java/io/bitsquare/offer/OfferModule.java +++ b/core/src/main/java/io/bitsquare/trade/offer/OfferModule.java @@ -15,13 +15,20 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.offer; +package io.bitsquare.trade.offer; import io.bitsquare.BitsquareModule; +import com.google.inject.Injector; +import com.google.inject.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import org.springframework.core.env.Environment; public abstract class OfferModule extends BitsquareModule { + private static final Logger log = LoggerFactory.getLogger(OfferModule.class); protected OfferModule(Environment env) { super(env); @@ -29,9 +36,16 @@ public abstract class OfferModule extends BitsquareModule { @Override protected final void configure() { + bind(OpenOfferManager.class).in(Singleton.class); doConfigure(); } protected void doConfigure() { } + + @Override + protected void doClose(Injector injector) { + log.trace("doClose " + getClass().getSimpleName()); + injector.getInstance(OpenOfferManager.class).shutDown(); + } } diff --git a/core/src/main/java/io/bitsquare/trade/offer/OpenOffer.java b/core/src/main/java/io/bitsquare/trade/offer/OpenOffer.java new file mode 100644 index 0000000000..14db034658 --- /dev/null +++ b/core/src/main/java/io/bitsquare/trade/offer/OpenOffer.java @@ -0,0 +1,124 @@ +/* + * 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 . + */ + +package io.bitsquare.trade.offer; + +import io.bitsquare.storage.Storage; +import io.bitsquare.trade.Tradable; +import io.bitsquare.trade.TradableList; + +import org.bitcoinj.utils.Threading; + +import java.io.Serializable; + +import java.util.Date; +import java.util.Timer; +import java.util.TimerTask; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OpenOffer implements Tradable, Serializable { + // That object is saved to disc. We need to take care of changes to not break deserialization. + private static final long serialVersionUID = 1L; + + private static final Logger log = LoggerFactory.getLogger(OpenOffer.class); + + transient private static final long TIMEOUT = 5000; + + public enum State { + AVAILABLE, + RESERVED, + CLOSED, + CANCELED + } + + private final Offer offer; + private State state = State.AVAILABLE; + + transient private Timer timeoutTimer; + transient private Storage> storage; + + public OpenOffer(Offer offer, Storage> storage) { + this.offer = offer; + this.storage = storage; + } + + public Date getDate() { + return offer.getCreationDate(); + } + + @Override + public String getId() { + return offer.getId(); + } + + public Offer getOffer() { + return offer; + } + + public void setStorage(Storage> storage) { + this.storage = storage; + } + + public void setState(State state) { + log.trace("setState" + state); + this.state = state; + storage.queueUpForSave(); + + // We keep it reserved for a limited time, if trade preparation fails we revert to available state + if (this.state == State.RESERVED) + startTimeout(); + else + stopTimeout(); + + } + + public State getState() { + return state; + } + + + private void startTimeout() { + log.trace("startTimeout"); + stopTimeout(); + + timeoutTimer = new Timer(); + TimerTask task = new TimerTask() { + @Override + public void run() { + Threading.USER_THREAD.execute(() -> { + log.debug("Timeout reached"); + if (state == State.RESERVED) + setState(State.AVAILABLE); + }); + } + }; + + timeoutTimer.schedule(task, TIMEOUT); + } + + protected void stopTimeout() { + log.trace("stopTimeout"); + if (timeoutTimer != null) { + timeoutTimer.cancel(); + timeoutTimer = null; + } + } +} + + \ No newline at end of file diff --git a/core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java b/core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java new file mode 100644 index 0000000000..4af38ea05b --- /dev/null +++ b/core/src/main/java/io/bitsquare/trade/offer/OpenOfferManager.java @@ -0,0 +1,287 @@ +/* + * 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 . + */ + +package io.bitsquare.trade.offer; + +import io.bitsquare.btc.TradeWalletService; +import io.bitsquare.btc.WalletService; +import io.bitsquare.common.handlers.ErrorMessageHandler; +import io.bitsquare.common.handlers.ResultHandler; +import io.bitsquare.crypto.KeyRing; +import io.bitsquare.crypto.MessageWithPubKey; +import io.bitsquare.fiat.FiatAccount; +import io.bitsquare.p2p.DecryptedMessageHandler; +import io.bitsquare.p2p.Message; +import io.bitsquare.p2p.MessageService; +import io.bitsquare.p2p.Peer; +import io.bitsquare.p2p.listener.SendMessageListener; +import io.bitsquare.storage.Storage; +import io.bitsquare.trade.TradableList; +import io.bitsquare.trade.closed.ClosedTradableManager; +import io.bitsquare.trade.handlers.TransactionResultHandler; +import io.bitsquare.trade.protocol.availability.messages.OfferAvailabilityRequest; +import io.bitsquare.trade.protocol.availability.messages.OfferAvailabilityResponse; +import io.bitsquare.trade.protocol.placeoffer.PlaceOfferModel; +import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol; +import io.bitsquare.user.AccountSettings; +import io.bitsquare.user.User; + +import org.bitcoinj.core.Coin; +import org.bitcoinj.utils.Fiat; + +import com.google.inject.Inject; + +import java.io.File; + +import java.util.Optional; + +import javax.inject.Named; + +import javafx.collections.ObservableList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static com.google.inject.internal.util.$Preconditions.checkNotNull; +import static io.bitsquare.util.Validator.nonEmptyStringOf; + +public class OpenOfferManager { + private static final Logger log = LoggerFactory.getLogger(OpenOfferManager.class); + + private final User user; + private final KeyRing keyRing; + private final AccountSettings accountSettings; + private final WalletService walletService; + private MessageService messageService; + private final TradeWalletService tradeWalletService; + private final OfferBookService offerBookService; + private ClosedTradableManager closedTradableManager; + + private final TradableList openOffers; + private final Storage> openOffersStorage; + private boolean shutDownRequested; + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + @Inject + public OpenOfferManager(User user, + KeyRing keyRing, + AccountSettings accountSettings, + WalletService walletService, + MessageService messageService, + TradeWalletService tradeWalletService, + OfferBookService offerBookService, + ClosedTradableManager closedTradableManager, + @Named("storage.dir") File storageDir) { + this.user = user; + this.keyRing = keyRing; + this.accountSettings = accountSettings; + this.walletService = walletService; + this.messageService = messageService; + this.tradeWalletService = tradeWalletService; + this.offerBookService = offerBookService; + this.closedTradableManager = closedTradableManager; + + openOffersStorage = new Storage<>(storageDir); + this.openOffers = new TradableList<>(openOffersStorage, "OpenOffers"); + + // In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook + Thread shutDownHookThread = new Thread(OpenOfferManager.this::shutDown, "OpenOfferManager.ShutDownHook"); + Runtime.getRuntime().addShutdownHook(shutDownHookThread); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Lifecycle + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onAllServicesInitialized() { + log.trace("onAllServicesInitialized"); + + // Handler for incoming offer availability requests + messageService.addDecryptedMessageHandler(new DecryptedMessageHandler() { + @Override + public void handleMessage(MessageWithPubKey messageWithPubKey, Peer sender) { + // We get an encrypted message but don't do the signature check as we don't know the peer yet. + // A basic sig check is in done also at decryption time + Message message = messageWithPubKey.getMessage(); + if (message instanceof OfferAvailabilityRequest) + handleOfferAvailabilityRequest((OfferAvailabilityRequest) message, sender); + } + }); + + for (OpenOffer openOffer : openOffers) { + // We add own offers to offerbook when we go online again + offerBookService.addOffer(openOffer.getOffer(), + () -> log.debug("Successful added offer to DHT"), + (message, throwable) -> log.error("Add offer to DHT failed. " + message)); + //setupDepositPublishedListener(openOffer); + openOffer.setStorage(openOffersStorage); + } + } + + public void shutDown() { + if (!shutDownRequested) { + log.debug("shutDown"); + shutDownRequested = true; + // we remove own offers form offerbook when we go offline + for (OpenOffer openOffer : openOffers) { + offerBookService.removeOfferAtShutDown(openOffer.getOffer()); + } + } + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // API + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onPlaceOffer(String id, + Offer.Direction direction, + Fiat price, + Coin amount, + Coin minAmount, + TransactionResultHandler resultHandler, + ErrorMessageHandler errorMessageHandler) { + + FiatAccount fiatAccount = user.currentFiatAccountProperty().get(); + Offer offer = new Offer(id, + keyRing.getPubKeyRing(), + direction, + price.getValue(), + amount, + minAmount, + fiatAccount.type, + fiatAccount.currencyCode, + fiatAccount.country, + fiatAccount.id, + accountSettings.getAcceptedArbitratorIds(), + accountSettings.getSecurityDeposit(), + accountSettings.getAcceptedCountries(), + accountSettings.getAcceptedLanguageLocaleCodes()); + + PlaceOfferModel model = new PlaceOfferModel(offer, walletService, tradeWalletService, offerBookService); + + PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol( + model, + transaction -> { + OpenOffer openOffer = new OpenOffer(offer, openOffersStorage); + openOffers.add(openOffer); + openOffersStorage.queueUpForSave(); + resultHandler.handleResult(transaction); + }, + errorMessageHandler::handleErrorMessage + ); + + placeOfferProtocol.placeOffer(); + } + + + public void onCancelOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + Optional openOfferOptional = findOpenOffer(offer.getId()); + if (openOfferOptional.isPresent()) + onCancelOpenOffer(openOfferOptional.get(), resultHandler, errorMessageHandler); + } + + public void onCancelOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + offerBookService.removeOffer(openOffer.getOffer(), + () -> { + openOffer.getOffer().setState(Offer.State.REMOVED); + openOffer.setState(OpenOffer.State.CANCELED); + openOffers.remove(openOffer); + closedTradableManager.add(openOffer); + //disposeCheckOfferAvailabilityRequest(offer); + resultHandler.handleResult(); + }, + (message, throwable) -> errorMessageHandler.handleErrorMessage(message)); + } + + public void reserveOpenOffer(OpenOffer openOffer) { + openOffer.setState(OpenOffer.State.RESERVED); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Getters + /////////////////////////////////////////////////////////////////////////////////////////// + + public boolean isMyOffer(Offer offer) { + return offer.isMyOffer(keyRing); + } + + public ObservableList getOpenOffers() { + return openOffers.getObservableList(); + } + + public Optional findOpenOffer(String offerId) { + return openOffers.stream().filter(openOffer -> openOffer.getOffer().getId().equals(offerId)).findAny(); + } + + // Close openOffer after deposit published + public void closeOpenOffer(Offer offer) { + findOpenOffer(offer.getId()).ifPresent(openOffer -> { + openOffers.remove(openOffer); + openOffer.setState(OpenOffer.State.CLOSED); + offerBookService.removeOffer(openOffer.getOffer(), + () -> log.trace("Successful removed offer"), + (message, throwable) -> log.error(message)); + }); + + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Offer Availability + /////////////////////////////////////////////////////////////////////////////////////////// + + private void handleOfferAvailabilityRequest(OfferAvailabilityRequest message, Peer sender) { + log.trace("handleNewMessage: message = " + message.getClass().getSimpleName() + " from " + sender); + try { + nonEmptyStringOf(message.offerId); + checkNotNull(message.getPubKeyRing()); + } catch (Throwable t) { + log.warn("Invalid message " + message.toString()); + return; + } + + Optional openOfferOptional = findOpenOffer(message.offerId); + boolean isAvailable = openOfferOptional.isPresent() && openOfferOptional.get().getState() == OpenOffer.State.AVAILABLE; + try { + OfferAvailabilityResponse offerAvailabilityResponse = new OfferAvailabilityResponse(message.offerId, isAvailable); + messageService.sendEncryptedMessage(sender, + message.getPubKeyRing(), + offerAvailabilityResponse, + new SendMessageListener() { + @Override + public void handleResult() { + log.trace("ReportOfferAvailabilityMessage successfully arrived at peer"); + } + + @Override + public void handleFault() { + log.info("Sending ReportOfferAvailabilityMessage failed."); + } + }); + } catch (Throwable t) { + t.printStackTrace(); + log.info("Exception at handleRequestIsOfferAvailableMessage " + t.getMessage()); + } + } +} diff --git a/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferBookService.java b/core/src/main/java/io/bitsquare/trade/offer/tomp2p/TomP2POfferBookService.java similarity index 99% rename from core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferBookService.java rename to core/src/main/java/io/bitsquare/trade/offer/tomp2p/TomP2POfferBookService.java index d5ef1d16a4..8383c1d217 100644 --- a/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferBookService.java +++ b/core/src/main/java/io/bitsquare/trade/offer/tomp2p/TomP2POfferBookService.java @@ -15,15 +15,15 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.offer.tomp2p; +package io.bitsquare.trade.offer.tomp2p; import io.bitsquare.common.handlers.FaultHandler; import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.crypto.KeyRing; -import io.bitsquare.offer.Offer; -import io.bitsquare.offer.OfferBookService; import io.bitsquare.p2p.tomp2p.TomP2PDHTService; import io.bitsquare.p2p.tomp2p.TomP2PNode; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.offer.OfferBookService; import java.io.IOException; diff --git a/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java b/core/src/main/java/io/bitsquare/trade/offer/tomp2p/TomP2POfferModule.java similarity index 88% rename from core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java rename to core/src/main/java/io/bitsquare/trade/offer/tomp2p/TomP2POfferModule.java index a92e8ac065..915b9fa0cf 100644 --- a/core/src/main/java/io/bitsquare/offer/tomp2p/TomP2POfferModule.java +++ b/core/src/main/java/io/bitsquare/trade/offer/tomp2p/TomP2POfferModule.java @@ -15,10 +15,10 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.offer.tomp2p; +package io.bitsquare.trade.offer.tomp2p; -import io.bitsquare.offer.OfferBookService; -import io.bitsquare.offer.OfferModule; +import io.bitsquare.trade.offer.OfferBookService; +import io.bitsquare.trade.offer.OfferModule; import com.google.inject.Singleton; diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/CheckOfferAvailabilityModel.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/OfferAvailabilityModel.java similarity index 85% rename from core/src/main/java/io/bitsquare/trade/protocol/availability/CheckOfferAvailabilityModel.java rename to core/src/main/java/io/bitsquare/trade/protocol/availability/OfferAvailabilityModel.java index ac20f8c675..563e5ad377 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/CheckOfferAvailabilityModel.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/OfferAvailabilityModel.java @@ -19,17 +19,17 @@ package io.bitsquare.trade.protocol.availability; import io.bitsquare.common.taskrunner.Model; import io.bitsquare.crypto.PubKeyRing; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.AddressService; import io.bitsquare.p2p.MessageService; import io.bitsquare.p2p.Peer; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.protocol.availability.messages.OfferMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class CheckOfferAvailabilityModel implements Model { - private static final Logger log = LoggerFactory.getLogger(CheckOfferAvailabilityModel.class); +public class OfferAvailabilityModel implements Model { + private static final Logger log = LoggerFactory.getLogger(OfferAvailabilityModel.class); public final Offer offer; private final PubKeyRing pubKeyRing; @@ -39,7 +39,7 @@ public class CheckOfferAvailabilityModel implements Model { private Peer peer; private OfferMessage message; - public CheckOfferAvailabilityModel(Offer offer, PubKeyRing pubKeyRing, MessageService messageService, AddressService addressService) { + public OfferAvailabilityModel(Offer offer, PubKeyRing pubKeyRing, MessageService messageService, AddressService addressService) { this.offer = offer; this.pubKeyRing = pubKeyRing; this.messageService = messageService; @@ -64,12 +64,10 @@ public class CheckOfferAvailabilityModel implements Model { @Override public void persist() { - } @Override public void onComplete() { - } public PubKeyRing getPubKeyRing() { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/CheckOfferAvailabilityProtocol.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/OfferAvailabilityProtocol.java similarity index 80% rename from core/src/main/java/io/bitsquare/trade/protocol/availability/CheckOfferAvailabilityProtocol.java rename to core/src/main/java/io/bitsquare/trade/protocol/availability/OfferAvailabilityProtocol.java index 23250e0c32..7ab5e2ec7f 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/CheckOfferAvailabilityProtocol.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/OfferAvailabilityProtocol.java @@ -21,15 +21,15 @@ import io.bitsquare.common.handlers.ErrorMessageHandler; import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.common.taskrunner.TaskRunner; import io.bitsquare.crypto.MessageWithPubKey; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.DecryptedMessageHandler; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Peer; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.protocol.availability.messages.OfferAvailabilityResponse; import io.bitsquare.trade.protocol.availability.messages.OfferMessage; -import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage; import io.bitsquare.trade.protocol.availability.tasks.GetPeerAddress; -import io.bitsquare.trade.protocol.availability.tasks.ProcessReportOfferAvailabilityMessage; -import io.bitsquare.trade.protocol.availability.tasks.SendRequestIsOfferAvailableMessage; +import io.bitsquare.trade.protocol.availability.tasks.ProcessOfferAvailabilityResponse; +import io.bitsquare.trade.protocol.availability.tasks.SendOfferAvailabilityRequest; import org.bitcoinj.utils.Threading; @@ -41,26 +41,26 @@ import org.slf4j.LoggerFactory; import static io.bitsquare.util.Validator.nonEmptyStringOf; -public class CheckOfferAvailabilityProtocol { - private static final Logger log = LoggerFactory.getLogger(CheckOfferAvailabilityProtocol.class); +public class OfferAvailabilityProtocol { + private static final Logger log = LoggerFactory.getLogger(OfferAvailabilityProtocol.class); private static final long TIMEOUT = 10000; - private final CheckOfferAvailabilityModel model; + private final OfferAvailabilityModel model; private final ResultHandler resultHandler; private final ErrorMessageHandler errorMessageHandler; private final DecryptedMessageHandler decryptedMessageHandler; private Timer timeoutTimer; private boolean isCanceled; - private TaskRunner taskRunner; + private TaskRunner taskRunner; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// - public CheckOfferAvailabilityProtocol(CheckOfferAvailabilityModel model, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + public OfferAvailabilityProtocol(OfferAvailabilityModel model, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { this.model = model; this.resultHandler = resultHandler; this.errorMessageHandler = errorMessageHandler; @@ -79,7 +79,7 @@ public class CheckOfferAvailabilityProtocol { public void checkOfferAvailability() { // reset - model.offer.setState(Offer.State.UNKNOWN); + model.offer.setState(Offer.State.UNDEFINED); model.messageService.addDecryptedMessageHandler(decryptedMessageHandler); @@ -89,7 +89,7 @@ public class CheckOfferAvailabilityProtocol { ); taskRunner.addTasks( GetPeerAddress.class, - SendRequestIsOfferAvailableMessage.class + SendOfferAvailabilityRequest.class ); startTimeout(); taskRunner.run(); @@ -111,13 +111,13 @@ public class CheckOfferAvailabilityProtocol { log.trace("handleNewMessage: message = " + message.getClass().getSimpleName() + " from " + sender); if (message instanceof OfferMessage) { nonEmptyStringOf(((OfferMessage) message).offerId); - if (message instanceof ReportOfferAvailabilityMessage && model.offer.getId().equals(((OfferMessage) message).offerId)) - handleDecryptedMessage((ReportOfferAvailabilityMessage) message); + if (message instanceof OfferAvailabilityResponse && model.offer.getId().equals(((OfferMessage) message).offerId)) + handleDecryptedMessage((OfferAvailabilityResponse) message); } } - private void handleDecryptedMessage(ReportOfferAvailabilityMessage message) { + private void handleDecryptedMessage(OfferAvailabilityResponse message) { stopTimeout(); model.setMessage(message); @@ -131,7 +131,7 @@ public class CheckOfferAvailabilityProtocol { errorMessageHandler.handleErrorMessage(errorMessage); } ); - taskRunner.addTasks(ProcessReportOfferAvailabilityMessage.class); + taskRunner.addTasks(ProcessOfferAvailabilityResponse.class); taskRunner.run(); } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/RequestIsOfferAvailableMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/OfferAvailabilityRequest.java similarity index 72% rename from core/src/main/java/io/bitsquare/trade/protocol/availability/messages/RequestIsOfferAvailableMessage.java rename to core/src/main/java/io/bitsquare/trade/protocol/availability/messages/OfferAvailabilityRequest.java index fe867ac1e0..8feb239ef0 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/RequestIsOfferAvailableMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/OfferAvailabilityRequest.java @@ -18,22 +18,29 @@ package io.bitsquare.trade.protocol.availability.messages; import io.bitsquare.crypto.PubKeyRing; -import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import java.io.Serializable; -public class RequestIsOfferAvailableMessage extends TradeMessage implements Serializable { +public class OfferAvailabilityRequest extends OfferMessage implements Serializable { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = 1L; private final PubKeyRing pubKeyRing; - public RequestIsOfferAvailableMessage(String tradeId, PubKeyRing pubKeyRing) { - super(tradeId); + public OfferAvailabilityRequest(String offerId, PubKeyRing pubKeyRing) { + super(offerId); this.pubKeyRing = pubKeyRing; } public PubKeyRing getPubKeyRing() { return pubKeyRing; } + + @Override + public String toString() { + return "RequestIsOfferAvailableMessage{" + + "offerId=" + offerId + + "pubKeyRing=" + pubKeyRing != null ? pubKeyRing.toString() : "null" + + '}'; + } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/ReportOfferAvailabilityMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/OfferAvailabilityResponse.java similarity index 79% rename from core/src/main/java/io/bitsquare/trade/protocol/availability/messages/ReportOfferAvailabilityMessage.java rename to core/src/main/java/io/bitsquare/trade/protocol/availability/messages/OfferAvailabilityResponse.java index 507b250549..16746ba282 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/ReportOfferAvailabilityMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/messages/OfferAvailabilityResponse.java @@ -19,14 +19,14 @@ package io.bitsquare.trade.protocol.availability.messages; import java.io.Serializable; -public class ReportOfferAvailabilityMessage extends OfferMessage implements Serializable { +public class OfferAvailabilityResponse extends OfferMessage implements Serializable { // That object is sent over the wire, so we need to take care of version compatibility. private static final long serialVersionUID = 1L; - public final boolean isOfferOpen; + public final boolean isAvailable; - public ReportOfferAvailabilityMessage(String offerId, boolean isOfferOpen) { + public OfferAvailabilityResponse(String offerId, boolean isAvailable) { super(offerId); - this.isOfferOpen = isOfferOpen; + this.isAvailable = isAvailable; } } \ No newline at end of file diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java index 1a74c57f17..ebe8fa835b 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/GetPeerAddress.java @@ -19,18 +19,18 @@ package io.bitsquare.trade.protocol.availability.tasks; import io.bitsquare.common.taskrunner.Task; import io.bitsquare.common.taskrunner.TaskRunner; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.Peer; import io.bitsquare.p2p.listener.GetPeerAddressListener; -import io.bitsquare.trade.protocol.availability.CheckOfferAvailabilityModel; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.protocol.availability.OfferAvailabilityModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class GetPeerAddress extends Task { +public class GetPeerAddress extends Task { private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class); - public GetPeerAddress(TaskRunner taskHandler, CheckOfferAvailabilityModel model) { + public GetPeerAddress(TaskRunner taskHandler, OfferAvailabilityModel model) { super(taskHandler, model); errorMessage = "DHT lookup for peer address failed. Maybe the offerer was offline for too long time."; @@ -55,8 +55,6 @@ public class GetPeerAddress extends Task { } }); } catch (Throwable t) { - model.offer.setState(Offer.State.FAULT); - failed(t); } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/ProcessReportOfferAvailabilityMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/ProcessOfferAvailabilityResponse.java similarity index 63% rename from core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/ProcessReportOfferAvailabilityMessage.java rename to core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/ProcessOfferAvailabilityResponse.java index 3092bf162d..0fb4d1cc3f 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/ProcessReportOfferAvailabilityMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/ProcessOfferAvailabilityResponse.java @@ -19,36 +19,34 @@ package io.bitsquare.trade.protocol.availability.tasks; import io.bitsquare.common.taskrunner.Task; import io.bitsquare.common.taskrunner.TaskRunner; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.protocol.availability.CheckOfferAvailabilityModel; -import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.protocol.availability.OfferAvailabilityModel; +import io.bitsquare.trade.protocol.availability.messages.OfferAvailabilityResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class ProcessReportOfferAvailabilityMessage extends Task { - private static final Logger log = LoggerFactory.getLogger(ProcessReportOfferAvailabilityMessage.class); +public class ProcessOfferAvailabilityResponse extends Task { + private static final Logger log = LoggerFactory.getLogger(ProcessOfferAvailabilityResponse.class); - public ProcessReportOfferAvailabilityMessage(TaskRunner taskHandler, CheckOfferAvailabilityModel model) { + public ProcessOfferAvailabilityResponse(TaskRunner taskHandler, OfferAvailabilityModel model) { super(taskHandler, model); } @Override protected void doRun() { try { - ReportOfferAvailabilityMessage reportOfferAvailabilityMessage = (ReportOfferAvailabilityMessage) model.getMessage(); + OfferAvailabilityResponse offerAvailabilityResponse = (OfferAvailabilityResponse) model.getMessage(); if (model.offer.getState() != Offer.State.REMOVED) { - if (reportOfferAvailabilityMessage.isOfferOpen) + if (offerAvailabilityResponse.isAvailable) model.offer.setState(Offer.State.AVAILABLE); else - model.offer.setState(Offer.State.RESERVED); + model.offer.setState(Offer.State.NOT_AVAILABLE); } complete(); } catch (Throwable t) { - model.offer.setState(Offer.State.FAULT); - failed(t); } } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/SendRequestIsOfferAvailableMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/SendOfferAvailabilityRequest.java similarity index 72% rename from core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/SendRequestIsOfferAvailableMessage.java rename to core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/SendOfferAvailabilityRequest.java index 5b2e3108f9..e272cf2710 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/SendRequestIsOfferAvailableMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/availability/tasks/SendOfferAvailabilityRequest.java @@ -19,26 +19,25 @@ package io.bitsquare.trade.protocol.availability.tasks; import io.bitsquare.common.taskrunner.Task; import io.bitsquare.common.taskrunner.TaskRunner; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.listener.SendMessageListener; -import io.bitsquare.trade.protocol.availability.CheckOfferAvailabilityModel; -import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.protocol.availability.OfferAvailabilityModel; +import io.bitsquare.trade.protocol.availability.messages.OfferAvailabilityRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class SendRequestIsOfferAvailableMessage extends Task { - private static final Logger log = LoggerFactory.getLogger(SendRequestIsOfferAvailableMessage.class); - private static final long serialVersionUID = 1L; +public class SendOfferAvailabilityRequest extends Task { + private static final Logger log = LoggerFactory.getLogger(SendOfferAvailabilityRequest.class); - public SendRequestIsOfferAvailableMessage(TaskRunner taskHandler, CheckOfferAvailabilityModel model) { + public SendOfferAvailabilityRequest(TaskRunner taskHandler, OfferAvailabilityModel model) { super(taskHandler, model); } @Override protected void doRun() { try { - RequestIsOfferAvailableMessage message = new RequestIsOfferAvailableMessage(model.offer.getId(), model.getPubKeyRing()); + OfferAvailabilityRequest message = new OfferAvailabilityRequest(model.offer.getId(), model.getPubKeyRing()); model.messageService.sendEncryptedMessage(model.getPeer(), model.offer.getPubKeyRing(), message, @@ -56,8 +55,6 @@ public class SendRequestIsOfferAvailableMessage extends Task log.debug("taskRunner at handleRequestDepositTxInputsMessage completed"), + this::handleTaskRunnerFault); + taskRunner.addTasks( + ProcessRequestDepositTxInputsMessage.class, + CreateDepositTxInputs.class, + SendRequestPayDepositMessage.class + ); + taskRunner.run(); + startTimeout(); + } + @Override public void doApplyMailboxMessage(Message message, Trade trade) { this.trade = trade; @@ -93,61 +108,6 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc // Incoming message handling /////////////////////////////////////////////////////////////////////////////////////////// - // OpenOffer requests - // We get an encrypted message but don't do the signature check as we don't know the peer yet. - // A basic sig check is in done also at decryption time - private void handle(RequestIsOfferAvailableMessage message, Peer sender) { - try { - checkTradeId(processModel.getId(), message); - - // We don't store anything in the offererTradeProcessModel as we might be in a trade process and receive that request from another peer who wants - // to take the offer at the same time - boolean isOfferOpen = buyerAsOffererTrade.lifeCycleStateProperty().get() == OffererTradeState.LifeCycleState.OFFER_OPEN; - - ReportOfferAvailabilityMessage reportOfferAvailabilityMessage = new ReportOfferAvailabilityMessage(processModel.getId(), isOfferOpen); - processModel.getMessageService().sendEncryptedMessage(sender, - message.getPubKeyRing(), - reportOfferAvailabilityMessage, - new SendMessageListener() { - @Override - public void handleResult() { - // Offerer does not do anything at that moment. Peer might only watch the offer and does not start a trade. - log.trace("ReportOfferAvailabilityMessage successfully arrived at peer"); - } - - @Override - public void handleFault() { - // We don't handle the error as we might be in a trade process with another trader - log.warn("Sending ReportOfferAvailabilityMessage failed."); - } - }); - } catch (Throwable t) { - // We don't handle the error as we might be in a trade process with another trader - t.printStackTrace(); - log.warn("Exception at handleRequestIsOfferAvailableMessage " + t.getMessage()); - } - } - - // Trade started. We reserve the offer for that taker. If anything goes wrong we reset the offer as open. - private void handle(RequestDepositTxInputsMessage tradeMessage, Peer taker) { - checkTradeId(processModel.getId(), tradeMessage); - processModel.setTradeMessage(tradeMessage); - buyerAsOffererTrade.setTradingPeer(taker); - - buyerAsOffererTrade.setLifeCycleState(OffererTradeState.LifeCycleState.OFFER_RESERVED); - - TradeTaskRunner taskRunner = new TradeTaskRunner(buyerAsOffererTrade, - () -> log.debug("taskRunner at handleRequestDepositTxInputsMessage completed"), - this::handleTaskRunnerFault); - taskRunner.addTasks( - ProcessRequestDepositTxInputsMessage.class, - CreateDepositTxInputs.class, - SendRequestPayDepositMessage.class - ); - taskRunner.run(); - startTimeout(); - } - private void handle(RequestPublishDepositTxMessage tradeMessage) { stopTimeout(); processModel.setTradeMessage(tradeMessage); @@ -217,13 +177,7 @@ public class BuyerAsOffererProtocol extends TradeProtocol implements BuyerProtoc @Override protected void doHandleDecryptedMessage(TradeMessage tradeMessage, Peer sender) { - if (tradeMessage instanceof RequestIsOfferAvailableMessage) { - handle((RequestIsOfferAvailableMessage) tradeMessage, sender); - } - else if (tradeMessage instanceof RequestDepositTxInputsMessage) { - handle((RequestDepositTxInputsMessage) tradeMessage, sender); - } - else if (tradeMessage instanceof RequestPublishDepositTxMessage) { + if (tradeMessage instanceof RequestPublishDepositTxMessage) { handle((RequestPublishDepositTxMessage) tradeMessage); } else if (tradeMessage instanceof RequestFinalizePayoutTxMessage) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/OffererProtocol.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/OffererProtocol.java index d933b37d5e..6f19225d5f 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/OffererProtocol.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/OffererProtocol.java @@ -17,5 +17,9 @@ package io.bitsquare.trade.protocol.trade; +import io.bitsquare.p2p.Peer; +import io.bitsquare.trade.protocol.trade.messages.TradeMessage; + public interface OffererProtocol { + void handleTakeOfferRequest(TradeMessage message, Peer taker); } diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java index 0c5bf17ef1..4ad9418a8b 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/ProcessModel.java @@ -27,9 +27,9 @@ import io.bitsquare.crypto.CryptoService; import io.bitsquare.crypto.KeyRing; import io.bitsquare.crypto.PubKeyRing; import io.bitsquare.fiat.FiatAccount; -import io.bitsquare.offer.Offer; import io.bitsquare.p2p.AddressService; import io.bitsquare.p2p.MessageService; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.user.User; diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java index 34498ef10a..47b6bf7e34 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/SellerAsOffererProtocol.java @@ -19,15 +19,11 @@ package io.bitsquare.trade.protocol.trade; import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Peer; -import io.bitsquare.p2p.listener.SendMessageListener; import io.bitsquare.trade.SellerAsOffererTrade; import io.bitsquare.trade.Trade; -import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage; -import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage; import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage; import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage; import io.bitsquare.trade.protocol.trade.messages.PayoutTxFinalizedMessage; -import io.bitsquare.trade.protocol.trade.messages.RequestPayDepositMessage; import io.bitsquare.trade.protocol.trade.messages.TradeMessage; import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakeOfferFeePayment; import io.bitsquare.trade.protocol.trade.tasks.offerer.VerifyTakerAccount; @@ -43,13 +39,10 @@ import io.bitsquare.trade.protocol.trade.tasks.seller.SendRequestPublishDepositT import io.bitsquare.trade.protocol.trade.tasks.seller.SignPayoutTx; import io.bitsquare.trade.protocol.trade.tasks.shared.CommitPayoutTx; import io.bitsquare.trade.protocol.trade.tasks.shared.SetupPayoutTxLockTimeReachedListener; -import io.bitsquare.trade.states.OffererTradeState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static io.bitsquare.util.Validator.checkTradeId; - public class SellerAsOffererProtocol extends TradeProtocol implements SellerProtocol, OffererProtocol { private static final Logger log = LoggerFactory.getLogger(SellerAsOffererProtocol.class); @@ -72,6 +65,26 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt // Public methods /////////////////////////////////////////////////////////////////////////////////////////// + @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( + ProcessRequestPayDepositMessage.class, + VerifyTakerAccount.class, + CreateAndSignContract.class, + CreateAndSignDepositTx.class, + SendRequestPublishDepositTxMessage.class + ); + taskRunner.run(); + startTimeout(); + } + @Override public void doApplyMailboxMessage(Message message, Trade trade) { this.trade = trade; @@ -101,67 +114,6 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt // Incoming message handling /////////////////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////////////////// - // IsOfferAvailable - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handle(RequestIsOfferAvailableMessage message, Peer sender) { - try { - checkTradeId(processModel.getId(), message); - - // We don't store anything in the offererTradeProcessModel as we might be in a trade process and receive that request from another peer who wants - // to take the offer at the same time - boolean isOfferOpen = sellerAsOffererTrade.lifeCycleStateProperty().get() == OffererTradeState.LifeCycleState.OFFER_OPEN; - - ReportOfferAvailabilityMessage reportOfferAvailabilityMessage = new ReportOfferAvailabilityMessage(processModel.getId(), isOfferOpen); - processModel.getMessageService().sendEncryptedMessage(sender, - message.getPubKeyRing(), - reportOfferAvailabilityMessage, - new SendMessageListener() { - @Override - public void handleResult() { - // Offerer does not do anything at that moment. Peer might only watch the offer and does not start a trade. - log.trace("ReportOfferAvailabilityMessage successfully arrived at peer"); - } - - @Override - public void handleFault() { - // We don't handle the error as we might be in a trade process with another trader - log.warn("Sending ReportOfferAvailabilityMessage failed."); - } - }); - } catch (Throwable t) { - // We don't handle the error as we might be in a trade process with another trader - t.printStackTrace(); - log.warn("Exception at handleRequestIsOfferAvailableMessage " + t.getMessage()); - } - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Trade - /////////////////////////////////////////////////////////////////////////////////////////// - - private void handle(RequestPayDepositMessage tradeMessage, Peer sender) { - processModel.setTradeMessage(tradeMessage); - - sellerAsOffererTrade.setTradingPeer(sender); - - TradeTaskRunner taskRunner = new TradeTaskRunner(sellerAsOffererTrade, - () -> log.debug("taskRunner at handleTakerDepositPaymentRequestMessage completed"), - this::handleTaskRunnerFault); - - taskRunner.addTasks( - ProcessRequestPayDepositMessage.class, - VerifyTakerAccount.class, - CreateAndSignContract.class, - CreateAndSignDepositTx.class, - SendRequestPublishDepositTxMessage.class - ); - taskRunner.run(); - startTimeout(); - } - private void handle(DepositTxPublishedMessage tradeMessage) { stopTimeout(); processModel.setTradeMessage(tradeMessage); @@ -239,13 +191,7 @@ public class SellerAsOffererProtocol extends TradeProtocol implements SellerProt @Override protected void doHandleDecryptedMessage(TradeMessage tradeMessage, Peer sender) { - if (tradeMessage instanceof RequestIsOfferAvailableMessage) { - handle((RequestIsOfferAvailableMessage) tradeMessage, sender); - } - else if (tradeMessage instanceof RequestPayDepositMessage) { - handle((RequestPayDepositMessage) tradeMessage, sender); - } - else if (tradeMessage instanceof DepositTxPublishedMessage) { + if (tradeMessage instanceof DepositTxPublishedMessage) { handle((DepositTxPublishedMessage) tradeMessage); } else if (tradeMessage instanceof FiatTransferStartedMessage) { diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/RequestPayDepositMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/RequestPayDepositMessage.java index 57adfdd351..a4608453fa 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/RequestPayDepositMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/messages/RequestPayDepositMessage.java @@ -37,6 +37,7 @@ public class RequestPayDepositMessage extends TradeMessage implements Serializab public final List buyerConnectedOutputsForAllInputs; public final List buyerOutputs; public final byte[] buyerTradeWalletPubKey; + public final boolean isInitialRequest; public final PubKeyRing buyerPubKeyRing; public final FiatAccount buyerFiatAccount; public final String buyerAccountId; @@ -44,6 +45,7 @@ public class RequestPayDepositMessage extends TradeMessage implements Serializab public RequestPayDepositMessage(String tradeId, Coin tradeAmount, + boolean isInitialRequest, List buyerConnectedOutputsForAllInputs, List buyerOutputs, byte[] buyerTradeWalletPubKey, @@ -52,6 +54,7 @@ public class RequestPayDepositMessage extends TradeMessage implements Serializab String buyerAccountId) { super(tradeId); this.tradeAmount = tradeAmount; + this.isInitialRequest = isInitialRequest; this.buyerPubKeyRing = buyerPubKeyRing; this.buyerConnectedOutputsForAllInputs = buyerConnectedOutputsForAllInputs; this.buyerOutputs = buyerOutputs; diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendRequestPayDepositMessage.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendRequestPayDepositMessage.java index 7bc5667ca1..72121e19a7 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendRequestPayDepositMessage.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SendRequestPayDepositMessage.java @@ -19,6 +19,7 @@ package io.bitsquare.trade.protocol.trade.tasks.buyer; 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.RequestPayDepositMessage; @@ -37,9 +38,11 @@ public class SendRequestPayDepositMessage extends TradeTask { @Override protected void doRun() { try { + boolean isInitialRequest = trade instanceof BuyerAsTakerTrade; RequestPayDepositMessage tradeMessage = new RequestPayDepositMessage( processModel.getId(), trade.getTradeAmount(), + isInitialRequest, processModel.getConnectedOutputsForAllInputs(), processModel.getOutputs(), processModel.getTradeWalletPubKey(), diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTx.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTx.java index a510588d1c..0db201b5ce 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTx.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/buyer/SignAndPublishDepositTx.java @@ -66,14 +66,11 @@ public class SignAndPublishDepositTx extends TradeTask { trade.setDepositTx(transaction); - if (trade instanceof TakerTrade) { + trade.setLifeCycleState(Trade.LifeCycleState.PENDING); + if (trade instanceof TakerTrade) trade.setProcessState(TakerTradeState.ProcessState.DEPOSIT_PUBLISHED); - trade.setLifeCycleState(TakerTradeState.LifeCycleState.PENDING); - } - else if (trade instanceof OffererTrade) { + else if (trade instanceof OffererTrade) trade.setProcessState(OffererTradeState.ProcessState.DEPOSIT_PUBLISHED); - trade.setLifeCycleState(OffererTradeState.LifeCycleState.PENDING); - } trade.setTakeOfferDate(new Date()); @@ -95,7 +92,7 @@ public class SignAndPublishDepositTx extends TradeTask { trade.setThrowable(t); if (trade instanceof OffererTrade) - trade.setLifeCycleState(OffererTradeState.LifeCycleState.OFFER_OPEN); + trade.setLifeCycleState(Trade.LifeCycleState.PREPARATION); failed(t); } diff --git a/core/src/main/java/io/bitsquare/trade/states/OffererTradeState.java b/core/src/main/java/io/bitsquare/trade/states/OffererTradeState.java index cc4a4e0de0..1183c714c7 100644 --- a/core/src/main/java/io/bitsquare/trade/states/OffererTradeState.java +++ b/core/src/main/java/io/bitsquare/trade/states/OffererTradeState.java @@ -23,19 +23,10 @@ import org.slf4j.LoggerFactory; public class OffererTradeState { private static final Logger log = LoggerFactory.getLogger(OffererTradeState.class); - public enum LifeCycleState implements TradeState.LifeCycleState { - OFFER_OPEN, - OFFER_RESERVED, - OFFER_CANCELED, - PENDING, - COMPLETED, - FAILED - } - public enum ProcessState implements TradeState.ProcessState { UNDEFINED, DEPOSIT_PUBLISHED, - DEPOSIT_CONFIRMED, + DEPOSIT_CONFIRMED, FIAT_PAYMENT_STARTED, @@ -43,7 +34,7 @@ public class OffererTradeState { PAYOUT_FINALIZED, PAYOUT_BROAD_CASTED, - PAYOUT_BROAD_CASTED_FAILED, + PAYOUT_BROAD_CASTED_FAILED, MESSAGE_SENDING_FAILED, TIMEOUT, diff --git a/core/src/main/java/io/bitsquare/trade/states/StateUtil.java b/core/src/main/java/io/bitsquare/trade/states/StateUtil.java index c575998f8c..98726e6822 100644 --- a/core/src/main/java/io/bitsquare/trade/states/StateUtil.java +++ b/core/src/main/java/io/bitsquare/trade/states/StateUtil.java @@ -36,6 +36,6 @@ public class StateUtil { public static void setOfferOpenState(Trade trade) { if (trade instanceof OffererTrade) - trade.setLifeCycleState(OffererTradeState.LifeCycleState.OFFER_OPEN); + trade.setLifeCycleState(Trade.LifeCycleState.PREPARATION); } } diff --git a/core/src/main/java/io/bitsquare/trade/states/TakerTradeState.java b/core/src/main/java/io/bitsquare/trade/states/TakerTradeState.java index b9dbe3c666..258fdc48ff 100644 --- a/core/src/main/java/io/bitsquare/trade/states/TakerTradeState.java +++ b/core/src/main/java/io/bitsquare/trade/states/TakerTradeState.java @@ -23,12 +23,6 @@ import org.slf4j.LoggerFactory; public class TakerTradeState { private static final Logger log = LoggerFactory.getLogger(TakerTradeState.class); - public enum LifeCycleState implements TradeState.LifeCycleState { - PENDING, - COMPLETED, - FAILED - } - public enum ProcessState implements TradeState.ProcessState { UNDEFINED, TAKE_OFFER_FEE_TX_CREATED, diff --git a/core/src/main/java/io/bitsquare/trade/states/TradeState.java b/core/src/main/java/io/bitsquare/trade/states/TradeState.java index c6965858d8..ef09c1a5b8 100644 --- a/core/src/main/java/io/bitsquare/trade/states/TradeState.java +++ b/core/src/main/java/io/bitsquare/trade/states/TradeState.java @@ -23,9 +23,6 @@ import org.slf4j.LoggerFactory; public class TradeState { private static final Logger log = LoggerFactory.getLogger(TradeState.class); - public interface LifeCycleState { - } - public interface ProcessState { } } diff --git a/core/src/test/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocolTest.java b/core/src/test/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocolTest.java index eca75daaa1..aa75fe8da4 100644 --- a/core/src/test/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocolTest.java +++ b/core/src/test/java/io/bitsquare/trade/protocol/placeoffer/PlaceOfferProtocolTest.java @@ -18,10 +18,10 @@ package io.bitsquare.trade.protocol.placeoffer; import io.bitsquare.btc.WalletService; -import io.bitsquare.offer.OfferBookService; import io.bitsquare.p2p.MessageService; import io.bitsquare.p2p.tomp2p.BootstrappedPeerBuilder; import io.bitsquare.p2p.tomp2p.TomP2PNode; +import io.bitsquare.trade.offer.OfferBookService; import org.bitcoinj.core.Address; diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java b/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java index 1a132c9c20..98d1f671ad 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareAppModule.java @@ -25,12 +25,12 @@ import io.bitsquare.crypto.CryptoModule; import io.bitsquare.crypto.KeyRing; import io.bitsquare.crypto.KeyStorage; import io.bitsquare.gui.GuiModule; -import io.bitsquare.offer.OfferModule; -import io.bitsquare.offer.tomp2p.TomP2POfferModule; import io.bitsquare.p2p.P2PModule; import io.bitsquare.p2p.tomp2p.TomP2PModule; import io.bitsquare.storage.Storage; import io.bitsquare.trade.TradeModule; +import io.bitsquare.trade.offer.OfferModule; +import io.bitsquare.trade.offer.tomp2p.TomP2POfferModule; import io.bitsquare.user.AccountSettings; import io.bitsquare.user.Preferences; import io.bitsquare.user.User; diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java index 5048fc9686..2a838cd5c5 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -31,6 +31,7 @@ import io.bitsquare.p2p.BootstrapState; import io.bitsquare.p2p.ClientNode; import io.bitsquare.trade.Trade; import io.bitsquare.trade.TradeManager; +import io.bitsquare.trade.offer.OpenOfferManager; import io.bitsquare.user.User; import com.google.inject.Inject; @@ -91,12 +92,13 @@ class MainViewModel implements ViewModel { private final ArbitrationRepository arbitrationRepository; private final ClientNode clientNode; private final TradeManager tradeManager; + private OpenOfferManager openOfferManager; private final UpdateProcess updateProcess; private final BSFormatter formatter; @Inject public MainViewModel(User user, KeyRing keyRing, WalletService walletService, ArbitrationRepository arbitrationRepository, ClientNode clientNode, - TradeManager tradeManager, BitcoinNetwork bitcoinNetwork, UpdateProcess updateProcess, + TradeManager tradeManager, OpenOfferManager openOfferManager, BitcoinNetwork bitcoinNetwork, UpdateProcess updateProcess, BSFormatter formatter) { this.user = user; this.keyRing = keyRing; @@ -104,6 +106,7 @@ class MainViewModel implements ViewModel { this.arbitrationRepository = arbitrationRepository; this.clientNode = clientNode; this.tradeManager = tradeManager; + this.openOfferManager = openOfferManager; this.updateProcess = updateProcess; this.formatter = formatter; @@ -211,6 +214,7 @@ class MainViewModel implements ViewModel { log.debug("loadAllArbitrators"); arbitrationRepository.loadAllArbitrators(); tradeManager.onAllServicesInitialized(); + openOfferManager.onAllServicesInitialized(); } private void applyUpdateState(UpdateProcess.State state) { diff --git a/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java b/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java index 87fdeb6e40..e9eeab1c43 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/debug/DebugView.java @@ -20,9 +20,9 @@ package io.bitsquare.gui.main.debug; import io.bitsquare.common.taskrunner.Task; import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.InitializableView; -import io.bitsquare.trade.protocol.availability.CheckOfferAvailabilityProtocol; -import io.bitsquare.trade.protocol.availability.tasks.ProcessReportOfferAvailabilityMessage; -import io.bitsquare.trade.protocol.availability.tasks.SendRequestIsOfferAvailableMessage; +import io.bitsquare.trade.protocol.availability.OfferAvailabilityProtocol; +import io.bitsquare.trade.protocol.availability.tasks.ProcessOfferAvailabilityResponse; +import io.bitsquare.trade.protocol.availability.tasks.SendOfferAvailabilityRequest; import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol; import io.bitsquare.trade.protocol.placeoffer.tasks.AddOfferToRemoteOfferBook; import io.bitsquare.trade.protocol.placeoffer.tasks.BroadcastCreateOfferFeeTx; @@ -80,10 +80,10 @@ public class DebugView extends InitializableView { final ObservableList items = FXCollections.observableArrayList(Arrays.asList( /*---- Protocol ----*/ - CheckOfferAvailabilityProtocol.class, + OfferAvailabilityProtocol.class, io.bitsquare.trade.protocol.availability.tasks.GetPeerAddress.class, - SendRequestIsOfferAvailableMessage.class, - ProcessReportOfferAvailabilityMessage.class, + SendOfferAvailabilityRequest.class, + ProcessOfferAvailabilityResponse.class, Boolean.class, /* used as seperator*/ diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java index b822b278fa..dd144aa788 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java @@ -24,6 +24,7 @@ import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.GUIUtil; import io.bitsquare.trade.TradeManager; +import io.bitsquare.trade.offer.OpenOfferManager; import org.bitcoinj.core.Coin; @@ -51,13 +52,15 @@ public class ReservedView extends ActivatableViewAndModel { private final WalletService walletService; private final TradeManager tradeManager; + private OpenOfferManager openOfferManager; private final BSFormatter formatter; private final ObservableList addressList = FXCollections.observableArrayList(); @Inject - private ReservedView(WalletService walletService, TradeManager tradeManager, BSFormatter formatter) { + private ReservedView(WalletService walletService, TradeManager tradeManager, OpenOfferManager openOfferManager, BSFormatter formatter) { this.walletService = walletService; this.tradeManager = tradeManager; + this.openOfferManager = openOfferManager; this.formatter = formatter; } @@ -94,8 +97,8 @@ public class ReservedView extends ActivatableViewAndModel { private void fillList() { addressList.clear(); - addressList.addAll(Stream.concat(tradeManager.getOpenOfferTrades().stream(), tradeManager.getPendingTrades().stream()) - .map(trade -> new ReservedListItem(walletService.getAddressEntry(trade.getId()), walletService, formatter)) + addressList.addAll(Stream.concat(openOfferManager.getOpenOffers().stream(), tradeManager.getPendingTrades().stream()) + .map(tradable -> new ReservedListItem(walletService.getAddressEntry(tradable.getOffer().getId()), walletService, formatter)) .collect(Collectors.toList())); // List addressEntryList = walletService.getAddressEntryList(); diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java index ee86f4988b..cc82d4a863 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java @@ -28,6 +28,7 @@ import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.GUIUtil; import io.bitsquare.trade.TradeManager; +import io.bitsquare.trade.offer.OpenOfferManager; import org.bitcoinj.core.AddressFormatException; import org.bitcoinj.core.Coin; @@ -67,13 +68,15 @@ public class WithdrawalView extends ActivatableViewAndModel { private final WalletService walletService; private TradeManager tradeManager; + private OpenOfferManager openOfferManager; private final BSFormatter formatter; private final ObservableList addressList = FXCollections.observableArrayList(); @Inject - private WithdrawalView(WalletService walletService, TradeManager tradeManager, BSFormatter formatter) { + private WithdrawalView(WalletService walletService, TradeManager tradeManager, OpenOfferManager openOfferManager, BSFormatter formatter) { this.walletService = walletService; this.tradeManager = tradeManager; + this.openOfferManager = openOfferManager; this.formatter = formatter; } @@ -181,8 +184,8 @@ public class WithdrawalView extends ActivatableViewAndModel { addressList.clear(); List addressEntryList = walletService.getAddressEntryList(); - List reservedTrades = Stream.concat(tradeManager.getOpenOfferTrades().stream(), tradeManager.getPendingTrades().stream()) - .map(trade -> trade.getId()) + List reservedTrades = Stream.concat(openOfferManager.getOpenOffers().stream(), tradeManager.getPendingTrades().stream()) + .map(tradable -> tradable.getOffer().getId()) .collect(Collectors.toList()); addressList.addAll(addressEntryList.stream() diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java index 5c34c6bcf7..3ba40ff0e3 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java @@ -26,7 +26,7 @@ import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.offer.createoffer.CreateOfferView; import io.bitsquare.gui.main.offer.offerbook.OfferBookView; import io.bitsquare.gui.main.offer.takeoffer.TakeOfferView; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import org.bitcoinj.core.Coin; import org.bitcoinj.utils.Fiat; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java index 24b81d5536..46e82a2dbf 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java @@ -28,8 +28,8 @@ import io.bitsquare.gui.common.model.Activatable; import io.bitsquare.gui.common.model.DataModel; import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.locale.Country; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.TradeManager; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.offer.OpenOfferManager; import io.bitsquare.user.AccountSettings; import io.bitsquare.user.Preferences; import io.bitsquare.user.User; @@ -67,7 +67,7 @@ import static com.google.common.base.Preconditions.checkNotNull; class CreateOfferDataModel implements Activatable, DataModel { private static final Logger log = LoggerFactory.getLogger(CreateOfferDataModel.class); - private final TradeManager tradeManager; + private OpenOfferManager openOfferManager; private final WalletService walletService; private final AccountSettings accountSettings; private final Preferences preferences; @@ -106,11 +106,10 @@ class CreateOfferDataModel implements Activatable, DataModel { // non private for testing @Inject - public CreateOfferDataModel(TradeManager tradeManager, WalletService walletService, ArbitratorService arbitratorService, + public CreateOfferDataModel(OpenOfferManager openOfferManager, WalletService walletService, ArbitratorService arbitratorService, AccountSettings accountSettings, Preferences preferences, User user, BSFormatter formatter) { - this.tradeManager = tradeManager; + this.openOfferManager = openOfferManager; this.walletService = walletService; - ArbitratorService arbitratorService1 = arbitratorService; this.accountSettings = accountSettings; this.preferences = preferences; this.formatter = formatter; @@ -163,9 +162,9 @@ class CreateOfferDataModel implements Activatable, DataModel { // no-op } - void placeOffer() { + void onPlaceOffer() { // data validation is done in the trade domain - tradeManager.placeOffer(offerId, + openOfferManager.onPlaceOffer(offerId, direction, priceAsFiat.get(), amountAsCoin.get(), diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java index 2baa5f22c0..3852651888 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferView.java @@ -38,7 +38,7 @@ import io.bitsquare.gui.main.portfolio.PortfolioView; import io.bitsquare.gui.main.portfolio.openoffer.OpenOffersView; import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.locale.BSResources; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import org.bitcoinj.core.Coin; import org.bitcoinj.utils.Fiat; @@ -141,7 +141,7 @@ public class CreateOfferView extends ActivatableViewAndModel item.getOffer().getId().equals(offer.getId())); diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookDataModel.java index 5b63c602d5..2c0802973b 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookDataModel.java @@ -25,8 +25,8 @@ import io.bitsquare.gui.common.model.DataModel; import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.locale.Country; import io.bitsquare.locale.CurrencyUtil; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.TradeManager; +import io.bitsquare.trade.offer.Offer; +import io.bitsquare.trade.offer.OpenOfferManager; import io.bitsquare.user.Preferences; import io.bitsquare.user.User; @@ -58,7 +58,7 @@ class OfferBookDataModel implements Activatable, DataModel { private final OfferBook offerBook; private final Preferences preferences; private final BSFormatter formatter; - private final TradeManager tradeManager; + private final OpenOfferManager openOfferManager; private final FilteredList filteredItems; private final SortedList sortedItems; @@ -77,9 +77,9 @@ class OfferBookDataModel implements Activatable, DataModel { @Inject - public OfferBookDataModel(User user, TradeManager tradeManager, OfferBook offerBook, Preferences preferences, + public OfferBookDataModel(User user, OpenOfferManager openOfferManager, OfferBook offerBook, Preferences preferences, BSFormatter formatter) { - this.tradeManager = tradeManager; + this.openOfferManager = openOfferManager; this.user = user; this.offerBook = offerBook; this.preferences = preferences; @@ -112,7 +112,7 @@ class OfferBookDataModel implements Activatable, DataModel { } void onCancelOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - tradeManager.onCancelOpenOffer(offer, resultHandler, errorMessageHandler); + openOfferManager.onCancelOpenOffer(offer, resultHandler, errorMessageHandler); } void calculateVolume() { @@ -210,7 +210,7 @@ class OfferBookDataModel implements Activatable, DataModel { } boolean isMyOffer(Offer offer) { - return tradeManager.isMyOffer(offer); + return openOfferManager.isMyOffer(offer); } Coin getAmountAsCoin() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookListItem.java b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookListItem.java index f0babadb3f..8ef07b45c4 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookListItem.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookListItem.java @@ -18,7 +18,7 @@ package io.bitsquare.gui.main.offer.offerbook; import io.bitsquare.locale.Country; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java index 3a7a09b9d7..2a8500e0bc 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java @@ -35,7 +35,7 @@ import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.gui.util.validation.OptionalBtcValidator; import io.bitsquare.gui.util.validation.OptionalFiatValidator; import io.bitsquare.locale.BSResources; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import java.util.ArrayList; import java.util.List; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java index 7facd46365..5dde1e3777 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java @@ -26,7 +26,7 @@ import io.bitsquare.gui.util.validation.InputValidator; import io.bitsquare.gui.util.validation.OptionalBtcValidator; import io.bitsquare.gui.util.validation.OptionalFiatValidator; import io.bitsquare.locale.BSResources; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import org.bitcoinj.core.Coin; import org.bitcoinj.utils.Fiat; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java index 2cf675199f..ea6177ef81 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferDataModel.java @@ -23,9 +23,9 @@ import io.bitsquare.btc.WalletService; import io.bitsquare.btc.listeners.BalanceListener; import io.bitsquare.gui.common.model.Activatable; import io.bitsquare.gui.common.model.DataModel; -import io.bitsquare.offer.Offer; import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.handlers.TakeOfferResultHandler; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.user.Preferences; import org.bitcoinj.core.Coin; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java index f4d573331c..11105bc13a 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferView.java @@ -36,7 +36,7 @@ import io.bitsquare.gui.main.portfolio.PortfolioView; import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesView; import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.locale.BSResources; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import org.bitcoinj.core.Coin; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java index 7c50e3e1e1..eb41ef8769 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/takeoffer/TakeOfferViewModel.java @@ -25,9 +25,9 @@ import io.bitsquare.gui.util.validation.BtcValidator; import io.bitsquare.gui.util.validation.InputValidator; import io.bitsquare.locale.BSResources; import io.bitsquare.locale.CurrencyUtil; -import io.bitsquare.offer.Offer; import io.bitsquare.trade.BuyerAsTakerTrade; import io.bitsquare.trade.SellerAsTakerTrade; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.states.TakerTradeState; import org.bitcoinj.core.Address; @@ -173,13 +173,13 @@ class TakeOfferViewModel extends ActivatableWithDataModel im log.debug("offer state = " + state); switch (state) { - case UNKNOWN: + case UNDEFINED: // TODO set spinner? break; case AVAILABLE: this.state.set(State.AMOUNT_SCREEN); break; - case RESERVED: + case NOT_AVAILABLE: if (takeOfferRequested) errorMessage.set("Take offer request failed because offer is not available anymore. " + "Maybe another trader has taken the offer in the meantime."); @@ -200,14 +200,14 @@ class TakeOfferViewModel extends ActivatableWithDataModel im errorMessage.set("You cannot take that offer because the offerer is offline."); takeOfferRequested = false; break; - case FAULT: + /* case FAULT: if (takeOfferRequested) errorMessage.set("Take offer request failed."); else errorMessage.set("The check for the offer availability failed."); takeOfferRequested = false; - break; + break;*/ default: log.error("Unhandled offer state: " + state); break; diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesDataModel.java index 929968a2ad..8a12cd9e97 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesDataModel.java @@ -19,10 +19,9 @@ package io.bitsquare.gui.main.portfolio.closedtrades; import io.bitsquare.gui.common.model.Activatable; import io.bitsquare.gui.common.model.DataModel; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.Trade; -import io.bitsquare.trade.TradeManager; -import io.bitsquare.user.User; +import io.bitsquare.trade.Tradable; +import io.bitsquare.trade.closed.ClosedTradableManager; +import io.bitsquare.trade.offer.Offer; import com.google.inject.Inject; @@ -34,16 +33,14 @@ import javafx.collections.ObservableList; class ClosedTradesDataModel implements Activatable, DataModel { - private final TradeManager tradeManager; - private final User user; + private final ClosedTradableManager closedTradableManager; private final ObservableList list = FXCollections.observableArrayList(); - private final ListChangeListener tradesListChangeListener; + private final ListChangeListener tradesListChangeListener; @Inject - public ClosedTradesDataModel(TradeManager tradeManager, User user) { - this.tradeManager = tradeManager; - this.user = user; + public ClosedTradesDataModel(ClosedTradableManager closedTradableManager) { + this.closedTradableManager = closedTradableManager; tradesListChangeListener = change -> applyList(); } @@ -51,12 +48,12 @@ class ClosedTradesDataModel implements Activatable, DataModel { @Override public void activate() { applyList(); - tradeManager.getClosedTrades().addListener(tradesListChangeListener); + closedTradableManager.getClosedTrades().addListener(tradesListChangeListener); } @Override public void deactivate() { - tradeManager.getClosedTrades().removeListener(tradesListChangeListener); + closedTradableManager.getClosedTrades().removeListener(tradesListChangeListener); } public ObservableList getList() { @@ -64,16 +61,16 @@ class ClosedTradesDataModel implements Activatable, DataModel { } public Offer.Direction getDirection(Offer offer) { - return tradeManager.isMyOffer(offer) ? offer.getDirection() : offer.getMirroredDirection(); + return closedTradableManager.wasMyOffer(offer) ? offer.getDirection() : offer.getMirroredDirection(); } private void applyList() { list.clear(); - list.addAll(tradeManager.getClosedTrades().stream().map(ClosedTradesListItem::new).collect(Collectors.toList())); + list.addAll(closedTradableManager.getClosedTrades().stream().map(ClosedTradesListItem::new).collect(Collectors.toList())); // we sort by date, earliest first - list.sort((o1, o2) -> o2.getTrade().getDate().compareTo(o1.getTrade().getDate())); + list.sort((o1, o2) -> o2.getTradable().getDate().compareTo(o1.getTradable().getDate())); } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesListItem.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesListItem.java index 0acfcb67f3..fbca1458b2 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesListItem.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesListItem.java @@ -17,22 +17,22 @@ package io.bitsquare.gui.main.portfolio.closedtrades; -import io.bitsquare.trade.Trade; +import io.bitsquare.trade.Tradable; /** * We could remove that wrapper if it is not needed for additional UI only fields. */ class ClosedTradesListItem { - private final Trade trade; + private final Tradable tradable; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// - ClosedTradesListItem(Trade trade) { - this.trade = trade; + ClosedTradesListItem(Tradable tradable) { + this.tradable = tradable; } @@ -40,7 +40,7 @@ class ClosedTradesListItem { // Getters /////////////////////////////////////////////////////////////////////////////////////////// - Trade getTrade() { - return trade; + Tradable getTradable() { + return tradable; } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java index 0d79441baa..1a3bc979be 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesViewModel.java @@ -20,15 +20,18 @@ package io.bitsquare.gui.main.portfolio.closedtrades; import io.bitsquare.gui.common.model.ActivatableWithDataModel; import io.bitsquare.gui.common.model.ViewModel; import io.bitsquare.gui.util.BSFormatter; -import io.bitsquare.trade.states.OffererTradeState; -import io.bitsquare.trade.states.TakerTradeState; -import io.bitsquare.trade.states.TradeState; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.offer.OpenOffer; import com.google.inject.Inject; import javafx.collections.ObservableList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + class ClosedTradesViewModel extends ActivatableWithDataModel implements ViewModel { + private static final Logger log = LoggerFactory.getLogger(ClosedTradesViewModel.class); private final BSFormatter formatter; @@ -45,34 +48,39 @@ class ClosedTradesViewModel extends ActivatableWithDataModel list = FXCollections.observableArrayList(); - private final ListChangeListener tradesListChangeListener; + private final ListChangeListener tradesListChangeListener; @Inject - public OpenOffersDataModel(TradeManager tradeManager, User user) { - this.tradeManager = tradeManager; - this.user = user; + public OpenOffersDataModel(OpenOfferManager openOfferManager) { + this.openOfferManager = openOfferManager; tradesListChangeListener = change -> applyList(); } @@ -57,16 +54,16 @@ class OpenOffersDataModel implements Activatable, DataModel { @Override public void activate() { applyList(); - tradeManager.getOpenOfferTrades().addListener(tradesListChangeListener); + openOfferManager.getOpenOffers().addListener(tradesListChangeListener); } @Override public void deactivate() { - tradeManager.getOpenOfferTrades().removeListener(tradesListChangeListener); + openOfferManager.getOpenOffers().removeListener(tradesListChangeListener); } - void onCancelOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - tradeManager.onCancelOpenOffer(offer, resultHandler, errorMessageHandler); + void onCancelOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + openOfferManager.onCancelOpenOffer(openOffer, resultHandler, errorMessageHandler); } @@ -75,13 +72,13 @@ class OpenOffersDataModel implements Activatable, DataModel { } public Offer.Direction getDirection(Offer offer) { - return tradeManager.isMyOffer(offer) ? offer.getDirection() : offer.getMirroredDirection(); + return openOfferManager.isMyOffer(offer) ? offer.getDirection() : offer.getMirroredDirection(); } private void applyList() { list.clear(); - list.addAll(tradeManager.getOpenOfferTrades().stream().map(OpenOfferListItem::new).collect(Collectors.toList())); + list.addAll(openOfferManager.getOpenOffers().stream().map(OpenOfferListItem::new).collect(Collectors.toList())); // we sort by date, earliest first list.sort((o1, o2) -> o2.getOffer().getCreationDate().compareTo(o1.getOffer().getCreationDate())); diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java index a7e61fc942..6dda28b77d 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersView.java @@ -25,7 +25,7 @@ import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.funds.FundsView; import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView; import io.bitsquare.gui.util.GUIUtil; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.OpenOffer; import javax.inject.Inject; @@ -69,8 +69,8 @@ public class OpenOffersView extends ActivatableViewAndModel { log.debug("Remove offer was successful"); Popups.openInfoPopup("You can withdraw the funds you paid in from the funds screens."); @@ -249,7 +249,7 @@ public class OpenOffersView extends ActivatableViewAndModel onCancelOpenOffer(item.getOffer())); + button.setOnAction(event -> onCancelOpenOffer(item.getOpenOffer())); setGraphic(button); } else { diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersViewModel.java index c7be0701e5..96e8ddb72b 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/openoffer/OpenOffersViewModel.java @@ -22,7 +22,7 @@ import io.bitsquare.common.handlers.ResultHandler; import io.bitsquare.gui.common.model.ActivatableWithDataModel; import io.bitsquare.gui.common.model.ViewModel; import io.bitsquare.gui.util.BSFormatter; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.OpenOffer; import com.google.inject.Inject; @@ -45,8 +45,8 @@ class OpenOffersViewModel extends ActivatableWithDataModel } - void onCancelOpenOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - dataModel.onCancelOpenOffer(offer, resultHandler, errorMessageHandler); + void onCancelOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { + dataModel.onCancelOpenOffer(openOffer, resultHandler, errorMessageHandler); } public ObservableList getList() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java index d43d9dceb7..7b215fb165 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -27,12 +27,12 @@ import io.bitsquare.gui.components.Popups; import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.portfolio.PortfolioView; import io.bitsquare.gui.main.portfolio.closedtrades.ClosedTradesView; -import io.bitsquare.offer.Offer; import io.bitsquare.trade.BuyerTrade; import io.bitsquare.trade.Contract; import io.bitsquare.trade.SellerTrade; import io.bitsquare.trade.Trade; import io.bitsquare.trade.TradeManager; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.states.TradeState; import io.bitsquare.user.User; diff --git a/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java b/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java index ed716a244d..7bad50c980 100644 --- a/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java +++ b/gui/src/main/java/io/bitsquare/gui/util/BSFormatter.java @@ -23,7 +23,7 @@ import io.bitsquare.locale.BSResources; import io.bitsquare.locale.Country; import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.LanguageUtil; -import io.bitsquare.offer.Offer; +import io.bitsquare.trade.offer.Offer; import io.bitsquare.user.User; import org.bitcoinj.core.Coin;