Fix bug with offer remove (arbitrator, locale)

This commit is contained in:
Manfred Karrer 2015-03-25 02:07:23 +01:00
parent 9cb029c21b
commit af5949540d
20 changed files with 292 additions and 320 deletions

View File

@ -30,7 +30,6 @@ import java.security.PublicKey;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import javax.inject.Inject;
@ -83,7 +82,9 @@ public class Arbitrator implements Serializable {
// editable
private ID_TYPE idType;
private List<Locale> languages;
// TODO languages breaks something in serialisation with TomP2P when uing Locale. cannot remove an offer
private List<String> languages;
private Coin fee;
private List<METHOD> arbitrationMethods;
private List<ID_VERIFICATION> idVerifications;
@ -119,7 +120,7 @@ public class Arbitrator implements Serializable {
this.p2pSigPubKey = user.getP2PSigPubKey();
this.name = "Manfred Karrer";
this.idType = Arbitrator.ID_TYPE.REAL_LIFE_ID;
this.languages = Arrays.asList(LanguageUtil.getDefaultLanguageLocale());
this.languages = Arrays.asList(LanguageUtil.getDefaultLanguageLocale().getISO3Language());
this.reputation = new Reputation();
this.fee = Coin.parseCoin("0.1");
this.arbitrationMethods = Arrays.asList(Arbitrator.METHOD.TLS_NOTARY);
@ -181,7 +182,7 @@ public class Arbitrator implements Serializable {
doSave();
}
public void setLanguages(List<Locale> languages) {
public void setLanguages(List<String> languages) {
this.languages = languages;
doSave();
}
@ -231,7 +232,7 @@ public class Arbitrator implements Serializable {
return idType;
}
public List<Locale> getLanguages() {
public List<String> getLanguages() {
return languages;
}

View File

@ -23,8 +23,6 @@ import org.bitcoinj.crypto.DeterministicKey;
import java.io.Serializable;
import java.util.Arrays;
/**
* Is a minimalistic wallet abstraction used to separate transactions between different activities like:
* Registration, trade and arbiter deposit.
@ -96,10 +94,6 @@ public class AddressEntry implements Serializable {
return "AddressEntry{" +
"offerId='" + offerId +
", addressContext=" + context +
", keyPair=" + keyPair +
", pubKey=" + Arrays.toString(pubKey) +
", pubKeyHash=" + Arrays.toString(pubKeyHash) +
", params=" + params +
'}';
}
}

View File

@ -59,7 +59,7 @@ public class ArbitratorProfileView extends AbstractView {
nameLabel.setText(name);
nameTextField.setText(arbitrator.getName());
languagesTextField.setText(formatter.languageLocalesToString(arbitrator.getLanguages()));
// languagesTextField.setText(formatter.languageLocalesToString(arbitrator.getLanguages()));
reputationTextField.setText(arbitrator.getReputation().toString());
feeTextField.setText(String.valueOf(arbitrator.getFee() + " BTC"));
methodsTextField.setText(formatter.arbitrationMethodsToString(arbitrator.getArbitrationMethods()));

View File

@ -249,7 +249,7 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
arbitrator.setFee(formatter.parseToCoin(arbitrationFeeTextField.getText()));
arbitrator.setIdType(idType);
arbitrator.setIdVerifications(idVerificationList);
arbitrator.setLanguages(languageList);
// arbitrator.setLanguages(languageList);
arbitrator.setArbitrationMethods(methodList);
arbitrator.setSaveOnEveryUpdate(true);
@ -346,7 +346,7 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
nameTextField.setText(arbitrator.getName());
idTypeTextField.setText(BSResources.get(arbitrator.getIdType().toString()));
languagesTextField.setText(formatter.languageLocalesToString(arbitrator.getLanguages()));
// languagesTextField.setText(formatter.languageLocalesToString(arbitrator.getLanguages()));
arbitrationFeeTextField.setText(String.valueOf(arbitrator.getFee()));
methodsTextField.setText(formatter.arbitrationMethodsToString(arbitrator.getArbitrationMethods()));
idVerificationsTextField.setText(
@ -355,7 +355,7 @@ public class ArbitratorRegistrationView extends ActivatableView<AnchorPane, Void
descriptionTextArea.setText(arbitrator.getDescription());
idType = arbitrator.getIdType();
languageList = arbitrator.getLanguages();
// languageList = arbitrator.getLanguages();
methodList = arbitrator.getArbitrationMethods();
idVerificationList = arbitrator.getIdVerifications();
}

View File

@ -37,7 +37,6 @@ import io.bitsquare.trade.protocol.trade.offerer.tasks.ProcessRequestOffererPubl
import io.bitsquare.trade.protocol.trade.offerer.tasks.RequestTakerDepositPayment;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendBankTransferStartedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendDepositTxToTaker;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SetupListenerForBlockChainConfirmation;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SignAndPublishDepositTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyAndSignContract;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakeOfferFeePayment;
@ -110,7 +109,6 @@ public class DebugView extends InitializableView {
VerifyTakerAccount.class,
VerifyAndSignContract.class,
SignAndPublishDepositTx.class,
SetupListenerForBlockChainConfirmation.class,
SendDepositTxToTaker.class,
CreateAndSignPayoutTx.class,

View File

@ -139,11 +139,11 @@ class PendingTradesDataModel implements Activatable, DataModel {
}
void fiatPaymentStarted() {
tradeManager.onFiatPaymentStarted(getTrade().getId());
tradeManager.onFiatPaymentStarted(getTrade());
}
void fiatPaymentReceived() {
tradeManager.onFiatPaymentReceived(getTrade().getId());
tradeManager.onFiatPaymentReceived(getTrade());
}
void withdraw(String toAddress) {

View File

@ -43,8 +43,6 @@ import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.*;
//TODO flatten down?
public class Offer implements Serializable {
private static final long serialVersionUID = -971164804305475826L;
private transient static final Logger log = LoggerFactory.getLogger(Offer.class);
@ -86,7 +84,7 @@ public class Offer implements Serializable {
// Those state properties are transient and only used at runtime!
// don't access directly as it might be null; use getStateProperty() which creates an object if not instantiated
private transient ObjectProperty<State> stateProperty;
transient private ObjectProperty<State> stateProperty = new SimpleObjectProperty<>(State.UNKNOWN);
///////////////////////////////////////////////////////////////////////////////////////////
@ -137,6 +135,9 @@ public class Offer implements Serializable {
stateProperty().set(state);
}
public void setOfferFeePaymentTxID(String offerFeePaymentTxID) {
this.offerFeePaymentTxID = offerFeePaymentTxID;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
@ -205,10 +206,6 @@ public class Offer implements Serializable {
return offerFeePaymentTxID;
}
public void setOfferFeePaymentTxID(String offerFeePaymentTxID) {
this.offerFeePaymentTxID = offerFeePaymentTxID;
}
public List<Arbitrator> getArbitrators() {
return arbitrators;
}
@ -277,7 +274,6 @@ public class Offer implements Serializable {
", fiatPrice=" + fiatPrice +
", amount=" + amount +
", minAmount=" + minAmount +
", p2pSigPubKey=" + p2pSigPubKey +
", fiatAccountType=" + fiatAccountType +
", bankAccountCountry=" + bankAccountCountry +
", securityDeposit=" + securityDeposit +

View File

@ -64,6 +64,7 @@ public class TomP2POfferBookService extends TomP2PDHTService implements OfferBoo
@Override
public void addOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler) {
log.debug("addOffer " + offer);
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
try {
final Data offerData = new Data(offer);
@ -108,6 +109,7 @@ public class TomP2POfferBookService extends TomP2PDHTService implements OfferBoo
}
public void removeOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler) {
log.debug("removeOffer " + offer);
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
try {
final Data offerData = new Data(offer);
@ -170,6 +172,14 @@ public class TomP2POfferBookService extends TomP2PDHTService implements OfferBoo
try {
Object offerDataObject = offerData.object();
if (offerDataObject instanceof Offer) {
try {
Data offerData1 = new Data(offerDataObject);
log.trace("-------------------------- getOffers hash" + offerData1.hash().toString());
} catch (IOException e) {
e.printStackTrace();
}
offers.add((Offer) offerDataObject);
}
} catch (ClassNotFoundException | IOException e) {

View File

@ -163,9 +163,10 @@ public class TomP2PDHTService extends TomP2PService implements DHTService {
* @return
*/
public FuturePut addProtectedDataToMap(Number160 locationKey, Data data) {
log.trace("addProtectedDataToMap");
log.trace("addProtectedDataToMap locationKey = " + locationKey);
data.protectEntry(keyPair);
log.trace("addProtectedDataToMap with contentKey " + data.hash().toString());
return peerDHT.add(locationKey).data(data).keyPair(keyPair).start();
}
@ -178,7 +179,7 @@ public class TomP2PDHTService extends TomP2PService implements DHTService {
* @return
*/
public FutureRemove removeProtectedDataFromMap(Number160 locationKey, Data data) {
log.trace("removeProtectedDataFromMap");
log.trace("removeProtectedDataFromMap locationKey = " + locationKey);
Number160 contentKey = data.hash();
log.trace("removeProtectedDataFromMap with contentKey " + contentKey.toString());
return peerDHT.remove(locationKey).contentKey(contentKey).keyPair(keyPair).start();
@ -247,7 +248,7 @@ public class TomP2PDHTService extends TomP2PService implements DHTService {
log.trace("getDataFromMapOfMyProtectedDomain");
return peerDHT.get(locationKey).all().domainKey(pubKeyHashForMyDomain).start();
}
/**
* Remove all data from map for given locationKey.
* Access: Only the domain owner.

View File

@ -0,0 +1,42 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.protocol.trade.offerer.OffererAsBuyerProtocol;
import java.io.Serializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OffererTrade extends Trade implements Serializable {
private static final long serialVersionUID = 1;
transient private static final Logger log = LoggerFactory.getLogger(OffererTrade.class);
public OffererTrade(Offer offer) {
super(offer);
}
public void onFiatPaymentStarted() {
((OffererAsBuyerProtocol) protocol).onFiatPaymentStarted();
}
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade;
import io.bitsquare.offer.Offer;
import io.bitsquare.trade.protocol.trade.taker.TakerAsSellerProtocol;
import java.io.Serializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TakerTrade extends Trade implements Serializable {
private static final long serialVersionUID = 1;
transient private static final Logger log = LoggerFactory.getLogger(TakerTrade.class);
public TakerTrade(Offer offer) {
super(offer);
}
public void onFiatPaymentReceived() {
((TakerAsSellerProtocol) protocol).onFiatPaymentReceived();
}
}

View File

@ -18,7 +18,9 @@
package io.bitsquare.trade;
import io.bitsquare.offer.Offer;
import io.bitsquare.p2p.MailboxMessage;
import io.bitsquare.p2p.Peer;
import io.bitsquare.trade.protocol.Protocol;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
@ -30,7 +32,6 @@ import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.io.IOException;
import java.io.Serializable;
import java.util.Date;
@ -42,8 +43,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Trade implements Serializable {
private static final long serialVersionUID = -8275323072940974077L;
private static final Logger log = LoggerFactory.getLogger(Trade.class);
protected static final long serialVersionUID = 1;
protected static final Logger log = LoggerFactory.getLogger(Trade.class);
///////////////////////////////////////////////////////////////////////////////////////////
@ -71,7 +72,7 @@ public class Trade implements Serializable {
MESSAGE_SENDING_FAILED,
FAULT;
private String errorMessage;
protected String errorMessage;
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
@ -82,28 +83,32 @@ public class Trade implements Serializable {
}
}
private final Offer offer;
private final Date date;
private ProcessState processState;
private LifeCycleState lifeCycleState;
transient protected Protocol protocol;
private Coin tradeAmount;
private Contract contract;
private String contractAsJson;
private String takerContractSignature;
private String offererContractSignature;
private Transaction depositTx;
private Transaction payoutTx;
private Peer tradingPeer;
private int depthInBlocks = 0;
protected MailboxMessage mailboxMessage;
protected final Offer offer;
protected final Date date;
protected ProcessState processState;
protected LifeCycleState lifeCycleState;
protected Coin tradeAmount;
protected Contract contract;
protected String contractAsJson;
protected String takerContractSignature;
protected String offererContractSignature;
protected Transaction depositTx;
protected Transaction payoutTx;
protected Peer tradingPeer;
protected int depthInBlocks = 0;
// For changing values we use properties to get binding support in the UI (table)
// When serialized those transient properties are not instantiated, so we instantiate them in the getters at first
// access. Only use the accessor not the private field.
transient private ObjectProperty<Coin> _tradeAmount;
transient private ObjectProperty<Fiat> _tradeVolume;
transient private ObjectProperty<ProcessState> _processState;
transient private ObjectProperty<LifeCycleState> _lifeCycleState;
// access. Only use the accessor not the protected field.
transient protected ObjectProperty<Coin> _tradeAmount;
transient protected ObjectProperty<Fiat> _tradeVolume;
transient protected ObjectProperty<ProcessState> _processState;
transient protected ObjectProperty<LifeCycleState> _lifeCycleState;
///////////////////////////////////////////////////////////////////////////////////////////
@ -118,47 +123,36 @@ public class Trade implements Serializable {
log.debug("Trade ");
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
log.debug("Trade writeObject");
out.defaultWriteObject();
log.debug("Trade writeObject");
///////////////////////////////////////////////////////////////////////////////////////////
// Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void disposeProtocol() {
if (protocol != null)
protocol.cleanup();
protocol = null;
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
log.debug("Trade readObject");
in.defaultReadObject();
//TODO cannot call yet as persistence need to be refactored first. cann be called only after bitcoinJ is initialized as serialized tx objects throw
// exceptions
//setConfidenceListener();
log.debug("Trade readObject");
public void setMailboxMessage(MailboxMessage mailboxMessage) {
this.mailboxMessage = mailboxMessage;
if (protocol != null)
protocol.setMailboxMessage(mailboxMessage);
}
private void setConfidenceListener() {
// log.debug("setConfidenceListener called. depthInBlocks=" + depthInBlocks + " / depositTx != null ? " + (depositTx.toString() != null));
if (depositTx != null && depthInBlocks == 0) {
TransactionConfidence transactionConfidence = depositTx.getConfidence();
ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1);
Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@Override
public void onSuccess(TransactionConfidence result) {
setProcessState(Trade.ProcessState.DEPOSIT_CONFIRMED);
}
public void setProtocol(Protocol protocol) {
this.protocol = protocol;
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
log.error(t.getMessage());
Throwables.propagate(t);
}
});
}
if (mailboxMessage != null)
protocol.setMailboxMessage(mailboxMessage);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Setters
///////////////////////////////////////////////////////////////////////////////////////////
public void setTradingPeer(Peer tradingPeer) {
this.tradingPeer = tradingPeer;
}
@ -298,12 +292,38 @@ public class Trade implements Serializable {
return _lifeCycleState;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
protected void setConfidenceListener() {
TransactionConfidence transactionConfidence = depositTx.getConfidence();
ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1);
Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@Override
public void onSuccess(TransactionConfidence result) {
setProcessState(Trade.ProcessState.DEPOSIT_CONFIRMED);
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
log.error(t.getMessage());
Throwables.propagate(t);
}
});
}
@Override
public String toString() {
return "Trade{" +
"offer=" + offer +
"protocol=" + protocol +
", mailboxMessage=" + mailboxMessage +
", offer=" + offer +
", date=" + date +
", state=" + processState +
", processState=" + processState +
", lifeCycleState=" + lifeCycleState +
", tradeAmount=" + tradeAmount +
", contract=" + contract +
", contractAsJson='" + contractAsJson + '\'' +
@ -311,6 +331,8 @@ public class Trade implements Serializable {
", offererContractSignature='" + offererContractSignature + '\'' +
", depositTx=" + depositTx +
", payoutTx=" + payoutTx +
", tradingPeer=" + tradingPeer +
", depthInBlocks=" + depthInBlocks +
'}';
}
}

View File

@ -30,12 +30,12 @@ import javafx.collections.ObservableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TradeList extends ArrayList<Trade> implements Serializable {
public class TradeList<T> extends ArrayList<T> implements Serializable {
private static final long serialVersionUID = 1L;
transient private static final Logger log = LoggerFactory.getLogger(TradeList.class);
transient final private Storage<TradeList> storage;
transient private ObservableList<Trade> observableList;
transient private ObservableList<T> observableList;
public TradeList(File storageDir, String fileName) {
this.storage = new Storage<>(storageDir);
@ -51,7 +51,7 @@ public class TradeList extends ArrayList<Trade> implements Serializable {
}
@Override
public boolean add(Trade trade) {
public boolean add(T trade) {
boolean result = super.add(trade);
observableList.add(trade);
storage.save();
@ -66,7 +66,7 @@ public class TradeList extends ArrayList<Trade> implements Serializable {
return result;
}
public ObservableList<Trade> getObservableList() {
public ObservableList<T> getObservableList() {
return observableList;
}

View File

@ -51,6 +51,7 @@ import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
@ -62,6 +63,8 @@ import javax.inject.Named;
import javafx.collections.ObservableList;
import net.tomp2p.storage.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -80,14 +83,11 @@ public class TradeManager {
private final OfferBookService offerBookService;
private File storageDir;
private final Map<String, TakerAsSellerProtocol> takerAsSellerProtocolMap = new HashMap<>();
private final Map<String, OffererAsBuyerProtocol> offererAsBuyerProtocolMap = new HashMap<>();
private final Map<String, CheckOfferAvailabilityProtocol> checkOfferAvailabilityProtocolMap = new HashMap<>();
private final TradeList openOfferTrades;
private final TradeList pendingTrades;
private final TradeList closedTrades;
private final Map<String, MailboxMessage> mailboxMessages = new HashMap<>();
private final TradeList<OffererTrade> openOfferTrades;
private final TradeList<Trade> pendingTrades;
private final TradeList<Trade> closedTrades;
///////////////////////////////////////////////////////////////////////////////////////////
@ -111,9 +111,9 @@ public class TradeManager {
this.offerBookService = offerBookService;
this.storageDir = storageDir;
this.openOfferTrades = new TradeList(storageDir, "OpenOfferTrades");
this.pendingTrades = new TradeList(storageDir, "PendingTrades");
this.closedTrades = new TradeList(storageDir, "ClosedTrades");
this.openOfferTrades = new TradeList<>(storageDir, "OpenOfferTrades");
this.pendingTrades = new TradeList<>(storageDir, "PendingTrades");
this.closedTrades = new TradeList<>(storageDir, "ClosedTrades");
}
@ -124,18 +124,18 @@ public class TradeManager {
// When all services are initialized we create the protocols for our open offers and persisted not completed pendingTrades
// BuyerAcceptsOfferProtocol listens for take offer requests, so we need to instantiate it early.
public void onAllServicesInitialized() {
for (Trade trade : openOfferTrades) {
createOffererAsBuyerProtocol(trade);
for (OffererTrade offererTrade : openOfferTrades) {
createOffererAsBuyerProtocol(offererTrade);
}
for (Trade trade : pendingTrades) {
// We continue an interrupted trade.
// TODO if the peer has changed its IP address, we need to make another findPeer request. At the moment we use the peer stored in trade to
// continue the trade, but that might fail.
if (isMyOffer(trade.getOffer())) {
createOffererAsBuyerProtocol(trade);
if (trade instanceof OffererTrade) {
createOffererAsBuyerProtocol((OffererTrade) trade);
}
else {
createTakerAsSellerProtocol(trade);
else if (trade instanceof TakerTrade) {
createTakerAsSellerProtocol((TakerTrade) trade);
}
}
@ -179,16 +179,24 @@ public class TradeManager {
accountSettings.getAcceptedCountries(),
accountSettings.getAcceptedLanguageLocales());
try {
Data offerData = new Data(offer);
log.trace("-------------------------- placeOffer hash" + offerData.hash().toString());
} catch (IOException e) {
e.printStackTrace();
}
PlaceOfferModel model = new PlaceOfferModel(offer, walletService, offerBookService);
PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(
model,
(transaction) -> {
Trade trade = new Trade(offer);
trade.setLifeCycleState(Trade.LifeCycleState.OPEN_OFFER);
openOfferTrades.add(trade);
OffererTrade offererTrade = new OffererTrade(offer);
offererTrade.setLifeCycleState(Trade.LifeCycleState.OPEN_OFFER);
openOfferTrades.add(offererTrade);
createOffererAsBuyerProtocol(trade);
OffererAsBuyerProtocol protocol = createOffererAsBuyerProtocol(offererTrade);
offererTrade.setProtocol(protocol);
resultHandler.handleResult(transaction);
},
(message) -> errorMessageHandler.handleErrorMessage(message)
@ -249,23 +257,19 @@ public class TradeManager {
// Trade
///////////////////////////////////////////////////////////////////////////////////////////
public void onFiatPaymentStarted(String tradeId) {
// TODO remove if check when persistence is impl.
if (offererAsBuyerProtocolMap.containsKey(tradeId)) {
offererAsBuyerProtocolMap.get(tradeId).onFiatPaymentStarted();
// persistPendingTrades();
}
public void onFiatPaymentStarted(Trade trade) {
((OffererTrade) trade).onFiatPaymentStarted();
}
public void onFiatPaymentReceived(String tradeId) {
takerAsSellerProtocolMap.get(tradeId).onFiatPaymentReceived();
public void onFiatPaymentReceived(Trade trade) {
((TakerTrade) trade).onFiatPaymentReceived();
}
public void onWithdrawAtTradeCompleted(Trade trade) {
trade.setLifeCycleState(Trade.LifeCycleState.COMPLETED);
pendingTrades.remove(trade);
closedTrades.add(trade);
removeFromProtocolMap(trade);
trade.disposeProtocol();
}
@ -282,7 +286,7 @@ public class TradeManager {
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
public ObservableList<Trade> getOpenOfferTrades() {
public ObservableList<OffererTrade> getOpenOfferTrades() {
return openOfferTrades.getObservableList();
}
@ -310,24 +314,19 @@ public class TradeManager {
offerBookService.removeOffer(offer,
() -> {
offer.setState(Offer.State.REMOVED);
Optional<Trade> result = openOfferTrades.stream().filter(e -> e.getId().equals(offer.getId())).findAny();
if (result.isPresent()) {
Trade trade = result.get();
openOfferTrades.remove(trade);
Optional<OffererTrade> offererTradeOptional = openOfferTrades.stream().filter(e -> e.getId().equals(offer.getId())).findAny();
if (offererTradeOptional.isPresent()) {
OffererTrade offererTrade = offererTradeOptional.get();
openOfferTrades.remove(offererTrade);
if (isCancelRequest) {
trade.setLifeCycleState(Trade.LifeCycleState.CANCELED);
closedTrades.add(trade);
offererTrade.setLifeCycleState(Trade.LifeCycleState.CANCELED);
closedTrades.add(offererTrade);
offererTrade.disposeProtocol();
}
}
disposeCheckOfferAvailabilityRequest(offer);
String offerId = offer.getId();
if (isCancelRequest && offererAsBuyerProtocolMap.containsKey(offerId)) {
offererAsBuyerProtocolMap.get(offerId).cleanup();
offererAsBuyerProtocolMap.remove(offerId);
}
resultHandler.handleResult();
},
@ -354,23 +353,23 @@ public class TradeManager {
///////////////////////////////////////////////////////////////////////////////////////////
private Trade takeAvailableOffer(Coin amount, Offer offer, Peer peer) {
Trade trade = new Trade(offer);
trade.setTradeAmount(amount);
trade.setTradingPeer(peer);
trade.setLifeCycleState(Trade.LifeCycleState.PENDING);
pendingTrades.add(trade);
TakerTrade takerTrade = new TakerTrade(offer);
takerTrade.setTradeAmount(amount);
takerTrade.setTradingPeer(peer);
takerTrade.setLifeCycleState(Trade.LifeCycleState.PENDING);
pendingTrades.add(takerTrade);
TakerAsSellerProtocol sellerTakesOfferProtocol = createTakerAsSellerProtocol(trade);
//trade.setProtocol(sellerTakesOfferProtocol);
TakerAsSellerProtocol sellerTakesOfferProtocol = createTakerAsSellerProtocol(takerTrade);
takerTrade.setProtocol(sellerTakesOfferProtocol);
sellerTakesOfferProtocol.takeAvailableOffer();
return trade;
return takerTrade;
}
private TakerAsSellerProtocol createTakerAsSellerProtocol(Trade trade) {
trade.processStateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("trade state = " + newValue);
private TakerAsSellerProtocol createTakerAsSellerProtocol(TakerTrade takerTrade) {
takerTrade.processStateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("takerTrade state = " + newValue);
switch (newValue) {
case INIT:
break;
@ -384,17 +383,17 @@ public class TradeManager {
break;
case MESSAGE_SENDING_FAILED:
case FAULT:
trade.setLifeCycleState(Trade.LifeCycleState.FAILED);
removeFromProtocolMap(trade);
takerTrade.setLifeCycleState(Trade.LifeCycleState.FAILED);
takerTrade.disposeProtocol();
break;
default:
log.warn("Unhandled trade state: " + newValue);
log.warn("Unhandled takerTrade state: " + newValue);
break;
}
});
TakerAsSellerModel model = new TakerAsSellerModel(
trade,
takerTrade,
messageService,
mailboxService,
walletService,
@ -403,20 +402,13 @@ public class TradeManager {
user,
storageDir);
TakerAsSellerProtocol protocol = new TakerAsSellerProtocol(model);
takerAsSellerProtocolMap.put(trade.getId(), protocol);
if (mailboxMessages.containsKey(trade.getId())) {
log.debug("TakerAsSellerProtocol setMailboxMessage " + trade.getId());
protocol.setMailboxMessage(mailboxMessages.get(trade.getId()));
}
return protocol;
return new TakerAsSellerProtocol(model);
}
private void createOffererAsBuyerProtocol(Trade trade) {
private OffererAsBuyerProtocol createOffererAsBuyerProtocol(OffererTrade offererTrade) {
OffererAsBuyerModel model = new OffererAsBuyerModel(
trade,
offererTrade,
messageService,
mailboxService,
walletService,
@ -427,8 +419,8 @@ public class TradeManager {
// TODO check, remove listener
trade.processStateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("trade state = " + newValue);
offererTrade.processStateProperty().addListener((ov, oldValue, newValue) -> {
log.debug("offererTrade state = " + newValue);
switch (newValue) {
case INIT:
break;
@ -436,12 +428,12 @@ public class TradeManager {
// persistPendingTrades();
break;
case DEPOSIT_PUBLISHED:
removeOpenOffer(trade.getOffer(),
removeOpenOffer(offererTrade.getOffer(),
() -> log.debug("remove offer was successful"),
(message) -> log.error(message),
false);
model.trade.setLifeCycleState(Trade.LifeCycleState.PENDING);
pendingTrades.add(trade);
pendingTrades.add(offererTrade);
break;
case DEPOSIT_CONFIRMED:
case FIAT_PAYMENT_STARTED:
@ -452,32 +444,16 @@ public class TradeManager {
case TAKE_OFFER_FEE_PUBLISH_FAILED:
case MESSAGE_SENDING_FAILED:
case FAULT:
trade.setLifeCycleState(Trade.LifeCycleState.FAILED);
removeFromProtocolMap(trade);
offererTrade.setLifeCycleState(Trade.LifeCycleState.FAILED);
offererTrade.disposeProtocol();
break;
default:
log.warn("Unhandled trade state: " + newValue);
log.warn("Unhandled offererTrade state: " + newValue);
break;
}
});
OffererAsBuyerProtocol protocol = new OffererAsBuyerProtocol(model);
offererAsBuyerProtocolMap.put(trade.getId(), protocol);
if (mailboxMessages.containsKey(trade.getId())) {
log.debug("OffererAsBuyerProtocol setMailboxMessage " + trade.getId());
protocol.setMailboxMessage(mailboxMessages.get(trade.getId()));
}
}
private void removeFromProtocolMap(Trade trade) {
if (takerAsSellerProtocolMap.containsKey(trade.getId())) {
takerAsSellerProtocolMap.get(trade.getId()).cleanup();
takerAsSellerProtocolMap.remove(trade.getId());
}
else if (offererAsBuyerProtocolMap.containsKey(trade.getId())) {
offererAsBuyerProtocolMap.get(trade.getId()).cleanup();
offererAsBuyerProtocolMap.remove(trade.getId());
}
return new OffererAsBuyerProtocol(model);
}
@ -493,23 +469,15 @@ public class TradeManager {
if (mailboxMessage instanceof TradeMessage) {
String tradeId = ((TradeMessage) mailboxMessage).tradeId;
mailboxMessages.put(tradeId, mailboxMessage);
log.trace("added mailboxMessage with tradeID " + tradeId);
if (takerAsSellerProtocolMap.containsKey(tradeId)) {
takerAsSellerProtocolMap.get(tradeId).setMailboxMessage(mailboxMessage);
log.trace("sellerAsTakerProtocol exist with tradeID " + tradeId);
}
if (offererAsBuyerProtocolMap.containsKey(tradeId)) {
offererAsBuyerProtocolMap.get(tradeId).setMailboxMessage(mailboxMessage);
log.trace("buyerAcceptsOfferProtocol exist with tradeID " + tradeId);
}
Optional<Trade> tradeOptional = pendingTrades.stream().filter(e -> e.getId().equals(tradeId)).findAny();
if (tradeOptional.isPresent())
tradeOptional.get().setMailboxMessage(mailboxMessage);
}
} catch (Throwable e) {
e.printStackTrace();
log.error(e.getMessage());
}
}
log.trace("mailboxMessages.size=" + mailboxMessages.size());
}
private void emptyMailbox() {

View File

@ -0,0 +1,26 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol;
import io.bitsquare.p2p.MailboxMessage;
public interface Protocol {
void cleanup();
void setMailboxMessage(MailboxMessage mailboxMessage);
}

View File

@ -71,6 +71,7 @@ public class SharedTradeModel extends SharedTaskModel implements Serializable {
id = offer.getId();
tradeWalletService = walletService.getTradeWalletService();
//TODO use default arbitrator for now
arbitratorPubKey = offer.getArbitrators().get(0).getPubKey();
}

View File

@ -24,6 +24,7 @@ import io.bitsquare.p2p.MessageHandler;
import io.bitsquare.p2p.Peer;
import io.bitsquare.p2p.listener.SendMessageListener;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.Protocol;
import io.bitsquare.trade.protocol.availability.messages.ReportOfferAvailabilityMessage;
import io.bitsquare.trade.protocol.availability.messages.RequestIsOfferAvailableMessage;
import io.bitsquare.trade.protocol.trade.messages.PayoutTxPublishedMessage;
@ -39,7 +40,6 @@ import io.bitsquare.trade.protocol.trade.offerer.tasks.ProcessRequestOffererPubl
import io.bitsquare.trade.protocol.trade.offerer.tasks.RequestTakerDepositPayment;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendBankTransferStartedMessage;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SendDepositTxToTaker;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SetupListenerForBlockChainConfirmation;
import io.bitsquare.trade.protocol.trade.offerer.tasks.SignAndPublishDepositTx;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyAndSignContract;
import io.bitsquare.trade.protocol.trade.offerer.tasks.VerifyTakeOfferFeePayment;
@ -52,7 +52,7 @@ import org.slf4j.LoggerFactory;
import static io.bitsquare.util.Validator.*;
public class OffererAsBuyerProtocol {
public class OffererAsBuyerProtocol implements Protocol {
private static final Logger log = LoggerFactory.getLogger(OffererAsBuyerProtocol.class);
private final OffererAsBuyerModel model;
@ -156,7 +156,6 @@ public class OffererAsBuyerProtocol {
VerifyTakerAccount.class,
VerifyAndSignContract.class,
SignAndPublishDepositTx.class,
SetupListenerForBlockChainConfirmation.class,
SendDepositTxToTaker.class
);
taskRunner.run();

View File

@ -1,62 +0,0 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol.trade.offerer.tasks;
import io.bitsquare.common.taskrunner.Task;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.offerer.models.OffererAsBuyerModel;
import org.bitcoinj.core.TransactionConfidence;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SetupListenerForBlockChainConfirmation extends Task<OffererAsBuyerModel> {
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
public SetupListenerForBlockChainConfirmation(TaskRunner taskHandler, OffererAsBuyerModel model) {
super(taskHandler, model);
}
@Override
protected void doRun() {
TransactionConfidence transactionConfidence = model.trade.getDepositTx().getConfidence();
ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1);
Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@Override
public void onSuccess(TransactionConfidence result) {
model.trade.setProcessState(Trade.ProcessState.DEPOSIT_CONFIRMED);
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
log.error(t.getMessage());
Throwables.propagate(t);
}
});
complete();
}
}

View File

@ -23,11 +23,11 @@ import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.MessageHandler;
import io.bitsquare.p2p.Peer;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.Protocol;
import io.bitsquare.trade.protocol.trade.messages.DepositTxPublishedMessage;
import io.bitsquare.trade.protocol.trade.messages.FiatTransferStartedMessage;
import io.bitsquare.trade.protocol.trade.messages.RequestTakerDepositPaymentMessage;
import io.bitsquare.trade.protocol.trade.messages.TradeMessage;
import io.bitsquare.trade.protocol.trade.taker.tasks.SetupListenerForBlockChainConfirmation;
import io.bitsquare.trade.protocol.trade.taker.models.TakerAsSellerModel;
import io.bitsquare.trade.protocol.trade.taker.tasks.BroadcastTakeOfferFeeTx;
import io.bitsquare.trade.protocol.trade.taker.tasks.CreateAndSignContract;
@ -49,7 +49,7 @@ import org.slf4j.LoggerFactory;
import static io.bitsquare.util.Validator.nonEmptyStringOf;
public class TakerAsSellerProtocol {
public class TakerAsSellerProtocol implements Protocol {
private static final Logger log = LoggerFactory.getLogger(TakerAsSellerProtocol.class);
private final TakerAsSellerModel model;
@ -141,8 +141,7 @@ public class TakerAsSellerProtocol {
taskRunner.addTasks(
ProcessDepositTxPublishedMessage.class,
TakerCommitDepositTx.class,
SetupListenerForBlockChainConfirmation.class
TakerCommitDepositTx.class
);
taskRunner.run();
}

View File

@ -1,62 +0,0 @@
/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.trade.protocol.trade.taker.tasks;
import io.bitsquare.common.taskrunner.Task;
import io.bitsquare.common.taskrunner.TaskRunner;
import io.bitsquare.trade.Trade;
import io.bitsquare.trade.protocol.trade.taker.models.TakerAsSellerModel;
import org.bitcoinj.core.TransactionConfidence;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SetupListenerForBlockChainConfirmation extends Task<TakerAsSellerModel> {
private static final Logger log = LoggerFactory.getLogger(SetupListenerForBlockChainConfirmation.class);
public SetupListenerForBlockChainConfirmation(TaskRunner taskHandler, TakerAsSellerModel model) {
super(taskHandler, model);
}
@Override
protected void doRun() {
TransactionConfidence transactionConfidence = model.trade.getDepositTx().getConfidence();
ListenableFuture<TransactionConfidence> future = transactionConfidence.getDepthFuture(1);
Futures.addCallback(future, new FutureCallback<TransactionConfidence>() {
@Override
public void onSuccess(TransactionConfidence result) {
model.trade.setProcessState(Trade.ProcessState.DEPOSIT_CONFIRMED);
}
@Override
public void onFailure(Throwable t) {
t.printStackTrace();
log.error(t.getMessage());
Throwables.propagate(t);
}
});
complete();
}
}