mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 18:03:12 +01:00
refactoring trade protocol
This commit is contained in:
parent
7e55b7325a
commit
5da272bdbf
@ -166,6 +166,7 @@ public class MainController implements Initializable, NavigationController
|
||||
return childController;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -173,7 +174,8 @@ public class MainController implements Initializable, NavigationController
|
||||
private void init()
|
||||
{
|
||||
messageFacade.init();
|
||||
messageFacade.addTakeOfferRequestListener(this::onTakeOfferRequested);
|
||||
|
||||
trading.addTakeOfferRequestListener(this::onTakeOfferRequested);
|
||||
|
||||
walletFacade.addDownloadListener(new WalletFacade.DownloadListener()
|
||||
{
|
||||
|
@ -194,7 +194,7 @@ public class OrderBookController implements Initializable, ChildController
|
||||
|
||||
private boolean isRegistered()
|
||||
{
|
||||
return user.getAccountID() != null;
|
||||
return user.getAccountId() != null;
|
||||
}
|
||||
|
||||
private boolean areSettingsValid()
|
||||
|
@ -17,7 +17,8 @@ import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.Trading;
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocolListener;
|
||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocol;
|
||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocolListener;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
@ -173,8 +174,6 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
amountTextField.setEditable(false);
|
||||
trading.takeOffer(amount, offer, new TakerAsSellerProtocolListener()
|
||||
{
|
||||
|
||||
|
||||
@Override
|
||||
public void onDepositTxPublished(String depositTxId)
|
||||
{
|
||||
@ -197,7 +196,7 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTradeCompleted(Trade trade, String payoutTxId)
|
||||
public void onPayoutTxPublished(Trade trade, String payoutTxId)
|
||||
{
|
||||
accordion.setExpandedPane(summaryTitledPane);
|
||||
summaryPaidTextField.setText(BtcFormatter.formatSatoshis(trade.getTradeAmount()));
|
||||
@ -207,10 +206,32 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
summaryDepositTxIdTextField.setText(depositTxId);
|
||||
summaryPayoutTxIdTextField.setText(payoutTxId);
|
||||
}
|
||||
}, (task) -> {
|
||||
//log.trace(task.toString());
|
||||
}, throwable -> {
|
||||
log.error(throwable.toString());
|
||||
|
||||
@Override
|
||||
public void onFault(Throwable throwable, TakerAsSellerProtocol.State state)
|
||||
{
|
||||
log.error("Error while executing trade process at state: " + state + " / " + throwable);
|
||||
Popups.openErrorPopup("Error while executing trade process", "Error while executing trade process at state: " + state + " / " + throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWaitingForPeerResponse(TakerAsSellerProtocol.State state)
|
||||
{
|
||||
log.debug("Waiting for peers response at state " + state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted(TakerAsSellerProtocol.State state)
|
||||
{
|
||||
log.debug("Trade protocol completed at state " + state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTakeOfferRequestRejected(Trade trade)
|
||||
{
|
||||
log.error("Take offer request rejected");
|
||||
Popups.openErrorPopup("Take offer request rejected", "Your take offer request has been rejected. It might be that the offerer got another request shortly before your request arrived.");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -220,7 +241,7 @@ public class TakerOfferController implements Initializable, ChildController
|
||||
@FXML
|
||||
public void onReceivedFiat()
|
||||
{
|
||||
trading.releaseBTC(tradeId);
|
||||
trading.onFiatReceived(tradeId);
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
@ -172,7 +172,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
gridPane.add(isOnlineCheckerHolder, 2, row);
|
||||
|
||||
//TODO
|
||||
messageFacade.pingPeer(offer.getMessagePubKeyAsHex());
|
||||
// messageFacade.pingPeer(offer.getMessagePubKeyAsHex());
|
||||
checkOnlineStatusTimer = Utilities.setTimeout(1000, (AnimationTimer animationTimer) -> {
|
||||
setIsOnlineStatus(true);
|
||||
//noinspection ReturnOfNull
|
||||
@ -316,7 +316,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTradeCompleted(String hashAsString)
|
||||
public void onPayoutTxPublished(String hashAsString)
|
||||
{
|
||||
showSummary(hashAsString);
|
||||
}
|
||||
@ -359,7 +359,7 @@ public class TakerTradeController implements Initializable, ChildController
|
||||
private void releaseBTC()
|
||||
{
|
||||
processStepBar.next();
|
||||
trading.releaseBTC(trade.getId());
|
||||
trading.onFiatReceived(trade.getId());
|
||||
|
||||
nextButton.setText("Close");
|
||||
nextButton.setOnAction(e -> close());
|
||||
|
@ -7,7 +7,6 @@ import io.bitsquare.gui.NavigationController;
|
||||
import io.bitsquare.gui.util.Icons;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trading;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -110,13 +109,7 @@ public class OfferController implements Initializable, ChildController, Hibernat
|
||||
|
||||
private void removeOffer(OfferListItem offerListItem)
|
||||
{
|
||||
try
|
||||
{
|
||||
trading.removeOffer(offerListItem.getOffer());
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
trading.removeOffer(offerListItem.getOffer());
|
||||
offerListItems.remove(offerListItem);
|
||||
}
|
||||
|
||||
|
@ -152,20 +152,16 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||
}
|
||||
});
|
||||
|
||||
trading.getNewTradeProperty().addListener(new ChangeListener<String>()
|
||||
{
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends String> observableValue, String oldTradeUid, String newTradeUid)
|
||||
{
|
||||
Trade newTrade = trading.getTrades().get(newTradeUid);
|
||||
trading.getNewTradeProperty().addListener((observableValue, oldTradeId, newTradeId) -> {
|
||||
Trade newTrade = trading.getTrade(newTradeId);
|
||||
if (newTrade != null)
|
||||
tradeItems.add(new PendingTradesListItem(newTrade));
|
||||
}
|
||||
});
|
||||
|
||||
initCopyIcons();
|
||||
|
||||
// select
|
||||
Optional<PendingTradesListItem> currentTradeItemOptional = tradeItems.stream().filter((e) -> e.getTrade().getId().equals(trading.getCurrentPendingTrade().getId())).findFirst();
|
||||
Optional<PendingTradesListItem> currentTradeItemOptional = tradeItems.stream().filter((e) -> e.getTrade().getId().equals(trading.getPendingTrade().getId())).findFirst();
|
||||
if (currentTradeItemOptional.isPresent())
|
||||
openTradesTable.getSelectionModel().select(currentTradeItemOptional.get());
|
||||
|
||||
@ -183,7 +179,7 @@ public class PendingTradeController implements Initializable, ChildController, H
|
||||
|
||||
public void bankTransferInited()
|
||||
{
|
||||
trading.onUIEventBankTransferInited(currentTrade.getId());
|
||||
trading.bankTransferInited(currentTrade.getId());
|
||||
bankTransferInitedButton.setDisable(true);
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,6 @@ import com.google.inject.Inject;
|
||||
import io.bitsquare.BitSquare;
|
||||
import io.bitsquare.msg.listeners.*;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||
import io.bitsquare.trade.payment.offerer.messages.*;
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocol;
|
||||
import io.bitsquare.trade.payment.taker.listeners.GetPeerAddressListener;
|
||||
import io.bitsquare.trade.payment.taker.messages.PayoutTxPublishedMessage;
|
||||
import io.bitsquare.trade.payment.taker.messages.RequestOffererPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.payment.taker.messages.RequestTakeOfferMessage;
|
||||
import io.bitsquare.trade.payment.taker.messages.TakeOfferFeePayedMessage;
|
||||
import io.bitsquare.user.Arbitrator;
|
||||
import io.bitsquare.util.DSAKeyUtil;
|
||||
import io.bitsquare.util.FileUtil;
|
||||
@ -29,7 +21,6 @@ import net.tomp2p.p2p.Peer;
|
||||
import net.tomp2p.p2p.PeerMaker;
|
||||
import net.tomp2p.peers.Number160;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import net.tomp2p.rpc.ObjectDataReply;
|
||||
import net.tomp2p.storage.Data;
|
||||
import net.tomp2p.storage.StorageDisk;
|
||||
import net.tomp2p.utils.Utils;
|
||||
@ -44,19 +35,18 @@ import org.slf4j.LoggerFactory;
|
||||
@SuppressWarnings({"EmptyMethod", "ConstantConditions"})
|
||||
public class MessageFacade
|
||||
{
|
||||
private static final String PING = "ping";
|
||||
private static final String PONG = "pong";
|
||||
private static final Logger log = LoggerFactory.getLogger(MessageFacade.class);
|
||||
// private static final String PING = "ping";
|
||||
// private static final String PONG = "pong";
|
||||
private static final int MASTER_PEER_PORT = 5000;
|
||||
|
||||
private final List<OrderBookListener> orderBookListeners = new ArrayList<>();
|
||||
private final List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>();
|
||||
private final List<ArbitratorListener> arbitratorListeners = new ArrayList<>();
|
||||
|
||||
private final Map<String, TakerAsSellerProtocol> takerPaymentProtocols = new HashMap<>();
|
||||
private final Map<String, OffererAsBuyerProtocol> offererAsBuyerProtocols = new HashMap<>();
|
||||
private final List<IncomingTradeMessageListener> incomingTradeMessageListeners = new ArrayList<>();
|
||||
|
||||
private final List<PingPeerListener> pingPeerListeners = new ArrayList<>();
|
||||
|
||||
// private final List<PingPeerListener> pingPeerListeners = new ArrayList<>();
|
||||
private final BooleanProperty isDirty = new SimpleBooleanProperty(false);
|
||||
private Peer myPeer;
|
||||
|
||||
@ -71,17 +61,9 @@ public class MessageFacade
|
||||
@Inject
|
||||
public MessageFacade()
|
||||
{
|
||||
/* try
|
||||
{
|
||||
masterPeer = BootstrapMasterPeer.GET_INSTANCE(MASTER_PEER_PORT);
|
||||
} catch (Exception e)
|
||||
{
|
||||
if (masterPeer != null)
|
||||
masterPeer.shutdown();
|
||||
System.err.println("masterPeer already instantiated by another app. " + e.getMessage());
|
||||
} */
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -115,6 +97,146 @@ public class MessageFacade
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Find peer address
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void getPeerAddress(String pubKeyAsHex, GetPeerAddressListener listener)
|
||||
{
|
||||
final Number160 location = Number160.createHash(pubKeyAsHex);
|
||||
final FutureDHT getPeerAddressFuture = myPeer.get(location).start();
|
||||
getPeerAddressFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||
{
|
||||
if (baseFuture.isSuccess() && getPeerAddressFuture.getData() != null)
|
||||
{
|
||||
final PeerAddress peerAddress = (PeerAddress) getPeerAddressFuture.getData().getObject();
|
||||
Platform.runLater(() -> listener.onResult(peerAddress));
|
||||
}
|
||||
else
|
||||
{
|
||||
Platform.runLater(() -> listener.onFailed());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Publish offer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void addOffer(Offer offer) throws IOException
|
||||
{
|
||||
log.trace("addOffer");
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
final Number160 contentKey = Number160.createHash(offer.getId());
|
||||
final Data offerData = new Data(offer);
|
||||
//offerData.setTTLSeconds(5);
|
||||
final FutureDHT addFuture = myPeer.put(locationKey).setData(contentKey, offerData).start();
|
||||
//final FutureDHT addFuture = myPeer.add(locationKey).setData(offerData).start();
|
||||
addFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception
|
||||
{
|
||||
Platform.runLater(() -> onOfferAdded(offerData, future.isSuccess(), locationKey));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onOfferAdded(Data offerData, boolean success, Number160 locationKey)
|
||||
{
|
||||
log.trace("onOfferAdded");
|
||||
setDirty(locationKey);
|
||||
orderBookListeners.stream().forEach(orderBookListener -> orderBookListener.onOfferAdded(offerData, success));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Get offers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void getOffers(String currency)
|
||||
{
|
||||
log.trace("getOffers");
|
||||
final Number160 locationKey = Number160.createHash(currency);
|
||||
final FutureDHT getOffersFuture = myPeer.get(locationKey).setAll().start();
|
||||
getOffersFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception
|
||||
{
|
||||
final Map<Number160, Data> dataMap = getOffersFuture.getDataMap();
|
||||
Platform.runLater(() -> onOffersReceived(dataMap, future.isSuccess()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onOffersReceived(Map<Number160, Data> dataMap, boolean success)
|
||||
{
|
||||
log.trace("onOffersReceived");
|
||||
orderBookListeners.stream().forEach(orderBookListener -> orderBookListener.onOffersReceived(dataMap, success));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Remove offer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void removeOffer(Offer offer)
|
||||
{
|
||||
log.trace("removeOffer");
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
Number160 contentKey = Number160.createHash(offer.getId());
|
||||
log.debug("removeOffer");
|
||||
FutureDHT removeFuture = myPeer.remove(locationKey).setReturnResults().setContentKey(contentKey).start();
|
||||
removeFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception
|
||||
{
|
||||
Platform.runLater(() -> onOfferRemoved(removeFuture.getData(), future.isSuccess(), locationKey));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onOfferRemoved(Data data, boolean success, Number160 locationKey)
|
||||
{
|
||||
log.trace("onOfferRemoved");
|
||||
setDirty(locationKey);
|
||||
orderBookListeners.stream().forEach(orderBookListener -> orderBookListener.onOfferRemoved(data, success));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade process
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void sendTradeMessage(PeerAddress peerAddress, TradeMessage tradeMessage, OutgoingTradeMessageListener listener)
|
||||
{
|
||||
final PeerConnection peerConnection = myPeer.createPeerConnection(peerAddress, 10);
|
||||
final FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start();
|
||||
sendFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||
{
|
||||
if (sendFuture.isSuccess())
|
||||
Platform.runLater(() -> listener.onResult());
|
||||
else
|
||||
Platform.runLater(() -> listener.onFailed());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Reputation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setupReputationRoot() throws IOException
|
||||
{
|
||||
String pubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(getPubKey()); // out message ID
|
||||
@ -149,6 +271,7 @@ public class MessageFacade
|
||||
myPeer.put(locationKey).setData(contentKey, reputationData).start();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Arbitrators
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -199,100 +322,11 @@ public class MessageFacade
|
||||
arbitratorListener.onArbitratorsReceived(dataMap, success);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Publish offer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//TODO use Offer and do proper serialisation here
|
||||
public void addOffer(Offer offer) throws IOException
|
||||
{
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
final Number160 contentKey = Number160.createHash(offer.getId());
|
||||
final Data offerData = new Data(offer);
|
||||
//offerData.setTTLSeconds(5);
|
||||
final FutureDHT addFuture = myPeer.put(locationKey).setData(contentKey, offerData).start();
|
||||
//final FutureDHT addFuture = myPeer.add(locationKey).setData(offerData).start();
|
||||
addFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception
|
||||
{
|
||||
Platform.runLater(() -> onOfferAdded(offerData, future.isSuccess(), locationKey));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onOfferAdded(Data offerData, boolean success, Number160 locationKey)
|
||||
{
|
||||
setDirty(locationKey);
|
||||
|
||||
for (OrderBookListener orderBookListener : orderBookListeners)
|
||||
orderBookListener.onOfferAdded(offerData, success);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Get offers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void getOffers(String currency)
|
||||
{
|
||||
final Number160 locationKey = Number160.createHash(currency);
|
||||
final FutureDHT getOffersFuture = myPeer.get(locationKey).setAll().start();
|
||||
getOffersFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception
|
||||
{
|
||||
final Map<Number160, Data> dataMap = getOffersFuture.getDataMap();
|
||||
Platform.runLater(() -> onOffersReceived(dataMap, future.isSuccess()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onOffersReceived(Map<Number160, Data> dataMap, boolean success)
|
||||
{
|
||||
for (OrderBookListener orderBookListener : orderBookListeners)
|
||||
orderBookListener.onOffersReceived(dataMap, success);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Remove offer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void removeOffer(Offer offer)
|
||||
{
|
||||
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
|
||||
Number160 contentKey = Number160.createHash(offer.getId());
|
||||
log.debug("removeOffer");
|
||||
FutureDHT removeFuture = myPeer.remove(locationKey).setReturnResults().setContentKey(contentKey).start();
|
||||
removeFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture future) throws Exception
|
||||
{
|
||||
Data data = removeFuture.getData();
|
||||
Platform.runLater(() -> onOfferRemoved(data, future.isSuccess(), locationKey));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onOfferRemoved(Data data, boolean success, Number160 locationKey)
|
||||
{
|
||||
log.debug("onOfferRemoved");
|
||||
setDirty(locationKey);
|
||||
|
||||
for (OrderBookListener orderBookListener : orderBookListeners)
|
||||
orderBookListener.onOfferRemoved(data, success);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Check dirty flag for a location key
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// TODO just temp...
|
||||
public BooleanProperty getIsDirtyProperty()
|
||||
{
|
||||
return isDirty;
|
||||
@ -312,11 +346,7 @@ public class MessageFacade
|
||||
{
|
||||
Object object = data.getObject();
|
||||
if (object instanceof Long)
|
||||
{
|
||||
final long lastTimeStamp = (Long) object;
|
||||
//System.out.println("getDirtyFlag " + lastTimeStamp);
|
||||
Platform.runLater(() -> onGetDirtyFlag(lastTimeStamp));
|
||||
}
|
||||
Platform.runLater(() -> onGetDirtyFlag((Long) object));
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,149 +456,12 @@ public class MessageFacade
|
||||
}
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Find peer address
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public void getPeerAddress(String pubKeyAsHex, GetPeerAddressListener listener)
|
||||
{
|
||||
final Number160 location = Number160.createHash(pubKeyAsHex);
|
||||
final FutureDHT getPeerAddressFuture = myPeer.get(location).start();
|
||||
getPeerAddressFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||
{
|
||||
if (baseFuture.isSuccess() && getPeerAddressFuture.getData() != null)
|
||||
{
|
||||
final PeerAddress peerAddress = (PeerAddress) getPeerAddressFuture.getData().getObject();
|
||||
Platform.runLater(() -> listener.onResult(peerAddress));
|
||||
}
|
||||
else
|
||||
{
|
||||
Platform.runLater(() -> listener.onFailed());
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade process
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void sendTradingMessage(final PeerAddress peerAddress, TradeMessage tradeMessage, TradeMessageListener listener)
|
||||
{
|
||||
final PeerConnection peerConnection = myPeer.createPeerConnection(peerAddress, 10);
|
||||
final FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start();
|
||||
sendFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||
{
|
||||
if (sendFuture.isSuccess())
|
||||
{
|
||||
Platform.runLater(() -> listener.onResult());
|
||||
}
|
||||
else
|
||||
{
|
||||
Platform.runLater(() -> listener.onFailed());
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public void sendTradeMessage(PeerAddress peerAddress, TradeMessage tradeMessage, TradeMessageListener listener)
|
||||
{
|
||||
final PeerConnection peerConnection = myPeer.createPeerConnection(peerAddress, 10);
|
||||
final FutureResponse sendFuture = myPeer.sendDirect(peerConnection).setObject(tradeMessage).start();
|
||||
sendFuture.addListener(new BaseFutureAdapter<BaseFuture>()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(BaseFuture baseFuture) throws Exception
|
||||
{
|
||||
if (sendFuture.isSuccess())
|
||||
{
|
||||
Platform.runLater(() -> onSendTradingMessageResult(listener));
|
||||
}
|
||||
else
|
||||
{
|
||||
Platform.runLater(() -> onSendTradingMessageFailed(listener));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void onSendTradingMessageResult(TradeMessageListener listener)
|
||||
{
|
||||
listener.onResult();
|
||||
}
|
||||
|
||||
private void onSendTradingMessageFailed(TradeMessageListener listener)
|
||||
{
|
||||
listener.onFailed();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Process incoming tradingMessage
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void processTradingMessage(TradeMessage tradeMessage, PeerAddress sender)
|
||||
{
|
||||
// log.trace("processTradingMessage TradeId " + tradeMessage.getTradeId());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getSimpleName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getCanonicalName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getTypeName());
|
||||
|
||||
if (tradeMessage instanceof RequestTakeOfferMessage)
|
||||
{
|
||||
takeOfferRequestListeners.stream().forEach(e -> e.onTakeOfferRequested(tradeMessage.getTradeId(), sender));
|
||||
}
|
||||
else if (tradeMessage instanceof AcceptTakeOfferRequestMessage)
|
||||
{
|
||||
takerPaymentProtocols.get(tradeMessage.getTradeId()).onAcceptTakeOfferRequestMessage();
|
||||
}
|
||||
else if (tradeMessage instanceof RejectTakeOfferRequestMessage)
|
||||
{
|
||||
takerPaymentProtocols.get(tradeMessage.getTradeId()).onRejectTakeOfferRequestMessage();
|
||||
}
|
||||
else if (tradeMessage instanceof TakeOfferFeePayedMessage)
|
||||
{
|
||||
offererAsBuyerProtocols.get(tradeMessage.getTradeId()).onTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof RequestTakerDepositPaymentMessage)
|
||||
{
|
||||
takerPaymentProtocols.get(tradeMessage.getTradeId()).onRequestTakerDepositPaymentMessage((RequestTakerDepositPaymentMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage)
|
||||
{
|
||||
offererAsBuyerProtocols.get(tradeMessage.getTradeId()).onRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof DepositTxPublishedMessage)
|
||||
{
|
||||
takerPaymentProtocols.get(tradeMessage.getTradeId()).onDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof BankTransferInitedMessage)
|
||||
{
|
||||
takerPaymentProtocols.get(tradeMessage.getTradeId()).onBankTransferInitedMessage((BankTransferInitedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof PayoutTxPublishedMessage)
|
||||
{
|
||||
offererAsBuyerProtocols.get(tradeMessage.getTradeId()).onPayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Ping peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
//TODO not working anymore...
|
||||
public void pingPeer(String publicKeyAsHex)
|
||||
/* public void pingPeer(String publicKeyAsHex)
|
||||
{
|
||||
Number160 location = Number160.createHash(publicKeyAsHex);
|
||||
final FutureDHT getPeerAddressFuture = myPeer.get(location).start();
|
||||
@ -587,8 +480,7 @@ public class MessageFacade
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private void onAddressFoundPingPeer(PeerAddress peerAddress)
|
||||
private void onAddressFoundPingPeer(PeerAddress peerAddress)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -626,16 +518,7 @@ public class MessageFacade
|
||||
for (PingPeerListener pingPeerListener : pingPeerListeners)
|
||||
pingPeerListener.onPingPeerResult(success);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Misc
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PublicKey getPubKey()
|
||||
{
|
||||
return keyPair.getPublic();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -652,37 +535,7 @@ public class MessageFacade
|
||||
orderBookListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void addTakeOfferRequestListener(TakeOfferRequestListener listener)
|
||||
{
|
||||
takeOfferRequestListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeTakeOfferRequestListener(TakeOfferRequestListener listener)
|
||||
{
|
||||
takeOfferRequestListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void addTakerPaymentProtocol(TakerAsSellerProtocol protocol)
|
||||
{
|
||||
takerPaymentProtocols.put(protocol.getId(), protocol);
|
||||
}
|
||||
|
||||
public void removeTakerPaymentProtocol(TakerAsSellerProtocol protocol)
|
||||
{
|
||||
takerPaymentProtocols.remove(protocol);
|
||||
}
|
||||
|
||||
public void addOffererPaymentProtocol(OffererAsBuyerProtocol protocol)
|
||||
{
|
||||
offererAsBuyerProtocols.put(protocol.getId(), protocol);
|
||||
}
|
||||
|
||||
public void removeOffererPaymentProtocol(OffererAsBuyerProtocol protocol)
|
||||
{
|
||||
offererAsBuyerProtocols.remove(protocol);
|
||||
}
|
||||
|
||||
public void addPingPeerListener(PingPeerListener listener)
|
||||
/* public void addPingPeerListener(PingPeerListener listener)
|
||||
{
|
||||
pingPeerListeners.add(listener);
|
||||
}
|
||||
@ -690,7 +543,7 @@ public class MessageFacade
|
||||
public void removePingPeerListener(PingPeerListener listener)
|
||||
{
|
||||
pingPeerListeners.remove(listener);
|
||||
}
|
||||
} */
|
||||
|
||||
public void addArbitratorListener(ArbitratorListener listener)
|
||||
{
|
||||
@ -702,6 +555,44 @@ public class MessageFacade
|
||||
arbitratorListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void addIncomingTradeMessageListener(IncomingTradeMessageListener listener)
|
||||
{
|
||||
incomingTradeMessageListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeIncomingTradeMessageListener(IncomingTradeMessageListener listener)
|
||||
{
|
||||
incomingTradeMessageListeners.remove(listener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PublicKey getPubKey()
|
||||
{
|
||||
return keyPair.getPublic();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message handler
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void onMessage(Object request, PeerAddress sender)
|
||||
{
|
||||
if (request instanceof TradeMessage)
|
||||
{
|
||||
incomingTradeMessageListeners.stream().forEach(e -> e.onMessage((TradeMessage) request, sender));
|
||||
}
|
||||
/* else
|
||||
{
|
||||
for (OrderBookListener orderBookListener : orderBookListeners)
|
||||
orderBookListener.onMessage(request);
|
||||
} */
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -739,6 +630,18 @@ public class MessageFacade
|
||||
});
|
||||
}
|
||||
|
||||
private void setupReplyHandler()
|
||||
{
|
||||
myPeer.setObjectDataReply((sender, request) -> {
|
||||
if (!sender.equals(myPeer.getPeerAddress()))
|
||||
Platform.runLater(() -> onMessage(request, sender));
|
||||
else
|
||||
log.error("Received msg from myself. That should never happen.");
|
||||
//noinspection ReturnOfNull
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private void setupStorage()
|
||||
{
|
||||
myPeer.getPeerBean().setStorage(new StorageDisk(FileUtil.getDirectory(BitSquare.ID + "_tomP2P").getAbsolutePath()));
|
||||
@ -752,49 +655,4 @@ public class MessageFacade
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message handler
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void setupReplyHandler()
|
||||
{
|
||||
/* myPeer.setObjectDataReply((sender, request) -> {
|
||||
if (!sender.equals(myPeer.getPeerAddress()))
|
||||
{
|
||||
Platform.runLater(() -> onMessage(request, sender));
|
||||
}
|
||||
//noinspection ReturnOfNull
|
||||
return null;
|
||||
}); */
|
||||
|
||||
//noinspection Convert2Lambda
|
||||
myPeer.setObjectDataReply(new ObjectDataReply()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Object reply(PeerAddress sender, Object request) throws Exception
|
||||
{
|
||||
if (!sender.equals(myPeer.getPeerAddress()))
|
||||
{
|
||||
Platform.runLater(() -> onMessage(request, sender));
|
||||
}
|
||||
//noinspection ReturnOfNull
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onMessage(Object request, PeerAddress sender)
|
||||
{
|
||||
if (request instanceof TradeMessage)
|
||||
{
|
||||
processTradingMessage((TradeMessage) request, sender);
|
||||
}
|
||||
/* else
|
||||
{
|
||||
for (OrderBookListener orderBookListener : orderBookListeners)
|
||||
orderBookListener.onMessage(request);
|
||||
} */
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.taker.listeners;
|
||||
package io.bitsquare.msg.listeners;
|
||||
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
|
@ -0,0 +1,9 @@
|
||||
package io.bitsquare.msg.listeners;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
|
||||
public interface IncomingTradeMessageListener
|
||||
{
|
||||
void onMessage(TradeMessage tradeMessage, PeerAddress sender);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package io.bitsquare.msg.listeners;
|
||||
|
||||
public interface TradeMessageListener
|
||||
public interface OutgoingTradeMessageListener
|
||||
{
|
||||
void onFailed();
|
||||
|
@ -167,7 +167,7 @@ public class Offer implements Serializable
|
||||
return collateral;
|
||||
}
|
||||
|
||||
public String getBankAccountUID()
|
||||
public String getBankAccountId()
|
||||
{
|
||||
return bankAccountUID;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import java.math.BigInteger;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
public class Trade implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = -8275323072940974077L;
|
||||
@ -22,7 +21,6 @@ public class Trade implements Serializable
|
||||
private String takerSignature;
|
||||
private Transaction depositTransaction;
|
||||
private Transaction payoutTransaction;
|
||||
|
||||
private State state = State.OPEN;
|
||||
|
||||
public Trade(Offer offer)
|
||||
@ -30,15 +28,16 @@ public class Trade implements Serializable
|
||||
this.offer = offer;
|
||||
}
|
||||
|
||||
public void setContractTakerSignature(String takerSignature)
|
||||
{
|
||||
this.takerSignature = takerSignature;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setContractTakerSignature(String takerSignature)
|
||||
{
|
||||
this.takerSignature = takerSignature;
|
||||
}
|
||||
|
||||
public void setTakeOfferFeeTxID(String takeOfferFeeTxID)
|
||||
{
|
||||
this.takeOfferFeeTxID = takeOfferFeeTxID;
|
||||
|
@ -8,55 +8,61 @@ import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import io.bitsquare.msg.listeners.TakeOfferRequestListener;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocolListener;
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocol;
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocolListener;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.*;
|
||||
import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.messages.taker.RequestTakeOfferMessage;
|
||||
import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage;
|
||||
import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocol;
|
||||
import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocolListener;
|
||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocol;
|
||||
import io.bitsquare.trade.protocol.taker.TakerAsSellerProtocolListener;
|
||||
import io.bitsquare.user.User;
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Represents trade domain. Keeps complexity of process apart from view controller
|
||||
*/
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public class Trading
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(Trading.class);
|
||||
private final Map<String, TakerAsSellerProtocol> takerPaymentProtocols = new HashMap<>();
|
||||
private final Map<String, OffererAsBuyerProtocol> offererPaymentProtocols = new HashMap<>();
|
||||
private final String storageKey;
|
||||
private final User user;
|
||||
|
||||
private final String storageKey = this.getClass().getName();
|
||||
|
||||
private final User user;
|
||||
private final Storage storage;
|
||||
private final MessageFacade messageFacade;
|
||||
private final BlockChainFacade blockChainFacade;
|
||||
private final WalletFacade walletFacade;
|
||||
private final CryptoFacade cryptoFacade;
|
||||
|
||||
private final List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>();
|
||||
private final Map<String, TakerAsSellerProtocol> takerAsSellerProtocolMap = new HashMap<>();
|
||||
private final Map<String, OffererAsBuyerProtocol> offererAsBuyerProtocolMap = new HashMap<>();
|
||||
|
||||
private final StringProperty newTradeProperty = new SimpleStringProperty();
|
||||
|
||||
private Map<String, Offer> offers = new HashMap<>();
|
||||
private final Map<String, Offer> offers;
|
||||
private final Map<String, Trade> trades;
|
||||
|
||||
private Map<String, Trade> trades = new HashMap<>();
|
||||
private Trade currentPendingTrade;
|
||||
private Trade pendingTrade;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Inject
|
||||
public Trading(User user,
|
||||
Storage storage,
|
||||
@ -72,36 +78,55 @@ public class Trading
|
||||
this.walletFacade = walletFacade;
|
||||
this.cryptoFacade = cryptoFacade;
|
||||
|
||||
storageKey = this.getClass().getName();
|
||||
|
||||
Object offersObject = storage.read(storageKey + ".offers");
|
||||
if (offersObject instanceof HashMap)
|
||||
offers = (Map<String, Offer>) offersObject;
|
||||
else
|
||||
offers = new HashMap<>();
|
||||
|
||||
Object tradesObject = storage.read(storageKey + ".trades");
|
||||
if (tradesObject instanceof HashMap)
|
||||
trades = (Map<String, Trade>) tradesObject;
|
||||
else
|
||||
trades = new HashMap<>();
|
||||
|
||||
messageFacade.addTakeOfferRequestListener((offerId, sender) -> createOffererAsBuyerProtocol(offerId, sender));
|
||||
messageFacade.addIncomingTradeMessageListener(this::onIncomingTradeMessage);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void cleanup()
|
||||
{
|
||||
messageFacade.removeIncomingTradeMessageListener(this::onIncomingTradeMessage);
|
||||
}
|
||||
|
||||
private void saveOffers()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Event Listeners
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void addTakeOfferRequestListener(TakeOfferRequestListener listener)
|
||||
{
|
||||
storage.write(storageKey + ".offers", offers);
|
||||
takeOfferRequestListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeTakeOfferRequestListener(TakeOfferRequestListener listener)
|
||||
{
|
||||
takeOfferRequestListeners.remove(listener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Manage offers
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void addOffer(Offer offer) throws IOException
|
||||
{
|
||||
if (offers.containsKey(offer.getId()))
|
||||
throw new IllegalStateException("offers contains already a offer with the ID " + offer.getId());
|
||||
throw new IllegalStateException("offers contains already an offer with the ID " + offer.getId());
|
||||
|
||||
offers.put(offer.getId(), offer);
|
||||
saveOffers();
|
||||
@ -109,22 +134,44 @@ public class Trading
|
||||
messageFacade.addOffer(offer);
|
||||
}
|
||||
|
||||
public void removeOffer(Offer offer) throws IOException
|
||||
public void removeOffer(Offer offer)
|
||||
{
|
||||
if (!offers.containsKey(offer.getId()))
|
||||
throw new IllegalStateException("offers does not contain the offer with the ID " + offer.getId());
|
||||
|
||||
offers.remove(offer.getId());
|
||||
saveOffers();
|
||||
|
||||
messageFacade.removeOffer(offer);
|
||||
}
|
||||
|
||||
public Trade takeOffer(BigInteger amount, Offer offer, TakerAsSellerProtocolListener listener)
|
||||
{
|
||||
Trade trade = createTrade(offer);
|
||||
trade.setTradeAmount(amount);
|
||||
|
||||
TakerAsSellerProtocol takerAsSellerProtocol = new TakerAsSellerProtocol(trade, listener, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||
takerAsSellerProtocolMap.put(trade.getId(), takerAsSellerProtocol);
|
||||
takerAsSellerProtocol.start();
|
||||
|
||||
return trade;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Manage trades
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Trade createTrade(Offer offer)
|
||||
{
|
||||
if (trades.containsKey(offer.getId()))
|
||||
throw new IllegalStateException("trades contains already an trade with the ID " + offer.getId());
|
||||
|
||||
Trade trade = new Trade(offer);
|
||||
trades.put(offer.getId(), trade);
|
||||
//TODO for testing
|
||||
//storage.write(storageKey + ".trades", trades);
|
||||
saveTrades();
|
||||
|
||||
// for updating UIs
|
||||
this.newTradeProperty.set(trade.getId());
|
||||
|
||||
return trade;
|
||||
@ -132,39 +179,39 @@ public class Trading
|
||||
|
||||
public void removeTrade(Trade trade)
|
||||
{
|
||||
if (!trades.containsKey(trade.getId()))
|
||||
throw new IllegalStateException("trades does not contain the trade with the ID " + trade.getId());
|
||||
|
||||
trades.remove(trade.getId());
|
||||
storage.write(storageKey + ".trades", trades);
|
||||
saveTrades();
|
||||
|
||||
// for updating UIs
|
||||
this.newTradeProperty.set(null);
|
||||
}
|
||||
|
||||
|
||||
public final StringProperty getNewTradeProperty()
|
||||
{
|
||||
return this.newTradeProperty;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trading protocols
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Trade takeOffer(BigInteger amount, Offer offer, TakerAsSellerProtocolListener listener, WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
Trade trade = createTrade(offer);
|
||||
trade.setTradeAmount(amount);
|
||||
|
||||
TakerAsSellerProtocol takerPaymentProtocol = new TakerAsSellerProtocol(trade, listener, resultHandler, faultHandler, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user);
|
||||
takerPaymentProtocols.put(trade.getId(), takerPaymentProtocol);
|
||||
|
||||
return trade;
|
||||
}
|
||||
|
||||
|
||||
public void createOffererAsBuyerProtocol(String offerId, PeerAddress sender)
|
||||
private void createOffererAsBuyerProtocol(String offerId, PeerAddress sender)
|
||||
{
|
||||
log.trace("createOffererAsBuyerProtocol offerId = " + offerId);
|
||||
Offer offer = offers.get(offerId);
|
||||
if (offer != null && offers.containsKey(offer.getId()))
|
||||
if (offers.containsKey(offerId))
|
||||
{
|
||||
offers.remove(offer);
|
||||
Offer offer = offers.get(offerId);
|
||||
|
||||
currentPendingTrade = createTrade(offer);
|
||||
OffererAsBuyerProtocolListener listener = new OffererAsBuyerProtocolListener()
|
||||
Trade trade = createTrade(offer);
|
||||
pendingTrade = trade;
|
||||
|
||||
OffererAsBuyerProtocol offererAsBuyerProtocol = new OffererAsBuyerProtocol(trade, sender, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user, new OffererAsBuyerProtocolListener()
|
||||
{
|
||||
@Override
|
||||
public void onOfferAccepted(Offer offer)
|
||||
{
|
||||
removeOffer(offer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDepositTxPublished(String depositTxID)
|
||||
{
|
||||
@ -181,8 +228,8 @@ public class Trading
|
||||
public void onPayoutTxPublished(String payoutTxAsHex)
|
||||
{
|
||||
Transaction payoutTx = new Transaction(walletFacade.getWallet().getParams(), Utils.parseAsHexOrBase58(payoutTxAsHex));
|
||||
currentPendingTrade.setPayoutTransaction(payoutTx);
|
||||
currentPendingTrade.setState(Trade.State.COMPLETED);
|
||||
trade.setPayoutTransaction(payoutTx);
|
||||
trade.setState(Trade.State.COMPLETED);
|
||||
log.debug("trading onPayoutTxPublishedMessage");
|
||||
}
|
||||
|
||||
@ -192,27 +239,9 @@ public class Trading
|
||||
log.trace("trading onDepositTxConfirmedInBlockchain");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
WorkerResultHandler resultHandler = new WorkerResultHandler()
|
||||
{
|
||||
@Override
|
||||
public void onResult(Worker worker)
|
||||
{
|
||||
//log.trace("onResult " + worker.toString());
|
||||
}
|
||||
};
|
||||
WorkerFaultHandler faultHandler = new WorkerFaultHandler()
|
||||
{
|
||||
@Override
|
||||
public void onFault(Throwable throwable)
|
||||
{
|
||||
log.error("onFault " + throwable);
|
||||
}
|
||||
};
|
||||
|
||||
OffererAsBuyerProtocol offererAsBuyerProtocol = new OffererAsBuyerProtocol(currentPendingTrade, sender, messageFacade, walletFacade, blockChainFacade, cryptoFacade, user, resultHandler, faultHandler, listener);
|
||||
offererPaymentProtocols.put(currentPendingTrade.getId(), offererAsBuyerProtocol);
|
||||
});
|
||||
this.offererAsBuyerProtocolMap.put(trade.getId(), offererAsBuyerProtocol);
|
||||
offererAsBuyerProtocol.start();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -220,35 +249,89 @@ public class Trading
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onUIEventBankTransferInited(String tradeUID)
|
||||
public void bankTransferInited(String tradeUID)
|
||||
{
|
||||
offererPaymentProtocols.get(tradeUID).onUIEventBankTransferInited();
|
||||
offererAsBuyerProtocolMap.get(tradeUID).onUIEventBankTransferInited();
|
||||
}
|
||||
|
||||
public void onFiatReceived(String tradeUID)
|
||||
{
|
||||
takerAsSellerProtocolMap.get(tradeUID).onUIEventFiatReceived();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Process incoming tradeMessages
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void onIncomingTradeMessage(TradeMessage tradeMessage, PeerAddress sender)
|
||||
{
|
||||
// log.trace("processTradingMessage TradeId " + tradeMessage.getTradeId());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getSimpleName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getCanonicalName());
|
||||
log.trace("processTradingMessage instance " + tradeMessage.getClass().getTypeName());
|
||||
|
||||
String tradeId = tradeMessage.getTradeId();
|
||||
|
||||
if (tradeMessage instanceof RequestTakeOfferMessage)
|
||||
{
|
||||
createOffererAsBuyerProtocol(tradeId, sender);
|
||||
takeOfferRequestListeners.stream().forEach(e -> e.onTakeOfferRequested(tradeId, sender));
|
||||
}
|
||||
else if (tradeMessage instanceof AcceptTakeOfferRequestMessage)
|
||||
{
|
||||
takerAsSellerProtocolMap.get(tradeId).onAcceptTakeOfferRequestMessage();
|
||||
}
|
||||
else if (tradeMessage instanceof RejectTakeOfferRequestMessage)
|
||||
{
|
||||
takerAsSellerProtocolMap.get(tradeId).onRejectTakeOfferRequestMessage();
|
||||
}
|
||||
else if (tradeMessage instanceof TakeOfferFeePayedMessage)
|
||||
{
|
||||
offererAsBuyerProtocolMap.get(tradeId).onTakeOfferFeePayedMessage((TakeOfferFeePayedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof RequestTakerDepositPaymentMessage)
|
||||
{
|
||||
takerAsSellerProtocolMap.get(tradeId).onRequestTakerDepositPaymentMessage((RequestTakerDepositPaymentMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof RequestOffererPublishDepositTxMessage)
|
||||
{
|
||||
offererAsBuyerProtocolMap.get(tradeId).onRequestOffererPublishDepositTxMessage((RequestOffererPublishDepositTxMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof DepositTxPublishedMessage)
|
||||
{
|
||||
takerAsSellerProtocolMap.get(tradeId).onDepositTxPublishedMessage((DepositTxPublishedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof BankTransferInitedMessage)
|
||||
{
|
||||
takerAsSellerProtocolMap.get(tradeId).onBankTransferInitedMessage((BankTransferInitedMessage) tradeMessage);
|
||||
}
|
||||
else if (tradeMessage instanceof PayoutTxPublishedMessage)
|
||||
{
|
||||
offererAsBuyerProtocolMap.get(tradeId).onPayoutTxPublishedMessage((PayoutTxPublishedMessage) tradeMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Trade process
|
||||
// Utils
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// 6
|
||||
public void releaseBTC(String tradeUID)
|
||||
public boolean isOfferAlreadyInTrades(Offer offer)
|
||||
{
|
||||
takerPaymentProtocols.get(tradeUID).onUIEventFiatReceived();
|
||||
return trades.containsKey(offer.getId());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public Map<String, Trade> getTrades()
|
||||
{
|
||||
return trades;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Offer> getOffers()
|
||||
{
|
||||
return offers;
|
||||
@ -259,14 +342,37 @@ public class Trading
|
||||
return offers.get(offerId);
|
||||
}
|
||||
|
||||
|
||||
public boolean isOfferAlreadyInTrades(Offer offer)
|
||||
public Trade getPendingTrade()
|
||||
{
|
||||
return trades.containsKey(offer.getId());
|
||||
return pendingTrade;
|
||||
}
|
||||
|
||||
public Trade getCurrentPendingTrade()
|
||||
public final StringProperty getNewTradeProperty()
|
||||
{
|
||||
return currentPendingTrade;
|
||||
return this.newTradeProperty;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void saveOffers()
|
||||
{
|
||||
storage.write(storageKey + ".offers", offers);
|
||||
}
|
||||
|
||||
private void saveTrades()
|
||||
{
|
||||
storage.write(storageKey + ".trades", trades);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Trade getTrade(String tradeId)
|
||||
{
|
||||
if (trades.containsKey(tradeId))
|
||||
return trades.get(trades);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -77,13 +77,7 @@ public class OrderBook implements OrderBookListener
|
||||
|
||||
public void removeOffer(Offer offer)
|
||||
{
|
||||
try
|
||||
{
|
||||
trading.removeOffer(offer);
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
trading.removeOffer(offer);
|
||||
}
|
||||
|
||||
public void applyFilter(OrderBookFilter orderBookFilter)
|
||||
|
@ -1,26 +0,0 @@
|
||||
package io.bitsquare.trade.payment;
|
||||
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.nucleo.scheduler.model.PropertyProviderModel;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
|
||||
public class PaymentModel extends PropertyProviderModel
|
||||
{
|
||||
public final MessageFacade messageFacade;
|
||||
public final Offer offer;
|
||||
public PeerAddress peerAddress;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PaymentModel(MessageFacade messageFacade, Trade trade)
|
||||
{
|
||||
this.messageFacade = messageFacade;
|
||||
this.offer = trade.getOffer();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import io.bitsquare.trade.payment.offerer.OffererAsBuyerProtocol;
|
||||
import io.nucleo.scheduler.tasks.AbstractTask;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractOffererAsBuyerTask extends AbstractTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractOffererAsBuyerTask.class);
|
||||
|
||||
protected OffererAsBuyerProtocol sharedModel;
|
||||
|
||||
public AbstractOffererAsBuyerTask(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
addResultHandlers(resultHandler);
|
||||
addFaultHandlers(faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(Object model)
|
||||
{
|
||||
sharedModel = (OffererAsBuyerProtocol) model;
|
||||
super.setModel(model);
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateDepositTx extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateDepositTx.class);
|
||||
|
||||
public CreateDepositTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
|
||||
try
|
||||
{
|
||||
sharedModel.setOffererPubKey(sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getPubKeyAsHexString());
|
||||
Transaction tx = sharedModel.getWalletFacade().offererCreatesMSTxAndAddPayment(sharedModel.getTrade().getCollateralAmount(),
|
||||
sharedModel.getOffererPubKey(),
|
||||
sharedModel.getTakerMultiSigPubKey(),
|
||||
sharedModel.getTrade().getOffer().getArbitrator().getPubKeyAsHex(),
|
||||
sharedModel.getTrade().getId());
|
||||
|
||||
sharedModel.setPreparedOffererDepositTxAsHex(Utils.bytesToHexString(tx.bitcoinSerialize()));
|
||||
sharedModel.setOffererTxOutIndex(tx.getInput(0).getOutpoint().getIndex());
|
||||
complete();
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
log.error("Create deposit tx failed due InsufficientMoneyException " + e);
|
||||
failed(new Exception("Create deposit tx failed due InsufficientMoneyException " + e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.payment.offerer.messages.AcceptTakeOfferRequestMessage;
|
||||
import io.bitsquare.trade.payment.offerer.messages.RejectTakeOfferRequestMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HandleTakeOfferRequest extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class);
|
||||
|
||||
public HandleTakeOfferRequest(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
if (sharedModel.getTrade().getState() == Trade.State.OPEN)
|
||||
{
|
||||
AcceptTakeOfferRequestMessage msg = new AcceptTakeOfferRequestMessage(sharedModel.getTrade().getId());
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, msg, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("AcceptTakeOfferRequestMessage successfully arrived at peer");
|
||||
sharedModel.getTrade().setState(Trade.State.ACCEPTED);
|
||||
sharedModel.getMessageFacade().removeOffer(sharedModel.getTrade().getOffer());
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("AcceptTakeOfferRequestMessage failed to arrive at peer");
|
||||
failed(new Exception("AcceptTakeOfferRequestMessage failed to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
RejectTakeOfferRequestMessage msg = new RejectTakeOfferRequestMessage(sharedModel.getTrade().getId());
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, msg, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RejectTakeOfferRequestMessage successfully arrived at peer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RejectTakeOfferRequestMessage failed to arrive at peer");
|
||||
}
|
||||
});
|
||||
|
||||
log.error("Offer not marked as open.");
|
||||
failed(new Exception("Offer not marked as open."));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.payment.offerer.messages.RequestTakerDepositPaymentMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RequestTakerDepositPayment extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(RequestTakerDepositPayment.class);
|
||||
|
||||
public RequestTakerDepositPayment(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
|
||||
RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(sharedModel.getTrade().getId(),
|
||||
sharedModel.getUser().getBankAccount(sharedModel.getTrade().getOffer().getBankAccountUID()),
|
||||
sharedModel.getUser().getAccountID(),
|
||||
sharedModel.getOffererPubKey(),
|
||||
sharedModel.getPreparedOffererDepositTxAsHex(),
|
||||
sharedModel.getOffererTxOutIndex());
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, tradeMessage, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RequestTakerDepositPaymentMessage failed to arrive at peer");
|
||||
failed(new Exception("RequestTakerDepositPaymentMessage failed to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.payment.offerer.messages.DepositTxPublishedMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendDepositTxIdToTaker extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendDepositTxIdToTaker.class);
|
||||
|
||||
public SendDepositTxIdToTaker(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(sharedModel.getTrade().getId(), Utils.bytesToHexString(sharedModel.getTrade().getDepositTransaction().bitcoinSerialize()));
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, tradeMessage, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("DepositTxPublishedMessage successfully arrived at peer");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("DepositTxPublishedMessage failed to arrive at peer");
|
||||
failed(new Exception("DepositTxPublishedMessage failed to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.TransactionConfidence;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SetupListenerForBlockChainConfirmation extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
|
||||
|
||||
public SetupListenerForBlockChainConfirmation(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
//TODO
|
||||
// sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
||||
|
||||
Transaction tx = sharedModel.getTrade().getDepositTransaction();
|
||||
tx.getConfidence().addEventListener(new TransactionConfidence.Listener()
|
||||
{
|
||||
@Override
|
||||
public void onConfidenceChanged(Transaction tx, ChangeReason reason)
|
||||
{
|
||||
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||
if (reason == ChangeReason.SEEN_PEERS)
|
||||
{
|
||||
sharedModel.getListener().onDepositTxConfirmedUpdate(tx.getConfidence());
|
||||
}
|
||||
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||
{
|
||||
sharedModel.getListener().onDepositTxConfirmedInBlockchain();
|
||||
tx.getConfidence().removeEventListener(this);
|
||||
log.trace("Tx is in blockchain");
|
||||
complete();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SignAndPublishDepositTx extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class);
|
||||
|
||||
public SignAndPublishDepositTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
try
|
||||
{
|
||||
sharedModel.getWalletFacade().offererSignAndPublishTx(sharedModel.getPreparedOffererDepositTxAsHex(),
|
||||
sharedModel.getSignedTakerDepositTxAsHex(),
|
||||
sharedModel.getTxConnOutAsHex(),
|
||||
sharedModel.getTxScriptSigAsHex(),
|
||||
sharedModel.getOffererTxOutIndex(),
|
||||
sharedModel.getTakerTxOutIndex(),
|
||||
new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.trace("offererSignAndPublishTx succeeded " + transaction);
|
||||
sharedModel.getTrade().setDepositTransaction(transaction);
|
||||
sharedModel.getListener().onDepositTxPublished(transaction.getHashAsString());
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("offererSignAndPublishTx failed:" + t);
|
||||
failed(t);
|
||||
}
|
||||
});
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.error("offererSignAndPublishTx failed:" + e);
|
||||
failed(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.util.Utilities;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyAndSignContract extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyAndSignContract.class);
|
||||
|
||||
public VerifyAndSignContract(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
Contract contract = new Contract(sharedModel.getTrade().getOffer(),
|
||||
sharedModel.getTrade().getTradeAmount(),
|
||||
sharedModel.getTrade().getTakeOfferFeeTxId(),
|
||||
sharedModel.getUser().getAccountID(),
|
||||
sharedModel.getPeersAccountId(),
|
||||
sharedModel.getUser().getCurrentBankAccount(),
|
||||
sharedModel.getPeersBankAccount(),
|
||||
sharedModel.getTrade().getOffer().getMessagePubKeyAsHex(),
|
||||
sharedModel.getTakerMessagePubKey());
|
||||
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
// log.trace("Offerer contract created: " + contract);
|
||||
// log.trace("Offerers contractAsJson: " + contractAsJson);
|
||||
// log.trace("Takers contractAsJson: " + sharedModel.peersContractAsJson);
|
||||
if (contractAsJson.equals(sharedModel.getPeersContractAsJson()))
|
||||
{
|
||||
log.trace("The 2 contracts as json does match");
|
||||
String signature = sharedModel.getCryptoFacade().signContract(sharedModel.getWalletFacade().getRegistrationAddressInfo().getKey(), contractAsJson);
|
||||
sharedModel.getTrade().setContract(contract);
|
||||
sharedModel.getTrade().setContractAsJson(contractAsJson);
|
||||
sharedModel.getTrade().setContractTakerSignature(signature);
|
||||
//log.trace("signature: " + signature);
|
||||
|
||||
complete();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO use diff output as feedback ?
|
||||
log.error("Contracts are not matching.");
|
||||
log.error("Offerers contractAsJson: " + contractAsJson);
|
||||
log.error("Takers contractAsJson: " + sharedModel.getPeersContractAsJson());
|
||||
|
||||
failed(new Exception("Contracts are not matching"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyTakeOfferFeePayment extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyTakeOfferFeePayment.class);
|
||||
|
||||
public VerifyTakeOfferFeePayment(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
//TODO mocked yet, need a confidence listeners
|
||||
int numOfPeersSeenTx = sharedModel.getWalletFacade().getNumOfPeersSeenTx(sharedModel.getTakeOfferFeeTxId());
|
||||
if (numOfPeersSeenTx > 2)
|
||||
{
|
||||
complete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyTakerAccount extends AbstractOffererAsBuyerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class);
|
||||
|
||||
public VerifyTakerAccount(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
//TODO mocked yet
|
||||
if (sharedModel.getBlockChainFacade().verifyAccountRegistration())
|
||||
{
|
||||
if (sharedModel.getBlockChainFacade().isAccountBlackListed(sharedModel.getPeersAccountId(), sharedModel.getPeersBankAccount()))
|
||||
{
|
||||
log.error("Taker is blacklisted");
|
||||
failed(new Exception("Taker is blacklisted"));
|
||||
}
|
||||
else
|
||||
{
|
||||
complete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Account registration validation for peer failed.");
|
||||
failed(new Exception("Account registration validation for peer failed."));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker;
|
||||
|
||||
import io.bitsquare.trade.Trade;
|
||||
|
||||
public interface TakerAsSellerProtocolListener
|
||||
{
|
||||
void onDepositTxPublished(String depositTxId);
|
||||
|
||||
void onBankTransferInited(String tradeId);
|
||||
|
||||
void onTradeCompleted(Trade trade, String hashAsString);
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import io.bitsquare.trade.payment.taker.TakerAsSellerProtocol;
|
||||
import io.nucleo.scheduler.tasks.AbstractTask;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class AbstractTakerAsSellerTask extends AbstractTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractTakerAsSellerTask.class);
|
||||
|
||||
protected TakerAsSellerProtocol sharedModel;
|
||||
|
||||
public AbstractTakerAsSellerTask(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
addResultHandlers(resultHandler);
|
||||
addFaultHandlers(faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModel(Object model)
|
||||
{
|
||||
sharedModel = (TakerAsSellerProtocol) model;
|
||||
super.setModel(model);
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.util.Utilities;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateAndSignContract extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
||||
|
||||
public CreateAndSignContract(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
Trade trade = sharedModel.getTrade();
|
||||
Contract contract = new Contract(trade.getOffer(),
|
||||
trade.getTradeAmount(),
|
||||
trade.getTakeOfferFeeTxId(),
|
||||
sharedModel.getPeersAccountId(),
|
||||
sharedModel.getUser().getAccountID(),
|
||||
sharedModel.getPeersBankAccount(),
|
||||
sharedModel.getUser().getCurrentBankAccount(),
|
||||
trade.getOffer().getMessagePubKeyAsHex(),
|
||||
sharedModel.getUser().getMessagePubKeyAsHex()
|
||||
);
|
||||
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
String signature = sharedModel.getCryptoFacade().signContract(sharedModel.getWalletFacade().getRegistrationAddressInfo().getKey(), contractAsJson);
|
||||
//log.trace("contract: " + contract);
|
||||
//log.debug("contractAsJson: " + contractAsJson);
|
||||
//log.trace("contract signature: " + signature);
|
||||
|
||||
trade.setContract(contract);
|
||||
trade.setContractAsJson(contractAsJson);
|
||||
trade.setContractTakerSignature(signature);
|
||||
|
||||
complete();
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import io.bitsquare.trade.payment.taker.listeners.GetPeerAddressListener;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GetPeerAddress extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class);
|
||||
|
||||
public GetPeerAddress(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
sharedModel.getMessageFacade().getPeerAddress(sharedModel.getTrade().getOffer().getMessagePubKeyAsHex(), new GetPeerAddressListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult(PeerAddress address)
|
||||
{
|
||||
log.trace("Received address = " + address.toString());
|
||||
sharedModel.setPeerAddress(address);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("Lookup for peer address failed.");
|
||||
failed(new Exception("Lookup for peer address failed."));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import java.math.BigInteger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PayDeposit extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
|
||||
|
||||
public PayDeposit(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
try
|
||||
{
|
||||
Trade trade = sharedModel.getTrade();
|
||||
BigInteger collateralAmount = trade.getCollateralAmount();
|
||||
sharedModel.setSignedTakerDepositTx(sharedModel.getWalletFacade().takerAddPaymentAndSignTx(trade.getTradeAmount().add(collateralAmount),
|
||||
trade.getTradeAmount().add(collateralAmount).add(collateralAmount),
|
||||
sharedModel.getOffererPubKey(),
|
||||
sharedModel.getWalletFacade().getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString(),
|
||||
trade.getOffer().getArbitrator().getPubKeyAsHex(),
|
||||
sharedModel.getPreparedOffererDepositTxAsHex(),
|
||||
trade.getId()));
|
||||
|
||||
log.trace("sharedModel.signedTakerDepositTx: " + sharedModel.getSignedTakerDepositTx());
|
||||
sharedModel.setTakerTxOutIndex(sharedModel.getSignedTakerDepositTx().getInput(1).getOutpoint().getIndex());
|
||||
|
||||
complete();
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
log.error("Pay deposit failed due InsufficientMoneyException " + e);
|
||||
failed(new Exception("Pay deposit failed due InsufficientMoneyException " + e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PayTakeOfferFee extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class);
|
||||
|
||||
public PayTakeOfferFee(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
try
|
||||
{
|
||||
sharedModel.getWalletFacade().payTakeOfferFee(sharedModel.getTrade().getId(), new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString());
|
||||
sharedModel.getTrade().setTakeOfferFeeTxID(transaction.getHashAsString());
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("Take offer fee paid failed with exception: " + t);
|
||||
failed(new Exception("Take offer fee paid failed with exception: " + t));
|
||||
}
|
||||
});
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
log.error("Take offer fee paid failed due InsufficientMoneyException " + e);
|
||||
failed(new Exception("Take offer fee paid failed due InsufficientMoneyException " + e));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.payment.taker.messages.RequestTakeOfferMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RequestTakeOffer extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
|
||||
|
||||
public RequestTakeOffer(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
RequestTakeOfferMessage msg = new RequestTakeOfferMessage(sharedModel.getTrade().getId());
|
||||
sharedModel.getMessageFacade().sendTradingMessage(sharedModel.getPeerAddress(), msg, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RequestTakeOfferMessage successfully arrived at peer");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RequestTakeOfferMessage failed to arrive at peer");
|
||||
failed(new Exception("RequestTakeOfferMessage failed to arrive at peer"));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.payment.taker.messages.PayoutTxPublishedMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendPayoutTxToOfferer extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
|
||||
|
||||
public SendPayoutTxToOfferer(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(sharedModel.getTrade().getId(), sharedModel.getPayoutTxAsHex());
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.getPeerAddress(), tradeMessage, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("PayoutTxPublishedMessage failed to arrive at peer");
|
||||
failed(new Exception("PayoutTxPublishedMessage failed to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.payment.taker.messages.RequestOffererPublishDepositTxMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendSignedTakerDepositTxAsHex extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
|
||||
|
||||
public SendSignedTakerDepositTxAsHex(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
|
||||
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(sharedModel.getTrade().getId(),
|
||||
sharedModel.getUser().getCurrentBankAccount(),
|
||||
sharedModel.getUser().getAccountID(),
|
||||
sharedModel.getUser().getMessagePubKeyAsHex(),
|
||||
Utils.bytesToHexString(sharedModel.getSignedTakerDepositTx().bitcoinSerialize()),
|
||||
Utils.bytesToHexString(sharedModel.getSignedTakerDepositTx().getInput(1).getScriptBytes()),
|
||||
Utils.bytesToHexString(sharedModel.getSignedTakerDepositTx().getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()),
|
||||
sharedModel.getTrade().getContractAsJson(),
|
||||
sharedModel.getTrade().getTakerSignature(),
|
||||
sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getAddressString(),
|
||||
sharedModel.getTakerTxOutIndex(),
|
||||
sharedModel.getOffererTxOutIndex()
|
||||
);
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.getPeerAddress(), tradeMessage, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RequestOffererDepositPublicationMessage failed to arrive at peer");
|
||||
failed(new Exception("RequestOffererDepositPublicationMessage failed to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.payment.taker.messages.TakeOfferFeePayedMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendTakeOfferFeePayedTxId extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedTxId.class);
|
||||
|
||||
public SendTakeOfferFeePayedTxId(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
|
||||
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(sharedModel.getTrade().getId(),
|
||||
sharedModel.getTrade().getTakeOfferFeeTxId(),
|
||||
sharedModel.getTrade().getTradeAmount(),
|
||||
sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getPubKeyAsHexString());
|
||||
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.getPeerAddress(), msg, new TradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("TakeOfferFeePayedMessage successfully arrived at peer");
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("TakeOfferFeePayedMessage failed to arrive at peer");
|
||||
failed(new Exception("TakeOfferFeePayedMessage failed to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import java.math.BigInteger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SignAndPublishPayoutTx extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
||||
|
||||
public SignAndPublishPayoutTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
try
|
||||
{
|
||||
String depositTxAsHex = sharedModel.getDepositTxAsHex();
|
||||
String offererSignatureR = sharedModel.getOffererSignatureR();
|
||||
String offererSignatureS = sharedModel.getOffererSignatureS();
|
||||
BigInteger offererPaybackAmount = sharedModel.getOffererPaybackAmount();
|
||||
BigInteger takerPaybackAmount = sharedModel.getTakerPaybackAmount();
|
||||
String offererPayoutAddress = sharedModel.getOffererPayoutAddress();
|
||||
|
||||
sharedModel.getWalletFacade().takerSignsAndSendsTx(depositTxAsHex,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
offererPayoutAddress,
|
||||
sharedModel.getTrade().getId(),
|
||||
new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.debug("takerSignsAndSendsTx " + transaction);
|
||||
sharedModel.getListener().onTradeCompleted(sharedModel.getTrade(), transaction.getHashAsString());
|
||||
sharedModel.setPayoutTxAsHex(Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("Exception at takerSignsAndSendsTx " + t);
|
||||
failed(t);
|
||||
}
|
||||
});
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.error("Exception at takerSignsAndSendsTx " + e);
|
||||
failed(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package io.bitsquare.trade.payment.taker.tasks;
|
||||
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyOffererAccount extends AbstractTakerAsSellerTask
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
|
||||
|
||||
public VerifyOffererAccount(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
|
||||
//TODO mocked yet
|
||||
if (sharedModel.getBlockChainFacade().verifyAccountRegistration())
|
||||
{
|
||||
if (sharedModel.getBlockChainFacade().isAccountBlackListed(sharedModel.getPeersAccountId(), sharedModel.getPeersBankAccount()))
|
||||
{
|
||||
log.error("Offerer is blacklisted");
|
||||
failed(new Exception("Offerer is blacklisted"));
|
||||
}
|
||||
else
|
||||
{
|
||||
complete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Account Registration for peer failed.");
|
||||
failed(new Exception("Account Registration for peer failed."));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.offerer.messages;
|
||||
package io.bitsquare.trade.protocol.messages.offerer;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import java.io.Serializable;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.offerer.messages;
|
||||
package io.bitsquare.trade.protocol.messages.offerer;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import java.io.Serializable;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.offerer.messages;
|
||||
package io.bitsquare.trade.protocol.messages.offerer;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import java.io.Serializable;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.offerer.messages;
|
||||
package io.bitsquare.trade.protocol.messages.offerer;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import java.io.Serializable;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.offerer.messages;
|
||||
package io.bitsquare.trade.protocol.messages.offerer;
|
||||
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.msg.TradeMessage;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.taker.messages;
|
||||
package io.bitsquare.trade.protocol.messages.taker;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import java.io.Serializable;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.taker.messages;
|
||||
package io.bitsquare.trade.protocol.messages.taker;
|
||||
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.msg.TradeMessage;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.taker.messages;
|
||||
package io.bitsquare.trade.protocol.messages.taker;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import java.io.Serializable;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.taker.messages;
|
||||
package io.bitsquare.trade.protocol.messages.taker;
|
||||
|
||||
import io.bitsquare.msg.TradeMessage;
|
||||
import java.io.Serializable;
|
||||
@ -32,7 +32,7 @@ public class TakeOfferFeePayedMessage implements Serializable, TradeMessage
|
||||
return tradeAmount;
|
||||
}
|
||||
|
||||
public String getTakeOfferFeeTxID()
|
||||
public String getTakeOfferFeeTxId()
|
||||
{
|
||||
return takeOfferFeeTxID;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.process;
|
||||
package io.bitsquare.trade.protocol.mock;
|
||||
|
||||
//TODO not used but let it for reference until all use cases are impl.
|
||||
class BuyOffererPaymentProcess extends PaymentProcess
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.process;
|
||||
package io.bitsquare.trade.protocol.mock;
|
||||
|
||||
//TODO not used but let it for reference until all use cases are impl.
|
||||
public class BuyTakerPaymentProcess extends PaymentProcess
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.process;
|
||||
package io.bitsquare.trade.protocol.mock;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.process;
|
||||
package io.bitsquare.trade.protocol.mock;
|
||||
|
||||
//TODO not used but let it for reference until all use cases are impl.
|
||||
class SellOffererPaymentProcess extends PaymentProcess
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.process;
|
||||
package io.bitsquare.trade.protocol.mock;
|
||||
|
||||
//TODO not used but let it for reference until all use cases are impl.
|
||||
class SellTakerPaymentProcess extends PaymentProcess
|
@ -1,26 +1,27 @@
|
||||
package io.bitsquare.trade.payment.offerer;
|
||||
package io.bitsquare.trade.protocol.offerer;
|
||||
|
||||
import com.google.bitcoin.core.ECKey;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.payment.offerer.tasks.*;
|
||||
import io.bitsquare.trade.payment.taker.messages.PayoutTxPublishedMessage;
|
||||
import io.bitsquare.trade.payment.taker.messages.RequestOffererPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.payment.taker.messages.TakeOfferFeePayedMessage;
|
||||
import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.offerer.*;
|
||||
import io.bitsquare.user.User;
|
||||
import io.nucleo.scheduler.SequenceScheduler;
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.math.BigInteger;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.*;
|
||||
|
||||
//TODO refactor to process based pattern
|
||||
public class OffererAsBuyerProtocol
|
||||
{
|
||||
@ -31,19 +32,22 @@ public class OffererAsBuyerProtocol
|
||||
private final String id;
|
||||
private final Trade trade;
|
||||
private final OffererAsBuyerProtocolListener listener;
|
||||
private final WorkerResultHandler resultHandler;
|
||||
private final WorkerFaultHandler faultHandler;
|
||||
private final MessageFacade messageFacade;
|
||||
private final WalletFacade walletFacade;
|
||||
private final BlockChainFacade blockChainFacade;
|
||||
private final CryptoFacade cryptoFacade;
|
||||
private final User user;
|
||||
private final String tradeId;
|
||||
private final Offer offer;
|
||||
|
||||
|
||||
// private
|
||||
private final SequenceScheduler scheduler_1;
|
||||
private State state;
|
||||
|
||||
// data written/read by tasks
|
||||
private String preparedOffererDepositTxAsHex;
|
||||
private long offererTxOutIndex;
|
||||
private String offererPubKey;
|
||||
|
||||
// data written by messages, read by tasks
|
||||
private String takeOfferFeeTxId;
|
||||
private String takerMultiSigPubKey;
|
||||
@ -56,14 +60,6 @@ public class OffererAsBuyerProtocol
|
||||
private String txConnOutAsHex;
|
||||
private String txScriptSigAsHex;
|
||||
private long takerTxOutIndex;
|
||||
private SequenceScheduler scheduler_2;
|
||||
private SequenceScheduler scheduler_3;
|
||||
private SequenceScheduler scheduler_4;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public OffererAsBuyerProtocol(Trade trade,
|
||||
PeerAddress peerAddress,
|
||||
@ -72,15 +68,11 @@ public class OffererAsBuyerProtocol
|
||||
BlockChainFacade blockChainFacade,
|
||||
CryptoFacade cryptoFacade,
|
||||
User user,
|
||||
WorkerResultHandler resultHandler,
|
||||
WorkerFaultHandler faultHandler,
|
||||
OffererAsBuyerProtocolListener listener)
|
||||
{
|
||||
this.trade = trade;
|
||||
this.peerAddress = peerAddress;
|
||||
this.listener = listener;
|
||||
this.resultHandler = resultHandler;
|
||||
this.faultHandler = faultHandler;
|
||||
this.messageFacade = messageFacade;
|
||||
this.walletFacade = walletFacade;
|
||||
this.blockChainFacade = blockChainFacade;
|
||||
@ -89,43 +81,166 @@ public class OffererAsBuyerProtocol
|
||||
|
||||
id = trade.getId();
|
||||
|
||||
messageFacade.addOffererPaymentProtocol(this);
|
||||
tradeId = trade.getId();
|
||||
offer = trade.getOffer();
|
||||
|
||||
log.debug("OffererAsBuyerProtocol created");
|
||||
state = State.Start;
|
||||
}
|
||||
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new HandleTakeOfferRequest(resultHandler, faultHandler));
|
||||
scheduler_1 = new SequenceScheduler(tasks, this);
|
||||
scheduler_1.execute();
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Instantiation is triggered by an incoming message from peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void start()
|
||||
{
|
||||
HandleTakeOfferRequest.run(this::onResultHandleTakeOfferRequest, this::onFaultHandleTakeOfferRequest, peerAddress, messageFacade, trade.getState(), tradeId);
|
||||
state = State.HandleTakeOfferRequest;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultHandleTakeOfferRequest(Trade.State tradeState)
|
||||
{
|
||||
checkState(tradeState == Trade.State.ACCEPTED);
|
||||
|
||||
listener.onOfferAccepted(offer);
|
||||
trade.setState(tradeState);
|
||||
|
||||
messageFacade.removeOffer(offer);
|
||||
|
||||
// waiting for incoming msg from peer (-> onTakeOfferFeePayedMessage)
|
||||
}
|
||||
|
||||
public void onFaultHandleTakeOfferRequest(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onTakeOfferFeePayedMessage(TakeOfferFeePayedMessage message)
|
||||
{
|
||||
log.debug("onTakeOfferFeePayedMessage");
|
||||
getTrade().setTakeOfferFeeTxID(message.getTakeOfferFeeTxID());
|
||||
getTrade().setTradeAmount(message.getTradeAmount());
|
||||
|
||||
takeOfferFeeTxId = message.getTakeOfferFeeTxID();
|
||||
takerMultiSigPubKey = message.getTakerMultiSigPubKey();
|
||||
checkState(state == State.HandleTakeOfferRequest);
|
||||
|
||||
if (scheduler_1.getHasCompleted())
|
||||
{
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new VerifyTakeOfferFeePayment(getResultHandler(), getFaultHandler()));
|
||||
tasks.add(new CreateDepositTx(getResultHandler(), getFaultHandler()));
|
||||
tasks.add(new RequestTakerDepositPayment(getResultHandler(), getFaultHandler()));
|
||||
scheduler_2 = new SequenceScheduler(tasks, this);
|
||||
scheduler_2.execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("scheduler_1 has not completed yet.");
|
||||
}
|
||||
String takeOfferFeeTxId = message.getTakeOfferFeeTxId();
|
||||
BigInteger tradeAmount = message.getTradeAmount();
|
||||
String takerMultiSigPubKey = message.getTakerMultiSigPubKey();
|
||||
|
||||
// validate input
|
||||
checkNotNull(takeOfferFeeTxId);
|
||||
checkArgument(takeOfferFeeTxId.length() > 0);
|
||||
|
||||
checkNotNull(tradeAmount);
|
||||
// TODO make validator for amounts with testing against trades amount range
|
||||
//checkArgument(bigIntegerValidator.isValue(tradeAmount).inRangeOf(trade.getMinAmount(), trade.getAmount()));
|
||||
|
||||
checkNotNull(takerMultiSigPubKey);
|
||||
checkArgument(takerMultiSigPubKey.length() > 0);
|
||||
|
||||
state = State.onTakeOfferFeePayedMessage;
|
||||
|
||||
this.takeOfferFeeTxId = takeOfferFeeTxId;
|
||||
this.takerMultiSigPubKey = takerMultiSigPubKey;
|
||||
trade.setTakeOfferFeeTxID(takeOfferFeeTxId);
|
||||
trade.setTradeAmount(tradeAmount);
|
||||
|
||||
sequence2();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message from peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void sequence2()
|
||||
{
|
||||
VerifyTakeOfferFeePayment.run(this::onResultVerifyTakeOfferFeePayment, this::onFaultVerifyTakeOfferFeePayment, walletFacade, takeOfferFeeTxId);
|
||||
state = State.VerifyTakeOfferFeePayment;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultVerifyTakeOfferFeePayment()
|
||||
{
|
||||
BigInteger collateralAmount = trade.getCollateralAmount();
|
||||
String arbitratorPubKeyAsHex = offer.getArbitrator().getPubKeyAsHex();
|
||||
|
||||
CreateDepositTx.run(this::onResultCreateDepositTx,
|
||||
this::onFaultCreateDepositTx,
|
||||
walletFacade,
|
||||
tradeId,
|
||||
collateralAmount,
|
||||
takerMultiSigPubKey,
|
||||
arbitratorPubKeyAsHex);
|
||||
|
||||
state = State.CreateDepositTx;
|
||||
}
|
||||
|
||||
public void onFaultVerifyTakeOfferFeePayment(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onResultCreateDepositTx(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex)
|
||||
{
|
||||
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
||||
this.offererTxOutIndex = offererTxOutIndex;
|
||||
|
||||
BankAccount bankAccount = user.getBankAccount(trade.getOffer().getBankAccountId());
|
||||
String accountId = user.getAccountId();
|
||||
|
||||
RequestTakerDepositPayment.run(this::onResultRequestTakerDepositPayment,
|
||||
this::onFaultRequestTakerDepositPayment,
|
||||
peerAddress,
|
||||
messageFacade,
|
||||
tradeId,
|
||||
bankAccount,
|
||||
accountId,
|
||||
offererPubKey,
|
||||
preparedOffererDepositTxAsHex,
|
||||
offererTxOutIndex);
|
||||
|
||||
state = State.RequestTakerDepositPayment;
|
||||
}
|
||||
|
||||
public void onFaultCreateDepositTx(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onResultRequestTakerDepositPayment()
|
||||
{
|
||||
// waiting for incoming msg from peer (-> onRequestOffererPublishDepositTxMessage)
|
||||
}
|
||||
|
||||
public void onFaultRequestTakerDepositPayment(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onRequestOffererPublishDepositTxMessage(RequestOffererPublishDepositTxMessage message)
|
||||
{
|
||||
log.debug("onRequestOffererPublishDepositTxMessage");
|
||||
|
||||
checkState(state == State.RequestTakerDepositPayment);
|
||||
|
||||
checkNotNull(message);
|
||||
|
||||
//TODO validation
|
||||
|
||||
state = State.onRequestOffererPublishDepositTxMessage;
|
||||
|
||||
//TODO
|
||||
takerPayoutAddress = message.getTakerPayoutAddress();
|
||||
peersAccountId = message.getAccountId();
|
||||
peersBankAccount = message.getBankAccount();
|
||||
@ -136,50 +251,172 @@ public class OffererAsBuyerProtocol
|
||||
txScriptSigAsHex = message.getTxScriptSigAsHex();
|
||||
takerTxOutIndex = message.getTakerTxOutIndex();
|
||||
|
||||
if (scheduler_2.getHasCompleted())
|
||||
{
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new VerifyTakerAccount(getResultHandler(), getFaultHandler()));
|
||||
tasks.add(new VerifyAndSignContract(getResultHandler(), getFaultHandler()));
|
||||
tasks.add(new SignAndPublishDepositTx(getResultHandler(), getFaultHandler()));
|
||||
tasks.add(new SendDepositTxIdToTaker(getResultHandler(), getFaultHandler()));
|
||||
tasks.add(new SetupListenerForBlockChainConfirmation(getResultHandler(), getFaultHandler()));
|
||||
scheduler_3 = new SequenceScheduler(tasks, this);
|
||||
scheduler_3.execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("scheduler_2 has not completed yet.");
|
||||
}
|
||||
sequence3();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message from peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void sequence3()
|
||||
{
|
||||
VerifyTakerAccount.run(this::onResultVerifyTakerAccount, this::onFaultVerifyTakerAccount, blockChainFacade, peersAccountId, peersBankAccount);
|
||||
state = State.VerifyTakerAccount;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultVerifyTakerAccount()
|
||||
{
|
||||
String accountId = user.getAccountId();
|
||||
BigInteger tradeAmount = trade.getTradeAmount();
|
||||
String messagePubKeyAsHex = user.getMessagePubKeyAsHex();
|
||||
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountId());
|
||||
ECKey registrationKey = walletFacade.getRegistrationAddressInfo().getKey();
|
||||
|
||||
VerifyAndSignContract.run(this::onResultVerifyAndSignContract,
|
||||
this::onFaultVerifyAndSignContract,
|
||||
cryptoFacade,
|
||||
accountId,
|
||||
tradeAmount,
|
||||
takeOfferFeeTxId,
|
||||
messagePubKeyAsHex,
|
||||
offer,
|
||||
peersAccountId,
|
||||
bankAccount,
|
||||
peersBankAccount,
|
||||
takerMessagePubKey,
|
||||
peersContractAsJson,
|
||||
registrationKey);
|
||||
|
||||
state = State.VerifyAndSignContract;
|
||||
}
|
||||
|
||||
public void onFaultVerifyTakerAccount(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onResultVerifyAndSignContract(Contract contract, String contractAsJson, String signature)
|
||||
{
|
||||
trade.setContract(contract);
|
||||
trade.setContractAsJson(contractAsJson);
|
||||
trade.setContractTakerSignature(signature);
|
||||
|
||||
SignAndPublishDepositTx.run(this::onResultSignAndPublishDepositTx,
|
||||
this::onFaultSignAndPublishDepositTx,
|
||||
walletFacade,
|
||||
preparedOffererDepositTxAsHex,
|
||||
signedTakerDepositTxAsHex,
|
||||
txConnOutAsHex,
|
||||
txScriptSigAsHex,
|
||||
offererTxOutIndex,
|
||||
takerTxOutIndex);
|
||||
state = State.SignAndPublishDepositTx;
|
||||
}
|
||||
|
||||
public void onFaultVerifyAndSignContract(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onResultSignAndPublishDepositTx(Transaction transaction)
|
||||
{
|
||||
trade.setDepositTransaction(transaction);
|
||||
listener.onDepositTxPublished(transaction.getHashAsString());
|
||||
|
||||
SendDepositTxIdToTaker.run(this::onResultSendDepositTxIdToTaker, this::onFaultSendDepositTxIdToTaker, peerAddress, messageFacade, trade);
|
||||
state = State.SendDepositTxIdToTaker;
|
||||
}
|
||||
|
||||
public void onFaultSignAndPublishDepositTx(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onResultSendDepositTxIdToTaker()
|
||||
{
|
||||
SetupListenerForBlockChainConfirmation.run(this::onResultSetupListenerForBlockChainConfirmation, this::onFaultSetupListenerForBlockChainConfirmation, trade.getDepositTransaction(), listener);
|
||||
state = State.SetupListenerForBlockChainConfirmation;
|
||||
}
|
||||
|
||||
public void onFaultSendDepositTxIdToTaker(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onResultSetupListenerForBlockChainConfirmation()
|
||||
{
|
||||
// waiting for UI event (-> bankTransferInited)
|
||||
}
|
||||
|
||||
public void onFaultSetupListenerForBlockChainConfirmation(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Triggered from UI event: Button click "Bank transfer inited"
|
||||
public void onUIEventBankTransferInited()
|
||||
{
|
||||
log.debug("onUIEventBankTransferInited");
|
||||
log.debug("bankTransferInited");
|
||||
|
||||
if (scheduler_3.getHasCompleted())
|
||||
|
||||
if (state == State.SetupListenerForBlockChainConfirmation)
|
||||
{
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new SendSignedPayoutTx(getResultHandler(), getFaultHandler()));
|
||||
scheduler_4 = new SequenceScheduler(tasks, this);
|
||||
scheduler_4.execute();
|
||||
state = State.onUIEventBankTransferInited;
|
||||
sequence4();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("scheduler_3 has not completed yet.");
|
||||
log.error("Invalid state. Actual state is: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI event
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void sequence4()
|
||||
{
|
||||
SendSignedPayoutTx.run(this::onResultSendSignedPayoutTx, this::onFaultSendSignedPayoutTx, peerAddress, messageFacade, walletFacade, trade, takerPayoutAddress);
|
||||
state = State.SendSignedPayoutTx;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultSendSignedPayoutTx()
|
||||
{ // waiting for incoming msg from peer (-> onPayoutTxPublishedMessage)
|
||||
}
|
||||
|
||||
public void onFaultSendSignedPayoutTx(Throwable throwable)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void onPayoutTxPublishedMessage(PayoutTxPublishedMessage tradeMessage)
|
||||
{
|
||||
log.debug("onPayoutTxPublishedMessage");
|
||||
listener.onPayoutTxPublished(tradeMessage.getPayoutTxAsHex());
|
||||
if (state == State.SendSignedPayoutTx)
|
||||
{
|
||||
state = State.onPayoutTxPublishedMessage;
|
||||
listener.onPayoutTxPublished(tradeMessage.getPayoutTxAsHex());
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Invalid state. Actual state is: " + state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters, Setters
|
||||
// Incoming message from peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getId()
|
||||
@ -187,134 +424,35 @@ public class OffererAsBuyerProtocol
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTakeOfferFeeTxId()
|
||||
{
|
||||
return takeOfferFeeTxId;
|
||||
}
|
||||
|
||||
public String getTakerMultiSigPubKey()
|
||||
{
|
||||
return takerMultiSigPubKey;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters, Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getTakerPayoutAddress()
|
||||
enum State
|
||||
{
|
||||
return takerPayoutAddress;
|
||||
}
|
||||
Start,
|
||||
HandleTakeOfferRequest,
|
||||
|
||||
public String getPeersAccountId()
|
||||
{
|
||||
return peersAccountId;
|
||||
}
|
||||
onTakeOfferFeePayedMessage,
|
||||
|
||||
public BankAccount getPeersBankAccount()
|
||||
{
|
||||
return peersBankAccount;
|
||||
}
|
||||
VerifyTakeOfferFeePayment,
|
||||
CreateDepositTx,
|
||||
RequestTakerDepositPayment,
|
||||
|
||||
public String getTakerMessagePubKey()
|
||||
{
|
||||
return takerMessagePubKey;
|
||||
}
|
||||
onRequestOffererPublishDepositTxMessage,
|
||||
|
||||
public String getPeersContractAsJson()
|
||||
{
|
||||
return peersContractAsJson;
|
||||
}
|
||||
VerifyTakerAccount,
|
||||
VerifyAndSignContract,
|
||||
SignAndPublishDepositTx,
|
||||
SendDepositTxIdToTaker,
|
||||
SetupListenerForBlockChainConfirmation,
|
||||
|
||||
public String getSignedTakerDepositTxAsHex()
|
||||
{
|
||||
return signedTakerDepositTxAsHex;
|
||||
}
|
||||
onUIEventBankTransferInited,
|
||||
|
||||
public String getTxConnOutAsHex()
|
||||
{
|
||||
return txConnOutAsHex;
|
||||
}
|
||||
SendSignedPayoutTx,
|
||||
|
||||
public String getTxScriptSigAsHex()
|
||||
{
|
||||
return txScriptSigAsHex;
|
||||
}
|
||||
|
||||
public long getTakerTxOutIndex()
|
||||
{
|
||||
return takerTxOutIndex;
|
||||
}
|
||||
|
||||
public String getPreparedOffererDepositTxAsHex()
|
||||
{
|
||||
return preparedOffererDepositTxAsHex;
|
||||
}
|
||||
|
||||
public void setPreparedOffererDepositTxAsHex(String preparedOffererDepositTxAsHex)
|
||||
{
|
||||
this.preparedOffererDepositTxAsHex = preparedOffererDepositTxAsHex;
|
||||
}
|
||||
|
||||
public long getOffererTxOutIndex()
|
||||
{
|
||||
return offererTxOutIndex;
|
||||
}
|
||||
|
||||
public void setOffererTxOutIndex(long offererTxOutIndex)
|
||||
{
|
||||
this.offererTxOutIndex = offererTxOutIndex;
|
||||
}
|
||||
|
||||
public String getOffererPubKey()
|
||||
{
|
||||
return offererPubKey;
|
||||
}
|
||||
|
||||
public void setOffererPubKey(String offererPubKey)
|
||||
{
|
||||
this.offererPubKey = offererPubKey;
|
||||
}
|
||||
|
||||
public Trade getTrade()
|
||||
{
|
||||
return trade;
|
||||
}
|
||||
|
||||
public OffererAsBuyerProtocolListener getListener()
|
||||
{
|
||||
return listener;
|
||||
}
|
||||
|
||||
public WorkerResultHandler getResultHandler()
|
||||
{
|
||||
return resultHandler;
|
||||
}
|
||||
|
||||
public WorkerFaultHandler getFaultHandler()
|
||||
{
|
||||
return faultHandler;
|
||||
}
|
||||
|
||||
public MessageFacade getMessageFacade()
|
||||
{
|
||||
return messageFacade;
|
||||
}
|
||||
|
||||
public WalletFacade getWalletFacade()
|
||||
{
|
||||
return walletFacade;
|
||||
}
|
||||
|
||||
public BlockChainFacade getBlockChainFacade()
|
||||
{
|
||||
return blockChainFacade;
|
||||
}
|
||||
|
||||
public CryptoFacade getCryptoFacade()
|
||||
{
|
||||
return cryptoFacade;
|
||||
}
|
||||
|
||||
public User getUser()
|
||||
{
|
||||
return user;
|
||||
onPayoutTxPublishedMessage
|
||||
}
|
||||
|
||||
|
||||
@ -506,7 +644,7 @@ public class OffererAsBuyerProtocol
|
||||
|
||||
// offererPaymentProtocolListener.onProgress(getProgress());
|
||||
|
||||
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountUID());
|
||||
BankAccount bankAccount = user.getBankAccount(offer.getBankAccountId());
|
||||
String accountID = user.getAccountId();
|
||||
|
||||
TradeMessageOld tradeMessage = new TradeMessageOld(TradeMessageType.REQUEST_TAKER_DEPOSIT_PAYMENT, trade.getId(), bankAccount, accountID, offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
|
||||
@ -566,8 +704,8 @@ public class OffererAsBuyerProtocol
|
||||
Contract contract = new Contract(offer,
|
||||
trade.getTradeAmount(),
|
||||
trade.getTakeOfferFeeTxId(),
|
||||
user.getAccountID(),
|
||||
requestTradeMessage.getAccountID(),
|
||||
user.getAccountId(),
|
||||
requestTradeMessage.getAccountId(),
|
||||
user.getCurrentBankAccount(),
|
||||
requestTradeMessage.getBankAccount(),
|
||||
offer.getMessagePubKeyAsHex(),
|
@ -1,9 +1,12 @@
|
||||
package io.bitsquare.trade.payment.offerer;
|
||||
package io.bitsquare.trade.protocol.offerer;
|
||||
|
||||
import com.google.bitcoin.core.TransactionConfidence;
|
||||
import io.bitsquare.trade.Offer;
|
||||
|
||||
public interface OffererAsBuyerProtocolListener
|
||||
{
|
||||
void onOfferAccepted(Offer offer);
|
||||
|
||||
void onDepositTxPublished(String depositTxID);
|
||||
|
||||
void onDepositTxConfirmedInBlockchain();
|
@ -1,4 +1,4 @@
|
||||
package io.bitsquare.trade.payment.taker;
|
||||
package io.bitsquare.trade.protocol.taker;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
@ -6,42 +6,36 @@ import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.payment.offerer.messages.BankTransferInitedMessage;
|
||||
import io.bitsquare.trade.payment.offerer.messages.DepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.payment.offerer.messages.RequestTakerDepositPaymentMessage;
|
||||
import io.bitsquare.trade.payment.taker.tasks.*;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.BankTransferInitedMessage;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.DepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.RequestTakerDepositPaymentMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.taker.*;
|
||||
import io.bitsquare.user.User;
|
||||
import io.nucleo.scheduler.SequenceScheduler;
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//TODO use states
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static io.bitsquare.util.Validator.*;
|
||||
|
||||
public class TakerAsSellerProtocol
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(TakerAsSellerProtocol.class);
|
||||
|
||||
// provided data
|
||||
private final String id;
|
||||
private final Trade trade;
|
||||
private final TakerAsSellerProtocolListener listener;
|
||||
private final WorkerResultHandler resultHandler;
|
||||
private final WorkerFaultHandler faultHandler;
|
||||
private final MessageFacade messageFacade;
|
||||
private final WalletFacade walletFacade;
|
||||
private final BlockChainFacade blockChainFacade;
|
||||
private final CryptoFacade cryptoFacade;
|
||||
private final User user;
|
||||
// private
|
||||
private final SequenceScheduler scheduler_1;
|
||||
private final String id;
|
||||
private final Offer offer;
|
||||
private final String tradeId;
|
||||
// written/read by task
|
||||
private String payoutTxAsHex;
|
||||
private PeerAddress peerAddress;
|
||||
@ -59,20 +53,11 @@ public class TakerAsSellerProtocol
|
||||
private BigInteger offererPaybackAmount;
|
||||
private BigInteger takerPaybackAmount;
|
||||
private String offererPayoutAddress;
|
||||
private int currentStep = 0;
|
||||
private SequenceScheduler scheduler_2;
|
||||
private SequenceScheduler scheduler_3;
|
||||
private SequenceScheduler scheduler_4;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
//private
|
||||
private State state;
|
||||
|
||||
public TakerAsSellerProtocol(Trade trade,
|
||||
TakerAsSellerProtocolListener listener,
|
||||
WorkerResultHandler resultHandler,
|
||||
WorkerFaultHandler faultHandler,
|
||||
MessageFacade messageFacade,
|
||||
WalletFacade walletFacade,
|
||||
BlockChainFacade blockChainFacade,
|
||||
@ -81,263 +66,301 @@ public class TakerAsSellerProtocol
|
||||
{
|
||||
this.trade = trade;
|
||||
this.listener = listener;
|
||||
this.resultHandler = resultHandler;
|
||||
this.faultHandler = faultHandler;
|
||||
this.messageFacade = messageFacade;
|
||||
this.walletFacade = walletFacade;
|
||||
this.blockChainFacade = blockChainFacade;
|
||||
this.cryptoFacade = cryptoFacade;
|
||||
this.user = user;
|
||||
|
||||
offer = trade.getOffer();
|
||||
tradeId = trade.getId();
|
||||
|
||||
id = trade.getId();
|
||||
state = State.Init;
|
||||
}
|
||||
|
||||
log.debug("TakerAsSellerProtocol created");
|
||||
|
||||
messageFacade.addTakerPaymentProtocol(this);
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// start with first task sequence
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new GetPeerAddress(resultHandler, faultHandler));
|
||||
tasks.add(new RequestTakeOffer(resultHandler, faultHandler));
|
||||
scheduler_1 = new SequenceScheduler(tasks, this);
|
||||
scheduler_1.execute();
|
||||
// generic fault handler
|
||||
public void onFault(Throwable throwable)
|
||||
{
|
||||
listener.onFault(throwable, state);
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
String messagePubKeyAsHex = validString(offer.getMessagePubKeyAsHex());
|
||||
|
||||
GetPeerAddress.run(this::onResultGetPeerAddress, this::onFault, messageFacade, messagePubKeyAsHex);
|
||||
state = State.GetPeerAddress;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultGetPeerAddress(PeerAddress peerAddress)
|
||||
{
|
||||
this.peerAddress = validPeerAddress(peerAddress);
|
||||
|
||||
RequestTakeOffer.run(this::onResultRequestTakeOffer, this::onFault, this.peerAddress, messageFacade, tradeId);
|
||||
state = State.RequestTakeOffer;
|
||||
}
|
||||
|
||||
public void onResultRequestTakeOffer()
|
||||
{
|
||||
listener.onWaitingForPeerResponse(state);
|
||||
}
|
||||
|
||||
public void onAcceptTakeOfferRequestMessage()
|
||||
{
|
||||
log.debug("onAcceptTakeOfferRequestMessage");
|
||||
if (scheduler_1.getHasCompleted())
|
||||
{
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new PayTakeOfferFee(resultHandler, faultHandler));
|
||||
tasks.add(new SendTakeOfferFeePayedTxId(resultHandler, faultHandler));
|
||||
scheduler_2 = new SequenceScheduler(tasks, this);
|
||||
scheduler_2.execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("scheduler_1 has not completed yet.");
|
||||
}
|
||||
checkState(state == State.RequestTakeOffer);
|
||||
|
||||
PayTakeOfferFee.run(this::onResultPayTakeOfferFee, this::onFault, walletFacade, tradeId);
|
||||
state = State.PayTakeOfferFee;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message from peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OR
|
||||
public void onRejectTakeOfferRequestMessage()
|
||||
{
|
||||
log.debug("onRejectTakeOfferRequestMessage");
|
||||
if (scheduler_1.getHasCompleted())
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("scheduler_1 has not completed yet.");
|
||||
}
|
||||
checkState(state == State.RequestTakeOffer);
|
||||
|
||||
state = State.onRejectTakeOfferRequestMessage;
|
||||
listener.onTakeOfferRequestRejected(trade);
|
||||
}
|
||||
|
||||
public void onResultPayTakeOfferFee(Transaction transaction)
|
||||
{
|
||||
checkNotNull(transaction);
|
||||
String transactionId = validString(transaction.getHashAsString());
|
||||
|
||||
trade.setTakeOfferFeeTxID(transactionId);
|
||||
|
||||
String takeOfferFeeTxId = trade.getTakeOfferFeeTxId();
|
||||
BigInteger tradeAmount = trade.getTradeAmount();
|
||||
String pubKeyAsHexString = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
|
||||
|
||||
SendTakeOfferFeePayedTxId.run(this::onResultSendTakeOfferFeePayedTxId,
|
||||
this::onFault,
|
||||
peerAddress,
|
||||
messageFacade,
|
||||
tradeId,
|
||||
takeOfferFeeTxId,
|
||||
tradeAmount,
|
||||
pubKeyAsHexString);
|
||||
state = State.SendTakeOfferFeePayedTxId;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultSendTakeOfferFeePayedTxId()
|
||||
{
|
||||
listener.onWaitingForPeerResponse(state);
|
||||
}
|
||||
|
||||
public void onRequestTakerDepositPaymentMessage(RequestTakerDepositPaymentMessage message)
|
||||
{
|
||||
log.debug("onRequestTakerDepositPaymentMessage");
|
||||
peersAccountId = message.getAccountID();
|
||||
peersBankAccount = message.getBankAccount();
|
||||
offererPubKey = message.getOffererPubKey();
|
||||
preparedOffererDepositTxAsHex = message.getPreparedOffererDepositTxAsHex();
|
||||
offererTxOutIndex = message.getOffererTxOutIndex();
|
||||
|
||||
if (scheduler_2.getHasCompleted())
|
||||
{
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new VerifyOffererAccount(resultHandler, faultHandler));
|
||||
tasks.add(new CreateAndSignContract(resultHandler, faultHandler));
|
||||
tasks.add(new PayDeposit(resultHandler, faultHandler));
|
||||
tasks.add(new SendSignedTakerDepositTxAsHex(resultHandler, faultHandler));
|
||||
scheduler_3 = new SequenceScheduler(tasks, this);
|
||||
scheduler_3.execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("scheduler_2 has not completed yet.");
|
||||
}
|
||||
checkState(state == State.SendTakeOfferFeePayedTxId);
|
||||
|
||||
peersAccountId = validString(message.getAccountID());
|
||||
peersBankAccount = checkNotNull(message.getBankAccount());
|
||||
offererPubKey = validString(message.getOffererPubKey());
|
||||
preparedOffererDepositTxAsHex = validString(message.getPreparedOffererDepositTxAsHex());
|
||||
offererTxOutIndex = validNonNegativeLong(message.getOffererTxOutIndex());
|
||||
|
||||
VerifyOffererAccount.run(this::onResultVerifyOffererAccount,
|
||||
this::onFault,
|
||||
blockChainFacade,
|
||||
peersAccountId,
|
||||
peersBankAccount);
|
||||
state = State.VerifyOffererAccount;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message from peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultVerifyOffererAccount()
|
||||
{
|
||||
CreateAndSignContract.run(this::onResultCreateAndSignContract,
|
||||
this::onFault,
|
||||
cryptoFacade,
|
||||
trade,
|
||||
user,
|
||||
peersAccountId,
|
||||
peersBankAccount,
|
||||
walletFacade.getRegistrationAddressInfo().getKey());
|
||||
state = State.CreateAndSignContract;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultCreateAndSignContract()
|
||||
{
|
||||
PayDeposit.run(this::onResultPayDeposit, this::onFault, walletFacade, trade, offererPubKey, preparedOffererDepositTxAsHex);
|
||||
state = State.PayDeposit;
|
||||
}
|
||||
|
||||
public void onResultPayDeposit(Transaction signedTakerDepositTx, long takerTxOutIndex)
|
||||
{
|
||||
SendSignedTakerDepositTxAsHex.run(this::onResultSendSignedTakerDepositTxAsHex,
|
||||
this::onFault,
|
||||
peerAddress,
|
||||
messageFacade,
|
||||
walletFacade,
|
||||
trade,
|
||||
user,
|
||||
signedTakerDepositTx,
|
||||
takerTxOutIndex,
|
||||
offererTxOutIndex);
|
||||
state = State.SendSignedTakerDepositTxAsHex;
|
||||
}
|
||||
|
||||
public void onResultSendSignedTakerDepositTxAsHex()
|
||||
{
|
||||
listener.onWaitingForPeerResponse(state);
|
||||
}
|
||||
|
||||
// informational, does only trigger UI feedback/update
|
||||
public void onDepositTxPublishedMessage(DepositTxPublishedMessage message)
|
||||
{
|
||||
log.debug("onDepositTxPublishedMessage");
|
||||
String txID = getWalletFacade().takerCommitDepositTx(message.getDepositTxAsHex());
|
||||
listener.onDepositTxPublished(txID);
|
||||
if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal())
|
||||
{
|
||||
state = State.onDepositTxPublishedMessage;
|
||||
|
||||
listener.onDepositTxPublished(walletFacade.takerCommitDepositTx(message.getDepositTxAsHex()));
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Invalid state. Actual state is: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Incoming message from peer
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// informational, store data for later, does only trigger UI feedback/update
|
||||
public void onBankTransferInitedMessage(BankTransferInitedMessage tradeMessage)
|
||||
{
|
||||
log.debug("onBankTransferInitedMessage");
|
||||
|
||||
depositTxAsHex = tradeMessage.getDepositTxAsHex();
|
||||
offererSignatureR = tradeMessage.getOffererSignatureR();
|
||||
offererSignatureS = tradeMessage.getOffererSignatureS();
|
||||
offererPaybackAmount = tradeMessage.getOffererPaybackAmount();
|
||||
takerPaybackAmount = tradeMessage.getTakerPaybackAmount();
|
||||
offererPayoutAddress = tradeMessage.getOffererPayoutAddress();
|
||||
if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal())
|
||||
{
|
||||
state = State.onBankTransferInitedMessage;
|
||||
|
||||
listener.onBankTransferInited(tradeMessage.getTradeId());
|
||||
depositTxAsHex = tradeMessage.getDepositTxAsHex();
|
||||
offererSignatureR = tradeMessage.getOffererSignatureR();
|
||||
offererSignatureS = tradeMessage.getOffererSignatureS();
|
||||
offererPaybackAmount = tradeMessage.getOffererPaybackAmount();
|
||||
takerPaybackAmount = tradeMessage.getTakerPaybackAmount();
|
||||
offererPayoutAddress = tradeMessage.getOffererPayoutAddress();
|
||||
|
||||
listener.onBankTransferInited(tradeMessage.getTradeId());
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Invalid state. Actual state is: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
// User clicked the "bank transfer received" button, so we release the funds for pay out
|
||||
public void onUIEventFiatReceived()
|
||||
{
|
||||
log.debug("onUIEventFiatReceived");
|
||||
if (scheduler_3.getHasCompleted())
|
||||
|
||||
if (state.ordinal() > State.SendSignedTakerDepositTxAsHex.ordinal() && state.ordinal() < State.SignAndPublishPayoutTx.ordinal())
|
||||
{
|
||||
List<Worker> tasks = new ArrayList<>();
|
||||
tasks.add(new SignAndPublishPayoutTx(resultHandler, faultHandler));
|
||||
tasks.add(new SendPayoutTxToOfferer(resultHandler, faultHandler));
|
||||
scheduler_4 = new SequenceScheduler(tasks, this);
|
||||
scheduler_4.execute();
|
||||
state = State.onUIEventFiatReceived;
|
||||
|
||||
SignAndPublishPayoutTx.run(this::onResultSignAndPublishPayoutTx,
|
||||
this::onFault,
|
||||
walletFacade,
|
||||
trade,
|
||||
depositTxAsHex,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
offererPayoutAddress);
|
||||
state = State.SignAndPublishPayoutTx;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("scheduler_3 has not completed yet.");
|
||||
log.error("Invalid state. Actual state is: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
public void onResultSignAndPublishPayoutTx(Transaction transaction, String payoutTxAsHex)
|
||||
{
|
||||
listener.onPayoutTxPublished(trade, transaction.getHashAsString());
|
||||
|
||||
SendPayoutTxToOfferer.run(this::onResultSendPayoutTxToOfferer, this::onFault, peerAddress, messageFacade, trade, payoutTxAsHex);
|
||||
state = State.SendPayoutTxToOfferer;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tasks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onResultSendPayoutTxToOfferer()
|
||||
{
|
||||
checkState(state == State.SendPayoutTxToOfferer);
|
||||
listener.onCompleted(state);
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters, Setters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getId()
|
||||
public enum State
|
||||
{
|
||||
return id;
|
||||
Init,
|
||||
GetPeerAddress,
|
||||
RequestTakeOffer,
|
||||
PayTakeOfferFee,
|
||||
onRejectTakeOfferRequestMessage,
|
||||
SendTakeOfferFeePayedTxId,
|
||||
VerifyOffererAccount,
|
||||
CreateAndSignContract,
|
||||
PayDeposit,
|
||||
SendSignedTakerDepositTxAsHex,
|
||||
onDepositTxPublishedMessage,
|
||||
onBankTransferInitedMessage,
|
||||
onUIEventFiatReceived,
|
||||
SignAndPublishPayoutTx,
|
||||
SendPayoutTxToOfferer
|
||||
}
|
||||
|
||||
public Trade getTrade()
|
||||
{
|
||||
return trade;
|
||||
}
|
||||
|
||||
public TakerAsSellerProtocolListener getListener()
|
||||
{
|
||||
return listener;
|
||||
}
|
||||
|
||||
public MessageFacade getMessageFacade()
|
||||
{
|
||||
return messageFacade;
|
||||
}
|
||||
|
||||
public WalletFacade getWalletFacade()
|
||||
{
|
||||
return walletFacade;
|
||||
}
|
||||
|
||||
public BlockChainFacade getBlockChainFacade()
|
||||
{
|
||||
return blockChainFacade;
|
||||
}
|
||||
|
||||
public CryptoFacade getCryptoFacade()
|
||||
{
|
||||
return cryptoFacade;
|
||||
}
|
||||
|
||||
public User getUser()
|
||||
{
|
||||
return user;
|
||||
}
|
||||
|
||||
public PeerAddress getPeerAddress()
|
||||
{
|
||||
return peerAddress;
|
||||
}
|
||||
|
||||
public void setPeerAddress(PeerAddress peerAddress)
|
||||
{
|
||||
this.peerAddress = peerAddress;
|
||||
}
|
||||
|
||||
public Transaction getSignedTakerDepositTx()
|
||||
{
|
||||
return signedTakerDepositTx;
|
||||
}
|
||||
|
||||
public void setSignedTakerDepositTx(Transaction signedTakerDepositTx)
|
||||
{
|
||||
this.signedTakerDepositTx = signedTakerDepositTx;
|
||||
}
|
||||
|
||||
public long getTakerTxOutIndex()
|
||||
{
|
||||
return takerTxOutIndex;
|
||||
}
|
||||
|
||||
public void setTakerTxOutIndex(long takerTxOutIndex)
|
||||
{
|
||||
this.takerTxOutIndex = takerTxOutIndex;
|
||||
}
|
||||
|
||||
public String getPeersAccountId()
|
||||
{
|
||||
return peersAccountId;
|
||||
}
|
||||
|
||||
public BankAccount getPeersBankAccount()
|
||||
{
|
||||
return peersBankAccount;
|
||||
}
|
||||
|
||||
public String getOffererPubKey()
|
||||
{
|
||||
return offererPubKey;
|
||||
}
|
||||
|
||||
public String getPreparedOffererDepositTxAsHex()
|
||||
{
|
||||
return preparedOffererDepositTxAsHex;
|
||||
}
|
||||
|
||||
public long getOffererTxOutIndex()
|
||||
{
|
||||
return offererTxOutIndex;
|
||||
}
|
||||
|
||||
public String getDepositTxAsHex()
|
||||
{
|
||||
return depositTxAsHex;
|
||||
}
|
||||
|
||||
public String getOffererSignatureR()
|
||||
{
|
||||
return offererSignatureR;
|
||||
}
|
||||
|
||||
public String getOffererSignatureS()
|
||||
{
|
||||
return offererSignatureS;
|
||||
}
|
||||
|
||||
public BigInteger getOffererPaybackAmount()
|
||||
{
|
||||
return offererPaybackAmount;
|
||||
}
|
||||
|
||||
public BigInteger getTakerPaybackAmount()
|
||||
{
|
||||
return takerPaybackAmount;
|
||||
}
|
||||
|
||||
public String getOffererPayoutAddress()
|
||||
{
|
||||
return offererPayoutAddress;
|
||||
}
|
||||
|
||||
public String getPayoutTxAsHex()
|
||||
{
|
||||
return payoutTxAsHex;
|
||||
}
|
||||
|
||||
public void setPayoutTxAsHex(String payoutTxAsHex)
|
||||
{
|
||||
this.payoutTxAsHex = payoutTxAsHex;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Step 1.1
|
||||
@ -774,7 +797,7 @@ public class TakerAsSellerProtocol
|
||||
{
|
||||
System.out.println("######### 3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
||||
log.debug("3.12 onSuccess walletFacade.takerSignsAndSendsTx " + transaction);
|
||||
listener.onTradeCompleted(transaction.getHashAsString());
|
||||
listener.onPayoutTxPublished(transaction.getHashAsString());
|
||||
|
||||
sendPayoutTxToOfferer(Utils.bytesToHexString(transaction.bitcoinSerialize()));
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.bitsquare.trade.protocol.taker;
|
||||
|
||||
import io.bitsquare.trade.Trade;
|
||||
|
||||
public interface TakerAsSellerProtocolListener
|
||||
{
|
||||
void onDepositTxPublished(String depositTxId);
|
||||
|
||||
void onBankTransferInited(String tradeId);
|
||||
|
||||
void onPayoutTxPublished(Trade trade, String hashAsString);
|
||||
|
||||
void onFault(Throwable throwable, TakerAsSellerProtocol.State state);
|
||||
|
||||
void onWaitingForPeerResponse(TakerAsSellerProtocol.State state);
|
||||
|
||||
void onCompleted(TakerAsSellerProtocol.State state);
|
||||
|
||||
void onTakeOfferRequestRejected(Trade trade);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package io.bitsquare.trade.protocol.tasks;
|
||||
|
||||
public interface FaultHandler
|
||||
{
|
||||
void onFault(Throwable throwable);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package io.bitsquare.trade.protocol.tasks;
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult();
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import java.math.BigInteger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateDepositTx
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateDepositTx.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
WalletFacade walletFacade,
|
||||
String tradeId,
|
||||
BigInteger collateralAmount,
|
||||
String takerMultiSigPubKey,
|
||||
String arbitratorPubKeyAsHex)
|
||||
{
|
||||
try
|
||||
{
|
||||
String offererPubKey = walletFacade.getAddressInfoByTradeID(tradeId).getPubKeyAsHexString();
|
||||
Transaction transaction = walletFacade.offererCreatesMSTxAndAddPayment(collateralAmount,
|
||||
offererPubKey,
|
||||
takerMultiSigPubKey,
|
||||
arbitratorPubKeyAsHex,
|
||||
tradeId);
|
||||
|
||||
String preparedOffererDepositTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize());
|
||||
long offererTxOutIndex = transaction.getInput(0).getOutpoint().getIndex();
|
||||
|
||||
resultHandler.onResult(offererPubKey, preparedOffererDepositTxAsHex, offererTxOutIndex);
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
log.error("Create deposit tx faultHandler.onFault due InsufficientMoneyException " + e);
|
||||
faultHandler.onFault(new Exception("Create deposit tx faultHandler.onFault due InsufficientMoneyException " + e));
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(String offererPubKey, String preparedOffererDepositTxAsHex, long offererTxOutIndex);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.AcceptTakeOfferRequestMessage;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.RejectTakeOfferRequestMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class HandleTakeOfferRequest
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(HandleTakeOfferRequest.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade.State tradeState, String tradeId)
|
||||
{
|
||||
if (tradeState == Trade.State.OPEN)
|
||||
{
|
||||
messageFacade.sendTradeMessage(peerAddress, new AcceptTakeOfferRequestMessage(tradeId), new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("AcceptTakeOfferRequestMessage successfully arrived at peer");
|
||||
resultHandler.onResult(Trade.State.ACCEPTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("AcceptTakeOfferRequestMessage faultHandler.onFault to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
RejectTakeOfferRequestMessage msg = new RejectTakeOfferRequestMessage(tradeId);
|
||||
messageFacade.sendTradeMessage(peerAddress, msg, new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RejectTakeOfferRequestMessage successfully arrived at peer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RejectTakeOfferRequestMessage faultHandler.onFault to arrive at peer");
|
||||
}
|
||||
});
|
||||
|
||||
log.error("Offer not marked as open.");
|
||||
faultHandler.onFault(new Exception("Offer not marked as open."));
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(Trade.State tradeState);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.RequestTakerDepositPaymentMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RequestTakerDepositPayment
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(RequestTakerDepositPayment.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
PeerAddress peerAddress,
|
||||
MessageFacade messageFacade,
|
||||
String tradeId,
|
||||
BankAccount bankAccount,
|
||||
String accountId,
|
||||
String offererPubKey,
|
||||
String preparedOffererDepositTxAsHex,
|
||||
long offererTxOutIndex)
|
||||
{
|
||||
RequestTakerDepositPaymentMessage tradeMessage = new RequestTakerDepositPaymentMessage(tradeId,
|
||||
bankAccount,
|
||||
accountId,
|
||||
offererPubKey,
|
||||
preparedOffererDepositTxAsHex,
|
||||
offererTxOutIndex);
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RequestTakerDepositPaymentMessage successfully arrived at peer");
|
||||
resultHandler.onResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RequestTakerDepositPaymentMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("RequestTakerDepositPaymentMessage faultHandler.onFault to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.DepositTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendDepositTxIdToTaker
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendDepositTxIdToTaker.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade trade)
|
||||
{
|
||||
DepositTxPublishedMessage tradeMessage = new DepositTxPublishedMessage(trade.getId(), Utils.bytesToHexString(trade.getDepositTransaction().bitcoinSerialize()));
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("DepositTxPublishedMessage successfully arrived at peer");
|
||||
resultHandler.onResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("DepositTxPublishedMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("DepositTxPublishedMessage faultHandler.onFault to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +1,57 @@
|
||||
package io.bitsquare.trade.payment.offerer.tasks;
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import com.google.bitcoin.core.ECKey;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import io.bitsquare.msg.listeners.TradeMessageListener;
|
||||
import io.bitsquare.trade.payment.offerer.messages.BankTransferInitedMessage;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.messages.offerer.BankTransferInitedMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import java.math.BigInteger;
|
||||
import javafx.util.Pair;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendSignedPayoutTx extends AbstractOffererAsBuyerTask
|
||||
public class SendSignedPayoutTx
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendSignedPayoutTx.class);
|
||||
|
||||
public SendSignedPayoutTx(WorkerResultHandler resultHandler, WorkerFaultHandler faultHandler)
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
PeerAddress peerAddress,
|
||||
MessageFacade messageFacade,
|
||||
WalletFacade walletFacade,
|
||||
Trade trade,
|
||||
String takerPayoutAddress)
|
||||
{
|
||||
super(resultHandler, faultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
log.trace("execute");
|
||||
|
||||
try
|
||||
{
|
||||
Transaction depositTransaction = sharedModel.getTrade().getDepositTransaction();
|
||||
BigInteger collateral = sharedModel.getTrade().getCollateralAmount();
|
||||
BigInteger offererPaybackAmount = sharedModel.getTrade().getTradeAmount().add(collateral);
|
||||
Transaction depositTransaction = trade.getDepositTransaction();
|
||||
BigInteger collateral = trade.getCollateralAmount();
|
||||
BigInteger offererPaybackAmount = trade.getTradeAmount().add(collateral);
|
||||
BigInteger takerPaybackAmount = collateral;
|
||||
|
||||
log.trace("offererPaybackAmount " + offererPaybackAmount);
|
||||
log.trace("takerPaybackAmount " + takerPaybackAmount);
|
||||
log.trace("depositTransaction.getHashAsString() " + depositTransaction.getHashAsString());
|
||||
log.trace("takerPayoutAddress " + sharedModel.getTakerPayoutAddress());
|
||||
log.trace("takerPayoutAddress " + takerPayoutAddress);
|
||||
|
||||
Pair<ECKey.ECDSASignature, String> result = sharedModel.getWalletFacade().offererCreatesAndSignsPayoutTx(depositTransaction.getHashAsString(),
|
||||
Pair<ECKey.ECDSASignature, String> result = walletFacade.offererCreatesAndSignsPayoutTx(depositTransaction.getHashAsString(),
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
sharedModel.getTakerPayoutAddress(),
|
||||
sharedModel.getTrade().getId());
|
||||
takerPayoutAddress,
|
||||
trade.getId());
|
||||
|
||||
ECKey.ECDSASignature offererSignature = result.getKey();
|
||||
String offererSignatureR = offererSignature.r.toString();
|
||||
String offererSignatureS = offererSignature.s.toString();
|
||||
String depositTxAsHex = result.getValue();
|
||||
String offererPayoutAddress = sharedModel.getWalletFacade().getAddressInfoByTradeID(sharedModel.getTrade().getId()).getAddressString();
|
||||
String offererPayoutAddress = walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString();
|
||||
|
||||
BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(sharedModel.getTrade().getId(),
|
||||
BankTransferInitedMessage tradeMessage = new BankTransferInitedMessage(trade.getId(),
|
||||
depositTxAsHex,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
@ -64,28 +66,27 @@ public class SendSignedPayoutTx extends AbstractOffererAsBuyerTask
|
||||
log.trace("takerPaybackAmount " + takerPaybackAmount);
|
||||
log.trace("offererPayoutAddress " + offererPayoutAddress);
|
||||
|
||||
sharedModel.getMessageFacade().sendTradeMessage(sharedModel.peerAddress, tradeMessage, new TradeMessageListener()
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("BankTransferInitedMessage successfully arrived at peer");
|
||||
complete();
|
||||
resultHandler.onResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("BankTransferInitedMessage failed to arrive at peer");
|
||||
failed(new Exception("BankTransferInitedMessage failed to arrive at peer"));
|
||||
log.error("BankTransferInitedMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("BankTransferInitedMessage faultHandler.onFault to arrive at peer"));
|
||||
|
||||
}
|
||||
});
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.error("Exception at OffererCreatesAndSignsPayoutTx " + e);
|
||||
failed(e);
|
||||
faultHandler.onFault(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.TransactionConfidence;
|
||||
import io.bitsquare.trade.protocol.offerer.OffererAsBuyerProtocolListener;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SetupListenerForBlockChainConfirmation
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, Transaction depositTransaction, OffererAsBuyerProtocolListener listener)
|
||||
{ //TODO
|
||||
// sharedModel.offererPaymentProtocolListener.onDepositTxConfirmedInBlockchain();
|
||||
|
||||
depositTransaction.getConfidence().addEventListener(new TransactionConfidence.Listener()
|
||||
{
|
||||
@Override
|
||||
public void onConfidenceChanged(Transaction tx, ChangeReason reason)
|
||||
{
|
||||
log.trace("onConfidenceChanged " + tx.getConfidence());
|
||||
if (reason == ChangeReason.SEEN_PEERS)
|
||||
{
|
||||
listener.onDepositTxConfirmedUpdate(tx.getConfidence());
|
||||
}
|
||||
if (reason == ChangeReason.TYPE && tx.getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING)
|
||||
{
|
||||
listener.onDepositTxConfirmedInBlockchain();
|
||||
depositTransaction.getConfidence().removeEventListener(this);
|
||||
log.trace("Tx is in blockchain");
|
||||
resultHandler.onResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SignAndPublishDepositTx
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishDepositTx.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
WalletFacade walletFacade,
|
||||
String preparedOffererDepositTxAsHex,
|
||||
String signedTakerDepositTxAsHex,
|
||||
String txConnOutAsHex,
|
||||
String txScriptSigAsHex,
|
||||
long offererTxOutIndex,
|
||||
long takerTxOutIndex)
|
||||
{
|
||||
try
|
||||
{
|
||||
walletFacade.offererSignAndPublishTx(preparedOffererDepositTxAsHex,
|
||||
signedTakerDepositTxAsHex,
|
||||
txConnOutAsHex,
|
||||
txScriptSigAsHex,
|
||||
offererTxOutIndex,
|
||||
takerTxOutIndex,
|
||||
new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.trace("offererSignAndPublishTx succeeded " + transaction);
|
||||
resultHandler.onResult(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("offererSignAndPublishTx faultHandler.onFault:" + t);
|
||||
faultHandler.onFault(t);
|
||||
}
|
||||
});
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.error("offererSignAndPublishTx faultHandler.onFault:" + e);
|
||||
faultHandler.onFault(e);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(Transaction transaction);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import com.google.bitcoin.core.ECKey;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.trade.Offer;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.util.Utilities;
|
||||
import java.math.BigInteger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyAndSignContract
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyAndSignContract.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
CryptoFacade cryptoFacade,
|
||||
String accountId,
|
||||
BigInteger tradeAmount,
|
||||
String takeOfferFeeTxId,
|
||||
String messagePubKeyAsHex,
|
||||
Offer offer,
|
||||
String peersAccountId,
|
||||
BankAccount bankAccount,
|
||||
BankAccount peersBankAccount,
|
||||
String takerMessagePubKey,
|
||||
String peersContractAsJson,
|
||||
ECKey registrationKey)
|
||||
{
|
||||
Contract contract = new Contract(offer,
|
||||
tradeAmount,
|
||||
takeOfferFeeTxId,
|
||||
accountId,
|
||||
peersAccountId,
|
||||
bankAccount,
|
||||
peersBankAccount,
|
||||
messagePubKeyAsHex,
|
||||
takerMessagePubKey);
|
||||
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
// log.trace("Offerer contract created: " + contract);
|
||||
// log.trace("Offerers contractAsJson: " + contractAsJson);
|
||||
// log.trace("Takers contractAsJson: " + sharedModel.peersContractAsJson);
|
||||
if (contractAsJson.equals(peersContractAsJson))
|
||||
{
|
||||
log.trace("The 2 contracts as json does match");
|
||||
String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
|
||||
//log.trace("signature: " + signature);
|
||||
|
||||
resultHandler.onResult(contract, contractAsJson, signature);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO use diff output as feedback ?
|
||||
log.error("Contracts are not matching.");
|
||||
log.error("Offerers contractAsJson: " + contractAsJson);
|
||||
log.error("Takers contractAsJson: " + peersContractAsJson);
|
||||
|
||||
faultHandler.onFault(new Exception("Contracts are not matching"));
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(Contract contract, String contractAsJson, String signature);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyTakeOfferFeePayment
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyTakeOfferFeePayment.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, WalletFacade walletFacade, String takeOfferFeeTxId)
|
||||
{ //TODO mocked yet, need a confidence listeners
|
||||
int numOfPeersSeenTx = walletFacade.getNumOfPeersSeenTx(takeOfferFeeTxId);
|
||||
if (numOfPeersSeenTx > 2)
|
||||
{
|
||||
resultHandler.onResult();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package io.bitsquare.trade.protocol.tasks.offerer;
|
||||
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyTakerAccount
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyTakerAccount.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount)
|
||||
{
|
||||
//TODO mocked yet
|
||||
if (blockChainFacade.verifyAccountRegistration())
|
||||
{
|
||||
if (blockChainFacade.isAccountBlackListed(peersAccountId, peersBankAccount))
|
||||
{
|
||||
log.error("Taker is blacklisted");
|
||||
faultHandler.onFault(new Exception("Taker is blacklisted"));
|
||||
}
|
||||
else
|
||||
{
|
||||
resultHandler.onResult();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Account registration validation for peer faultHandler.onFault.");
|
||||
faultHandler.onFault(new Exception("Account registration validation for peer faultHandler.onFault."));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import com.google.bitcoin.core.ECKey;
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.crypto.CryptoFacade;
|
||||
import io.bitsquare.trade.Contract;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import io.bitsquare.user.User;
|
||||
import io.bitsquare.util.Utilities;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CreateAndSignContract
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(CreateAndSignContract.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
CryptoFacade cryptoFacade,
|
||||
Trade trade,
|
||||
User user,
|
||||
String peersAccountId,
|
||||
BankAccount peersBankAccount,
|
||||
ECKey registrationKey)
|
||||
{
|
||||
try
|
||||
{
|
||||
Contract contract = new Contract(trade.getOffer(),
|
||||
trade.getTradeAmount(),
|
||||
trade.getTakeOfferFeeTxId(),
|
||||
peersAccountId,
|
||||
user.getAccountId(),
|
||||
peersBankAccount,
|
||||
user.getCurrentBankAccount(),
|
||||
trade.getOffer().getMessagePubKeyAsHex(),
|
||||
user.getMessagePubKeyAsHex()
|
||||
);
|
||||
|
||||
String contractAsJson = Utilities.objectToJson(contract);
|
||||
String signature = cryptoFacade.signContract(registrationKey, contractAsJson);
|
||||
//log.trace("contract: " + contract);
|
||||
//log.debug("contractAsJson: " + contractAsJson);
|
||||
//log.trace("contract signature: " + signature);
|
||||
|
||||
trade.setContract(contract);
|
||||
trade.setContractAsJson(contractAsJson);
|
||||
trade.setContractTakerSignature(signature);
|
||||
|
||||
resultHandler.onResult();
|
||||
} catch (Throwable t)
|
||||
{
|
||||
log.error("Exception at sign contract " + t);
|
||||
faultHandler.onFault(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.GetPeerAddressListener;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GetPeerAddress
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, MessageFacade messageFacade, String messagePubKeyAsHex)
|
||||
{
|
||||
messageFacade.getPeerAddress(messagePubKeyAsHex, new GetPeerAddressListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult(PeerAddress peerAddress)
|
||||
{
|
||||
log.trace("Received address = " + peerAddress.toString());
|
||||
resultHandler.onResult(peerAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("Lookup for peer address faultHandler.onFault.");
|
||||
faultHandler.onFault(new Exception("Lookup for peer address faultHandler.onFault."));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(PeerAddress peerAddress);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import java.math.BigInteger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PayDeposit
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PayDeposit.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, WalletFacade walletFacade, Trade trade, String offererPubKey, String preparedOffererDepositTxAsHex)
|
||||
{
|
||||
try
|
||||
{
|
||||
BigInteger collateralAmount = trade.getCollateralAmount();
|
||||
Transaction signedTakerDepositTx = walletFacade.takerAddPaymentAndSignTx(trade.getTradeAmount().add(collateralAmount),
|
||||
trade.getTradeAmount().add(collateralAmount).add(collateralAmount),
|
||||
offererPubKey,
|
||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getPubKeyAsHexString(),
|
||||
trade.getOffer().getArbitrator().getPubKeyAsHex(),
|
||||
preparedOffererDepositTxAsHex,
|
||||
trade.getId());
|
||||
|
||||
log.trace("sharedModel.signedTakerDepositTx: " + signedTakerDepositTx);
|
||||
long takerTxOutIndex = signedTakerDepositTx.getInput(1).getOutpoint().getIndex();
|
||||
|
||||
resultHandler.onResult(signedTakerDepositTx, takerTxOutIndex);
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
log.error("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e);
|
||||
faultHandler.onFault(new Exception("Pay deposit faultHandler.onFault due InsufficientMoneyException " + e));
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(Transaction signedTakerDepositTx, long takerTxOutIndex);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import com.google.bitcoin.core.InsufficientMoneyException;
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PayTakeOfferFee
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PayTakeOfferFee.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, WalletFacade walletFacade, String tradeId)
|
||||
{
|
||||
log.trace("execute");
|
||||
try
|
||||
{
|
||||
walletFacade.payTakeOfferFee(tradeId, new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.debug("Take offer fee paid successfully. Transaction ID = " + transaction.getHashAsString());
|
||||
resultHandler.onResult(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("Take offer fee paid faultHandler.onFault with exception: " + t);
|
||||
faultHandler.onFault(new Exception("Take offer fee paid faultHandler.onFault with exception: " + t));
|
||||
}
|
||||
});
|
||||
} catch (InsufficientMoneyException e)
|
||||
{
|
||||
log.error("Take offer fee paid faultHandler.onFault due InsufficientMoneyException " + e);
|
||||
faultHandler.onFault(new Exception("Take offer fee paid faultHandler.onFault due InsufficientMoneyException " + e));
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(Transaction transaction);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.protocol.messages.taker.RequestTakeOfferMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RequestTakeOffer
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(RequestTakeOffer.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, String tradeId)
|
||||
{
|
||||
messageFacade.sendTradeMessage(peerAddress, new RequestTakeOfferMessage(tradeId), new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RequestTakeOfferMessage successfully arrived at peer");
|
||||
resultHandler.onResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RequestTakeOfferMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("RequestTakeOfferMessage faultHandler.onFault to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.messages.taker.PayoutTxPublishedMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendPayoutTxToOfferer
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendPayoutTxToOfferer.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, PeerAddress peerAddress, MessageFacade messageFacade, Trade trade, String payoutTxAsHex)
|
||||
{
|
||||
PayoutTxPublishedMessage tradeMessage = new PayoutTxPublishedMessage(trade.getId(), payoutTxAsHex);
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("PayoutTxPublishedMessage successfully arrived at peer");
|
||||
resultHandler.onResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("PayoutTxPublishedMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("PayoutTxPublishedMessage faultHandler.onFault to arrive at peer"));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.messages.taker.RequestOffererPublishDepositTxMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import io.bitsquare.user.User;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendSignedTakerDepositTxAsHex
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendSignedTakerDepositTxAsHex.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
PeerAddress peerAddress,
|
||||
MessageFacade messageFacade,
|
||||
WalletFacade walletFacade,
|
||||
Trade trade,
|
||||
User user,
|
||||
Transaction signedTakerDepositTx,
|
||||
long takerTxOutIndex,
|
||||
long offererTxOutIndex)
|
||||
{
|
||||
RequestOffererPublishDepositTxMessage tradeMessage = new RequestOffererPublishDepositTxMessage(trade.getId(),
|
||||
user.getCurrentBankAccount(),
|
||||
user.getAccountId(),
|
||||
user.getMessagePubKeyAsHex(),
|
||||
Utils.bytesToHexString(signedTakerDepositTx.bitcoinSerialize()),
|
||||
Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getScriptBytes()),
|
||||
Utils.bytesToHexString(signedTakerDepositTx.getInput(1).getConnectedOutput().getParentTransaction().bitcoinSerialize()),
|
||||
trade.getContractAsJson(),
|
||||
trade.getTakerSignature(),
|
||||
walletFacade.getAddressInfoByTradeID(trade.getId()).getAddressString(),
|
||||
takerTxOutIndex,
|
||||
offererTxOutIndex);
|
||||
messageFacade.sendTradeMessage(peerAddress, tradeMessage, new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("RequestOffererDepositPublicationMessage successfully arrived at peer");
|
||||
resultHandler.onResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("RequestOffererDepositPublicationMessage faultHandler.onFault to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import io.bitsquare.msg.MessageFacade;
|
||||
import io.bitsquare.msg.listeners.OutgoingTradeMessageListener;
|
||||
import io.bitsquare.trade.protocol.messages.taker.TakeOfferFeePayedMessage;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import java.math.BigInteger;
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SendTakeOfferFeePayedTxId
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SendTakeOfferFeePayedTxId.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
PeerAddress peerAddress,
|
||||
MessageFacade messageFacade,
|
||||
String tradeId,
|
||||
String takeOfferFeeTxId,
|
||||
BigInteger tradeAmount,
|
||||
String pubKeyAsHexString)
|
||||
{
|
||||
TakeOfferFeePayedMessage msg = new TakeOfferFeePayedMessage(tradeId,
|
||||
takeOfferFeeTxId,
|
||||
tradeAmount,
|
||||
pubKeyAsHexString);
|
||||
|
||||
messageFacade.sendTradeMessage(peerAddress, msg, new OutgoingTradeMessageListener()
|
||||
{
|
||||
@Override
|
||||
public void onResult()
|
||||
{
|
||||
log.trace("TakeOfferFeePayedMessage successfully arrived at peer");
|
||||
resultHandler.onResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailed()
|
||||
{
|
||||
log.error("TakeOfferFeePayedMessage faultHandler.onFault to arrive at peer");
|
||||
faultHandler.onFault(new Exception("TakeOfferFeePayedMessage faultHandler.onFault to arrive at peer"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import com.google.bitcoin.core.Transaction;
|
||||
import com.google.bitcoin.core.Utils;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import io.bitsquare.btc.WalletFacade;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import java.math.BigInteger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SignAndPublishPayoutTx
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SignAndPublishPayoutTx.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler,
|
||||
FaultHandler faultHandler,
|
||||
WalletFacade walletFacade,
|
||||
Trade trade,
|
||||
String depositTxAsHex,
|
||||
String offererSignatureR,
|
||||
String offererSignatureS,
|
||||
BigInteger offererPaybackAmount,
|
||||
BigInteger takerPaybackAmount,
|
||||
String offererPayoutAddress
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
walletFacade.takerSignsAndSendsTx(depositTxAsHex,
|
||||
offererSignatureR,
|
||||
offererSignatureS,
|
||||
offererPaybackAmount,
|
||||
takerPaybackAmount,
|
||||
offererPayoutAddress,
|
||||
trade.getId(),
|
||||
new FutureCallback<Transaction>()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction)
|
||||
{
|
||||
log.debug("takerSignsAndSendsTx " + transaction);
|
||||
String payoutTxAsHex = Utils.bytesToHexString(transaction.bitcoinSerialize());
|
||||
resultHandler.onResult(transaction, payoutTxAsHex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t)
|
||||
{
|
||||
log.error("Exception at takerSignsAndSendsTx " + t);
|
||||
faultHandler.onFault(t);
|
||||
}
|
||||
});
|
||||
} catch (Exception e)
|
||||
{
|
||||
log.error("Exception at takerSignsAndSendsTx " + e);
|
||||
faultHandler.onFault(e);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ResultHandler
|
||||
{
|
||||
void onResult(Transaction transaction, String payoutTxAsHex);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package io.bitsquare.trade.protocol.tasks.taker;
|
||||
|
||||
import io.bitsquare.bank.BankAccount;
|
||||
import io.bitsquare.btc.BlockChainFacade;
|
||||
import io.bitsquare.trade.protocol.tasks.FaultHandler;
|
||||
import io.bitsquare.trade.protocol.tasks.ResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VerifyOffererAccount
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(VerifyOffererAccount.class);
|
||||
|
||||
public static void run(ResultHandler resultHandler, FaultHandler faultHandler, BlockChainFacade blockChainFacade, String peersAccountId, BankAccount peersBankAccount)
|
||||
{
|
||||
//TODO mocked yet
|
||||
if (blockChainFacade.verifyAccountRegistration())
|
||||
{
|
||||
if (blockChainFacade.isAccountBlackListed(peersAccountId, peersBankAccount))
|
||||
{
|
||||
log.error("Offerer is blacklisted");
|
||||
faultHandler.onFault(new Exception("Offerer is blacklisted"));
|
||||
}
|
||||
else
|
||||
{
|
||||
resultHandler.onResult();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.error("Account Registration for peer faultHandler.onFault.");
|
||||
faultHandler.onFault(new Exception("Account Registration for peer faultHandler.onFault."));
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ public class User implements Serializable
|
||||
{
|
||||
if (savedUser != null)
|
||||
{
|
||||
accountID = savedUser.getAccountID();
|
||||
accountID = savedUser.getAccountId();
|
||||
messagePubKeyAsHex = savedUser.getMessagePubKeyAsHex();
|
||||
isOnline = savedUser.getIsOnline();
|
||||
bankAccounts = savedUser.getBankAccounts();
|
||||
@ -92,7 +92,7 @@ public class User implements Serializable
|
||||
}
|
||||
|
||||
|
||||
public String getAccountID()
|
||||
public String getAccountId()
|
||||
{
|
||||
return accountID;
|
||||
}
|
||||
|
34
src/main/java/io/bitsquare/util/Validator.java
Normal file
34
src/main/java/io/bitsquare/util/Validator.java
Normal file
@ -0,0 +1,34 @@
|
||||
package io.bitsquare.util;
|
||||
|
||||
import net.tomp2p.peers.PeerAddress;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class Validator
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(Validator.class);
|
||||
|
||||
public static String validString(String value)
|
||||
{
|
||||
checkNotNull(value);
|
||||
checkArgument(value.length() > 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static long validNonNegativeLong(long value)
|
||||
{
|
||||
checkArgument(value >= 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static PeerAddress validPeerAddress(PeerAddress value)
|
||||
{
|
||||
checkNotNull(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package io.nucleo.scheduler;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import io.nucleo.scheduler.worker.AbstractWorker;
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractScheduler extends AbstractWorker implements WorkerResultHandler, WorkerFaultHandler
|
||||
{
|
||||
protected List<Worker> workerElements = new ArrayList<>();
|
||||
|
||||
public void setWorkers(@NotNull List<Worker> workerElements)
|
||||
{
|
||||
this.workerElements = workerElements;
|
||||
}
|
||||
|
||||
protected void executeWorker(Worker worker)
|
||||
{
|
||||
((AbstractWorker) worker).setModel(model);
|
||||
worker.addResultHandlers(this);
|
||||
worker.addFaultHandlers(this);
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
public void onResult()
|
||||
{
|
||||
}
|
||||
|
||||
public void onFault(Throwable throwable)
|
||||
{
|
||||
failed(throwable);
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package io.nucleo.scheduler;
|
||||
|
||||
import io.nucleo.scheduler.tasks.AbstractDependencyManagedTask;
|
||||
import io.nucleo.scheduler.worker.AbstractWorker;
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import java.util.function.Predicate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Not tested yet as not used...
|
||||
*/
|
||||
public class DependencyManagedScheduler extends AbstractScheduler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(DependencyManagedScheduler.class);
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
if (workerElements.size() > 0)
|
||||
workerElements.stream().forEach(this::executeWorker);
|
||||
else
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeWorker(Worker worker)
|
||||
{
|
||||
((AbstractWorker) worker).setModel(model);
|
||||
if (((AbstractDependencyManagedTask) worker).areAllDependenciesAvailable())
|
||||
{
|
||||
worker.addResultHandlers(this);
|
||||
worker.addFaultHandlers(this);
|
||||
worker.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(Worker worker)
|
||||
{
|
||||
Predicate<Worker> notCompleted = w -> !w.getHasCompleted();
|
||||
if (workerElements.stream().filter(notCompleted).count() == 0)
|
||||
complete();
|
||||
else
|
||||
execute();
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package io.nucleo.scheduler;
|
||||
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import java.util.function.Predicate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Not tested yet as not used...
|
||||
*/
|
||||
public class ParallelScheduler extends AbstractScheduler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(ParallelScheduler.class);
|
||||
private long numberOfChildrenCompleted;
|
||||
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
if (workerElements.size() > 0)
|
||||
workerElements.stream().forEach(this::executeWorker);
|
||||
else
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(Worker worker)
|
||||
{
|
||||
Predicate<Worker> notCompleted = w -> !w.getHasCompleted();
|
||||
if (workerElements.stream().filter(notCompleted).count() == 0)
|
||||
complete();
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package io.nucleo.scheduler;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class SequenceScheduler extends AbstractScheduler
|
||||
{
|
||||
private Iterator<Worker> workerIterator;
|
||||
|
||||
public SequenceScheduler(List<Worker> workerElements, Object model)
|
||||
{
|
||||
setWorkers(workerElements);
|
||||
setModel(model);
|
||||
}
|
||||
|
||||
public SequenceScheduler()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorkers(@NotNull List<Worker> workerElements)
|
||||
{
|
||||
workerIterator = new LinkedList<>(workerElements).iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
if (workerIterator != null && workerIterator.hasNext())
|
||||
executeWorker(workerIterator.next());
|
||||
else
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(Worker worker)
|
||||
{
|
||||
execute();
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package io.nucleo.scheduler.example;
|
||||
|
||||
import io.nucleo.scheduler.model.PropertyProviderModel;
|
||||
|
||||
public class ExamplePropertyProviderModel extends PropertyProviderModel
|
||||
{
|
||||
public final Object flashVars;
|
||||
public Object user;
|
||||
|
||||
public ExamplePropertyProviderModel(Object flashVars)
|
||||
{
|
||||
this.flashVars = flashVars;
|
||||
}
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package io.nucleo.scheduler.example;
|
||||
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import io.nucleo.scheduler.worker.WorkerFaultHandler;
|
||||
import io.nucleo.scheduler.worker.WorkerResultHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SchedulerTestRunner implements WorkerResultHandler, WorkerFaultHandler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SchedulerTestRunner.class);
|
||||
private static SchedulerTestRunner schedulerTestRunner;
|
||||
|
||||
public SchedulerTestRunner()
|
||||
{
|
||||
/* Map<Object, Object> flashVars = new HashMap<>();
|
||||
flashVars.put("userName", "bully");
|
||||
|
||||
Object model = new ExamplePropertyProviderModel(flashVars);
|
||||
ExampleAS3Scheduler exampleScheduler = new ExampleAS3Scheduler();
|
||||
|
||||
exampleScheduler.setModel(model);
|
||||
exampleScheduler.setResultHandler(() -> {
|
||||
log.debug("setResultHandler ");
|
||||
});
|
||||
exampleScheduler.setFaultHandler((throwable) -> {
|
||||
log.debug("setFaultHandler ");
|
||||
});
|
||||
exampleScheduler.execute(); */
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
schedulerTestRunner = new SchedulerTestRunner();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(Throwable throwable)
|
||||
{
|
||||
log.debug("onFault " + this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResult(Worker worker)
|
||||
{
|
||||
log.debug("onResult " + this);
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
package io.nucleo.scheduler.model;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class PropertyProviderModel
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(PropertyProviderModel.class);
|
||||
|
||||
public PropertyProviderModel()
|
||||
{
|
||||
}
|
||||
|
||||
public boolean areAllDependenciesAvailable(List<String> propertyNames)
|
||||
{
|
||||
Predicate<String> isPropertyNotNull = (propertyName) -> read(propertyName) != null;
|
||||
return propertyNames.stream().allMatch(isPropertyNotNull);
|
||||
}
|
||||
|
||||
public Object read(String key)
|
||||
{
|
||||
try
|
||||
{
|
||||
return getField(key).get(this);
|
||||
} catch (IllegalAccessException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Private
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
private Field getField(String key)
|
||||
{
|
||||
Class clazz = this.getClass();
|
||||
try
|
||||
{
|
||||
Field field = clazz.getDeclaredField(key);
|
||||
field.setAccessible(true); // make sure a private field is accessible for reflection
|
||||
return field;
|
||||
} catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
package io.nucleo.scheduler.tasks;
|
||||
|
||||
import io.nucleo.scheduler.model.PropertyProviderModel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The base class for all tasks using a IPropertyProviderModel instance as a shared model.
|
||||
*/
|
||||
public abstract class AbstractDependencyManagedTask extends AbstractTask
|
||||
{
|
||||
private PropertyProviderModel propertyProviderModel;
|
||||
private List<String> readDependencyKeys = new ArrayList<>();
|
||||
|
||||
public AbstractDependencyManagedTask()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// IRunnable implementation
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void setModel(Object model)
|
||||
{
|
||||
propertyProviderModel = (PropertyProviderModel) model;
|
||||
|
||||
super.setModel(model);
|
||||
|
||||
initReadDependencies();
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Abstract Methods
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* To be overwritten in subclasses
|
||||
* Used to read the needed data objects for the task.
|
||||
* Typically stored as instance variable in the task.
|
||||
*/
|
||||
protected void initReadDependencies()
|
||||
{
|
||||
// user = read(IUser);
|
||||
// channel = read("channel");
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Final protected
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
final protected Object read(String key)
|
||||
{
|
||||
readDependencyKeys.add(key);
|
||||
|
||||
return propertyProviderModel.read(key);
|
||||
}
|
||||
|
||||
public boolean areAllDependenciesAvailable()
|
||||
{
|
||||
return propertyProviderModel.areAllDependenciesAvailable(readDependencyKeys);
|
||||
}
|
||||
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package io.nucleo.scheduler.tasks;
|
||||
|
||||
import io.nucleo.scheduler.worker.AbstractWorker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The base class for all tasks.
|
||||
*/
|
||||
public abstract class AbstractTask extends AbstractWorker
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractTask.class);
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package io.nucleo.scheduler.worker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractWorker implements Worker
|
||||
{
|
||||
protected List<WorkerResultHandler> resultHandlers = new ArrayList<>();
|
||||
protected List<WorkerFaultHandler> faultHandlers = new ArrayList<>();
|
||||
protected Object model;
|
||||
protected boolean hasFailed;
|
||||
protected boolean hasCompleted;
|
||||
|
||||
@Override
|
||||
abstract public void execute();
|
||||
|
||||
@Override
|
||||
public void addResultHandlers(WorkerResultHandler resultHandler)
|
||||
{
|
||||
resultHandlers.add(resultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFaultHandlers(WorkerFaultHandler faultHandler)
|
||||
{
|
||||
faultHandlers.add(faultHandler);
|
||||
}
|
||||
|
||||
public void setModel(Object model)
|
||||
{
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getHasCompleted()
|
||||
{
|
||||
return hasCompleted;
|
||||
}
|
||||
|
||||
protected void complete()
|
||||
{
|
||||
hasCompleted = true;
|
||||
resultHandlers.stream().forEach(e -> e.onResult(this));
|
||||
}
|
||||
|
||||
protected void failed(Throwable throwable)
|
||||
{
|
||||
hasFailed = true;
|
||||
faultHandlers.stream().forEach(e -> e.onFault(throwable));
|
||||
}
|
||||
|
||||
protected void destroy()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package io.nucleo.scheduler.worker;
|
||||
|
||||
/**
|
||||
* The base interface for all runnable objects (tasks, schedulers)
|
||||
*/
|
||||
public interface Worker
|
||||
{
|
||||
/**
|
||||
* Starts the execution.
|
||||
*/
|
||||
void execute();
|
||||
|
||||
void addResultHandlers(WorkerResultHandler resultHandler);
|
||||
|
||||
void addFaultHandlers(WorkerFaultHandler faultHandler);
|
||||
|
||||
boolean getHasCompleted();
|
||||
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package io.nucleo.scheduler.worker;
|
||||
|
||||
public interface WorkerFaultHandler
|
||||
{
|
||||
void onFault(Throwable throwable);
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package io.nucleo.scheduler.worker;
|
||||
|
||||
public interface WorkerResultHandler
|
||||
{
|
||||
void onResult(Worker worker);
|
||||
}
|
@ -3,7 +3,6 @@ package io.bitsquare;
|
||||
import io.bitsquare.btc.BtcValidatorTest;
|
||||
import io.bitsquare.gui.util.BitSquareConverterTest;
|
||||
import io.bitsquare.gui.util.BitSquareValidatorTest;
|
||||
import io.nucleo.scheduler.SequenceSchedulerTest;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@ -12,7 +11,6 @@ import org.junit.runners.Suite;
|
||||
BtcValidatorTest.class,
|
||||
BitSquareConverterTest.class,
|
||||
BitSquareValidatorTest.class,
|
||||
SequenceSchedulerTest.class
|
||||
})
|
||||
|
||||
public class BitSquareTestSuite
|
||||
|
@ -1,228 +0,0 @@
|
||||
package io.nucleo.scheduler;
|
||||
|
||||
import io.nucleo.scheduler.tasks.SyncWorker1;
|
||||
import io.nucleo.scheduler.tasks.SyncWorker2;
|
||||
import io.nucleo.scheduler.worker.Worker;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SequenceSchedulerTest
|
||||
{
|
||||
private final boolean[] hasCompleted = new boolean[1];
|
||||
private final boolean[] hasFailed = new boolean[1];
|
||||
private final boolean[] worker1HasCompleted = new boolean[1];
|
||||
private final boolean[] worker1HasFailed = new boolean[1];
|
||||
private final boolean[] worker2HasCompleted = new boolean[1];
|
||||
private final boolean[] worker2HasFailed = new boolean[1];
|
||||
private SequenceScheduler sequenceScheduler;
|
||||
private Map<String, String> model = new HashMap<>();
|
||||
private List<Worker> workerList = new ArrayList<>();
|
||||
private Throwable worker1Throwable;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
sequenceScheduler = new SequenceScheduler();
|
||||
sequenceScheduler.addResultHandlers((worker) -> {
|
||||
hasCompleted[0] = true;
|
||||
});
|
||||
sequenceScheduler.addFaultHandlers(throwable -> {
|
||||
hasFailed[0] = true;
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
hasCompleted[0] = false;
|
||||
hasFailed[0] = false;
|
||||
workerList.clear();
|
||||
model.clear();
|
||||
worker1Throwable = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty()
|
||||
{
|
||||
sequenceScheduler.execute();
|
||||
assertTrue(sequenceScheduler.getHasCompleted());
|
||||
assertTrue(hasCompleted[0]);
|
||||
assertFalse(hasFailed[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEmpty2()
|
||||
{
|
||||
sequenceScheduler.setWorkers(workerList);
|
||||
sequenceScheduler.execute();
|
||||
assertTrue(sequenceScheduler.getHasCompleted());
|
||||
assertTrue(hasCompleted[0]);
|
||||
assertFalse(hasFailed[0]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testOneWithCompleted()
|
||||
{
|
||||
Worker worker1 = getWorker1(false);
|
||||
workerList.add(worker1);
|
||||
sequenceScheduler.setWorkers(workerList);
|
||||
sequenceScheduler.execute();
|
||||
|
||||
assertTrue(sequenceScheduler.getHasCompleted());
|
||||
assertTrue(hasCompleted[0]);
|
||||
assertFalse(hasFailed[0]);
|
||||
|
||||
assertTrue(worker1.getHasCompleted());
|
||||
assertTrue(worker1HasCompleted[0]);
|
||||
assertFalse(worker1HasFailed[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneWithFailed()
|
||||
{
|
||||
Worker worker1 = getWorker1(true);
|
||||
workerList.add(worker1);
|
||||
sequenceScheduler.setWorkers(workerList);
|
||||
sequenceScheduler.execute();
|
||||
|
||||
assertFalse(sequenceScheduler.getHasCompleted());
|
||||
assertFalse(hasCompleted[0]);
|
||||
assertTrue(hasFailed[0]);
|
||||
|
||||
assertFalse(worker1.getHasCompleted());
|
||||
assertFalse(worker1HasCompleted[0]);
|
||||
assertTrue(worker1HasFailed[0]);
|
||||
assertEquals(SyncWorker1.ERR_MSG, worker1Throwable.getMessage());
|
||||
}
|
||||
|
||||
// @Test
|
||||
public void testTwoCompleted()
|
||||
{
|
||||
Worker worker1 = getWorker1(false);
|
||||
Worker worker2 = getWorker2(false);
|
||||
workerList.add(worker1);
|
||||
workerList.add(worker2);
|
||||
sequenceScheduler.setWorkers(workerList);
|
||||
sequenceScheduler.execute();
|
||||
|
||||
assertTrue(sequenceScheduler.getHasCompleted());
|
||||
assertTrue(hasCompleted[0]);
|
||||
assertFalse(hasFailed[0]);
|
||||
|
||||
assertTrue(worker1.getHasCompleted());
|
||||
assertTrue(worker1HasCompleted[0]);
|
||||
assertFalse(worker1HasFailed[0]);
|
||||
|
||||
assertTrue(worker2.getHasCompleted());
|
||||
assertTrue(worker2HasCompleted[0]);
|
||||
assertFalse(worker2HasFailed[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoReverseOrder()
|
||||
{
|
||||
model.put("worker1State", "");
|
||||
model.put("worker2State", "");
|
||||
Worker worker1 = getWorker1(false);
|
||||
Worker worker2 = getWorker2(false);
|
||||
workerList.add(worker2);
|
||||
workerList.add(worker1);
|
||||
sequenceScheduler.setWorkers(workerList);
|
||||
sequenceScheduler.setModel(model);
|
||||
sequenceScheduler.execute();
|
||||
|
||||
assertEquals(SyncWorker1.STATE, model.get("worker1State"));
|
||||
assertEquals(SyncWorker2.STATE, model.get("worker2State"));
|
||||
|
||||
assertTrue(sequenceScheduler.getHasCompleted());
|
||||
assertTrue(hasCompleted[0]);
|
||||
assertFalse(hasFailed[0]);
|
||||
|
||||
assertTrue(worker1.getHasCompleted());
|
||||
assertTrue(worker1HasCompleted[0]);
|
||||
assertFalse(worker1HasFailed[0]);
|
||||
|
||||
assertTrue(worker2.getHasCompleted());
|
||||
assertTrue(worker2HasCompleted[0]);
|
||||
assertFalse(worker2HasFailed[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoFirstFailed()
|
||||
{
|
||||
Worker worker1 = getWorker1(true);
|
||||
Worker worker2 = getWorker2(false);
|
||||
workerList.add(worker1);
|
||||
workerList.add(worker2);
|
||||
sequenceScheduler.setWorkers(workerList);
|
||||
sequenceScheduler.execute();
|
||||
|
||||
assertFalse(sequenceScheduler.getHasCompleted());
|
||||
assertFalse(hasCompleted[0]);
|
||||
assertTrue(hasFailed[0]);
|
||||
|
||||
assertFalse(worker1.getHasCompleted());
|
||||
assertFalse(worker1HasCompleted[0]);
|
||||
assertTrue(worker1HasFailed[0]);
|
||||
|
||||
assertFalse(worker2.getHasCompleted());
|
||||
assertFalse(worker2HasCompleted[0]);
|
||||
assertFalse(worker2HasFailed[0]); // second has not been executed and is not failed!
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTwoSecondFailed()
|
||||
{
|
||||
Worker worker1 = getWorker1(false);
|
||||
Worker worker2 = getWorker2(true);
|
||||
workerList.add(worker1);
|
||||
workerList.add(worker2);
|
||||
sequenceScheduler.setWorkers(workerList);
|
||||
sequenceScheduler.execute();
|
||||
|
||||
assertFalse(sequenceScheduler.getHasCompleted());
|
||||
assertFalse(hasCompleted[0]);
|
||||
assertTrue(hasFailed[0]);
|
||||
|
||||
assertTrue(worker1.getHasCompleted());
|
||||
assertTrue(worker1HasCompleted[0]);
|
||||
assertFalse(worker1HasFailed[0]);
|
||||
|
||||
assertFalse(worker2.getHasCompleted());
|
||||
assertFalse(worker2HasCompleted[0]);
|
||||
assertTrue(worker2HasFailed[0]); // second has not been executed and is not failed!
|
||||
}
|
||||
|
||||
private Worker getWorker1(boolean letItFail)
|
||||
{
|
||||
Worker worker1 = new SyncWorker1(letItFail);
|
||||
worker1.addResultHandlers((worker) -> {
|
||||
worker1HasCompleted[0] = true;
|
||||
});
|
||||
worker1.addFaultHandlers(throwable -> {
|
||||
worker1HasFailed[0] = true;
|
||||
worker1Throwable = throwable;
|
||||
});
|
||||
return worker1;
|
||||
}
|
||||
|
||||
private Worker getWorker2(boolean letItFail)
|
||||
{
|
||||
Worker worker2 = new SyncWorker2(letItFail);
|
||||
worker2.addResultHandlers((worker) -> {
|
||||
worker2HasCompleted[0] = true;
|
||||
});
|
||||
worker2.addFaultHandlers(throwable -> {
|
||||
worker2HasFailed[0] = true;
|
||||
});
|
||||
return worker2;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package io.nucleo.scheduler.tasks;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SyncWorker1 extends AbstractTask
|
||||
{
|
||||
|
||||
public static String ERR_MSG = "Failure message";
|
||||
public static String STATE = "ok";
|
||||
private boolean letItFail;
|
||||
|
||||
public SyncWorker1(boolean letItFail)
|
||||
{
|
||||
|
||||
this.letItFail = letItFail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
System.out.println("execute " + this);
|
||||
if (model != null) ((Map<String, String>) model).put("worker1State", STATE);
|
||||
if (letItFail)
|
||||
failed(new Exception(ERR_MSG));
|
||||
else
|
||||
complete();
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package io.nucleo.scheduler.tasks;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SyncWorker2 extends AbstractTask
|
||||
{
|
||||
public static String ERR_MSG = "Failure message";
|
||||
public static String STATE = "ok";
|
||||
private boolean letItFail;
|
||||
|
||||
public SyncWorker2(boolean letItFail)
|
||||
{
|
||||
this.letItFail = letItFail;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute()
|
||||
{
|
||||
System.out.println("execute " + this);
|
||||
if (model != null) ((Map<String, String>) model).put("worker2State", STATE);
|
||||
if (letItFail)
|
||||
failed(new Exception(ERR_MSG));
|
||||
else
|
||||
complete();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user